162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci// Copyright (c) 2022, Analog Devices Inc. 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#include <linux/acpi.h> 562306a36Sopenharmony_ci#include <linux/delay.h> 662306a36Sopenharmony_ci#include <linux/gpio.h> 762306a36Sopenharmony_ci#include <linux/i2c.h> 862306a36Sopenharmony_ci#include <linux/module.h> 962306a36Sopenharmony_ci#include <linux/mod_devicetable.h> 1062306a36Sopenharmony_ci#include <linux/of.h> 1162306a36Sopenharmony_ci#include <linux/of_gpio.h> 1262306a36Sopenharmony_ci#include <linux/pm_runtime.h> 1362306a36Sopenharmony_ci#include <linux/regmap.h> 1462306a36Sopenharmony_ci#include <linux/slab.h> 1562306a36Sopenharmony_ci#include <linux/cdev.h> 1662306a36Sopenharmony_ci#include <sound/pcm.h> 1762306a36Sopenharmony_ci#include <sound/pcm_params.h> 1862306a36Sopenharmony_ci#include <sound/soc.h> 1962306a36Sopenharmony_ci#include <sound/tlv.h> 2062306a36Sopenharmony_ci#include "max98388.h" 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_cistatic struct reg_default max98388_reg[] = { 2362306a36Sopenharmony_ci {MAX98388_R2000_SW_RESET, 0x00}, 2462306a36Sopenharmony_ci {MAX98388_R2001_INT_RAW1, 0x00}, 2562306a36Sopenharmony_ci {MAX98388_R2002_INT_RAW2, 0x00}, 2662306a36Sopenharmony_ci {MAX98388_R2004_INT_STATE1, 0x00}, 2762306a36Sopenharmony_ci {MAX98388_R2005_INT_STATE2, 0x00}, 2862306a36Sopenharmony_ci {MAX98388_R2020_THERM_WARN_THRESH, 0x0A}, 2962306a36Sopenharmony_ci {MAX98388_R2031_SPK_MON_THRESH, 0x58}, 3062306a36Sopenharmony_ci {MAX98388_R2032_SPK_MON_LD_SEL, 0x08}, 3162306a36Sopenharmony_ci {MAX98388_R2033_SPK_MON_DURATION, 0x02}, 3262306a36Sopenharmony_ci {MAX98388_R2037_ERR_MON_CTRL, 0x01}, 3362306a36Sopenharmony_ci {MAX98388_R2040_PCM_MODE_CFG, 0xC0}, 3462306a36Sopenharmony_ci {MAX98388_R2041_PCM_CLK_SETUP, 0x04}, 3562306a36Sopenharmony_ci {MAX98388_R2042_PCM_SR_SETUP, 0x88}, 3662306a36Sopenharmony_ci {MAX98388_R2044_PCM_TX_CTRL1, 0x00}, 3762306a36Sopenharmony_ci {MAX98388_R2045_PCM_TX_CTRL2, 0x00}, 3862306a36Sopenharmony_ci {MAX98388_R2050_PCM_TX_HIZ_CTRL1, 0xFF}, 3962306a36Sopenharmony_ci {MAX98388_R2051_PCM_TX_HIZ_CTRL2, 0xFF}, 4062306a36Sopenharmony_ci {MAX98388_R2052_PCM_TX_HIZ_CTRL3, 0xFF}, 4162306a36Sopenharmony_ci {MAX98388_R2053_PCM_TX_HIZ_CTRL4, 0xFF}, 4262306a36Sopenharmony_ci {MAX98388_R2054_PCM_TX_HIZ_CTRL5, 0xFF}, 4362306a36Sopenharmony_ci {MAX98388_R2055_PCM_TX_HIZ_CTRL6, 0xFF}, 4462306a36Sopenharmony_ci {MAX98388_R2056_PCM_TX_HIZ_CTRL7, 0xFF}, 4562306a36Sopenharmony_ci {MAX98388_R2057_PCM_TX_HIZ_CTRL8, 0xFF}, 4662306a36Sopenharmony_ci {MAX98388_R2058_PCM_RX_SRC1, 0x00}, 4762306a36Sopenharmony_ci {MAX98388_R2059_PCM_RX_SRC2, 0x01}, 4862306a36Sopenharmony_ci {MAX98388_R205C_PCM_TX_DRIVE_STRENGTH, 0x00}, 4962306a36Sopenharmony_ci {MAX98388_R205D_PCM_TX_SRC_EN, 0x00}, 5062306a36Sopenharmony_ci {MAX98388_R205E_PCM_RX_EN, 0x00}, 5162306a36Sopenharmony_ci {MAX98388_R205F_PCM_TX_EN, 0x00}, 5262306a36Sopenharmony_ci {MAX98388_R2090_SPK_CH_VOL_CTRL, 0x00}, 5362306a36Sopenharmony_ci {MAX98388_R2091_SPK_CH_CFG, 0x02}, 5462306a36Sopenharmony_ci {MAX98388_R2092_SPK_AMP_OUT_CFG, 0x03}, 5562306a36Sopenharmony_ci {MAX98388_R2093_SPK_AMP_SSM_CFG, 0x01}, 5662306a36Sopenharmony_ci {MAX98388_R2094_SPK_AMP_ER_CTRL, 0x00}, 5762306a36Sopenharmony_ci {MAX98388_R209E_SPK_CH_PINK_NOISE_EN, 0x00}, 5862306a36Sopenharmony_ci {MAX98388_R209F_SPK_CH_AMP_EN, 0x00}, 5962306a36Sopenharmony_ci {MAX98388_R20A0_IV_DATA_DSP_CTRL, 0x10}, 6062306a36Sopenharmony_ci {MAX98388_R20A7_IV_DATA_EN, 0x00}, 6162306a36Sopenharmony_ci {MAX98388_R20E0_BP_ALC_THRESH, 0x04}, 6262306a36Sopenharmony_ci {MAX98388_R20E1_BP_ALC_RATES, 0x20}, 6362306a36Sopenharmony_ci {MAX98388_R20E2_BP_ALC_ATTEN, 0x06}, 6462306a36Sopenharmony_ci {MAX98388_R20E3_BP_ALC_REL, 0x02}, 6562306a36Sopenharmony_ci {MAX98388_R20E4_BP_ALC_MUTE, 0x33}, 6662306a36Sopenharmony_ci {MAX98388_R20EE_BP_INF_HOLD_REL, 0x00}, 6762306a36Sopenharmony_ci {MAX98388_R20EF_BP_ALC_EN, 0x00}, 6862306a36Sopenharmony_ci {MAX98388_R210E_AUTO_RESTART, 0x00}, 6962306a36Sopenharmony_ci {MAX98388_R210F_GLOBAL_EN, 0x00}, 7062306a36Sopenharmony_ci {MAX98388_R22FF_REV_ID, 0x00}, 7162306a36Sopenharmony_ci}; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_cistatic int max98388_dac_event(struct snd_soc_dapm_widget *w, 7462306a36Sopenharmony_ci struct snd_kcontrol *kcontrol, int event) 7562306a36Sopenharmony_ci{ 7662306a36Sopenharmony_ci struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 7762306a36Sopenharmony_ci struct max98388_priv *max98388 = snd_soc_component_get_drvdata(component); 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci switch (event) { 8062306a36Sopenharmony_ci case SND_SOC_DAPM_POST_PMU: 8162306a36Sopenharmony_ci regmap_write(max98388->regmap, 8262306a36Sopenharmony_ci MAX98388_R210F_GLOBAL_EN, 1); 8362306a36Sopenharmony_ci usleep_range(30000, 31000); 8462306a36Sopenharmony_ci break; 8562306a36Sopenharmony_ci case SND_SOC_DAPM_PRE_PMD: 8662306a36Sopenharmony_ci regmap_write(max98388->regmap, 8762306a36Sopenharmony_ci MAX98388_R210F_GLOBAL_EN, 0); 8862306a36Sopenharmony_ci usleep_range(30000, 31000); 8962306a36Sopenharmony_ci max98388->tdm_mode = false; 9062306a36Sopenharmony_ci break; 9162306a36Sopenharmony_ci default: 9262306a36Sopenharmony_ci return 0; 9362306a36Sopenharmony_ci } 9462306a36Sopenharmony_ci return 0; 9562306a36Sopenharmony_ci} 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_cistatic const char * const max98388_monomix_switch_text[] = { 9862306a36Sopenharmony_ci "Left", "Right", "LeftRight"}; 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_cistatic const struct soc_enum dai_sel_enum = 10162306a36Sopenharmony_ci SOC_ENUM_SINGLE(MAX98388_R2058_PCM_RX_SRC1, 10262306a36Sopenharmony_ci MAX98388_PCM_TO_SPK_MONOMIX_CFG_SHIFT, 10362306a36Sopenharmony_ci 3, max98388_monomix_switch_text); 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_cistatic const struct snd_kcontrol_new max98388_dai_controls = 10662306a36Sopenharmony_ci SOC_DAPM_ENUM("DAI Sel", dai_sel_enum); 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_cistatic const struct snd_kcontrol_new max98388_vi_control = 10962306a36Sopenharmony_ci SOC_DAPM_SINGLE("Switch", MAX98388_R205F_PCM_TX_EN, 0, 1, 0); 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_cistatic const struct snd_soc_dapm_widget max98388_dapm_widgets[] = { 11262306a36Sopenharmony_ci SND_SOC_DAPM_DAC_E("Amp Enable", "HiFi Playback", 11362306a36Sopenharmony_ci MAX98388_R205E_PCM_RX_EN, 0, 0, max98388_dac_event, 11462306a36Sopenharmony_ci SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), 11562306a36Sopenharmony_ci SND_SOC_DAPM_MUX("DAI Sel Mux", SND_SOC_NOPM, 0, 0, 11662306a36Sopenharmony_ci &max98388_dai_controls), 11762306a36Sopenharmony_ci SND_SOC_DAPM_OUTPUT("BE_OUT"), 11862306a36Sopenharmony_ci SND_SOC_DAPM_AIF_OUT("Voltage Sense", "HiFi Capture", 0, 11962306a36Sopenharmony_ci MAX98388_R20A7_IV_DATA_EN, 0, 0), 12062306a36Sopenharmony_ci SND_SOC_DAPM_AIF_OUT("Current Sense", "HiFi Capture", 0, 12162306a36Sopenharmony_ci MAX98388_R20A7_IV_DATA_EN, 1, 0), 12262306a36Sopenharmony_ci SND_SOC_DAPM_ADC("ADC Voltage", NULL, 12362306a36Sopenharmony_ci MAX98388_R205D_PCM_TX_SRC_EN, 0, 0), 12462306a36Sopenharmony_ci SND_SOC_DAPM_ADC("ADC Current", NULL, 12562306a36Sopenharmony_ci MAX98388_R205D_PCM_TX_SRC_EN, 1, 0), 12662306a36Sopenharmony_ci SND_SOC_DAPM_SWITCH("VI Sense", SND_SOC_NOPM, 0, 0, 12762306a36Sopenharmony_ci &max98388_vi_control), 12862306a36Sopenharmony_ci SND_SOC_DAPM_SIGGEN("VMON"), 12962306a36Sopenharmony_ci SND_SOC_DAPM_SIGGEN("IMON"), 13062306a36Sopenharmony_ci}; 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_cistatic DECLARE_TLV_DB_SCALE(max98388_digital_tlv, -6350, 50, 1); 13362306a36Sopenharmony_cistatic DECLARE_TLV_DB_SCALE(max98388_amp_gain_tlv, -300, 300, 0); 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_cistatic const char * const max98388_alc_max_atten_text[] = { 13662306a36Sopenharmony_ci "0dBFS", "-1dBFS", "-2dBFS", "-3dBFS", "-4dBFS", "-5dBFS", 13762306a36Sopenharmony_ci "-6dBFS", "-7dBFS", "-8dBFS", "-9dBFS", "-10dBFS", "-11dBFS", 13862306a36Sopenharmony_ci "-12dBFS", "-13dBFS", "-14dBFS", "-15dBFS" 13962306a36Sopenharmony_ci}; 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(max98388_alc_max_atten_enum, 14262306a36Sopenharmony_ci MAX98388_R20E2_BP_ALC_ATTEN, 14362306a36Sopenharmony_ci MAX98388_ALC_MAX_ATTEN_SHIFT, 14462306a36Sopenharmony_ci max98388_alc_max_atten_text); 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_cistatic const char * const max98388_thermal_warn_text[] = { 14762306a36Sopenharmony_ci "95C", "105C", "115C", "125C" 14862306a36Sopenharmony_ci}; 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(max98388_thermal_warning_thresh_enum, 15162306a36Sopenharmony_ci MAX98388_R2020_THERM_WARN_THRESH, 15262306a36Sopenharmony_ci MAX98388_THERM_WARN_THRESH_SHIFT, 15362306a36Sopenharmony_ci max98388_thermal_warn_text); 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_cistatic const char * const max98388_thermal_shutdown_text[] = { 15662306a36Sopenharmony_ci "135C", "145C", "155C", "165C" 15762306a36Sopenharmony_ci}; 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(max98388_thermal_shutdown_thresh_enum, 16062306a36Sopenharmony_ci MAX98388_R2020_THERM_WARN_THRESH, 16162306a36Sopenharmony_ci MAX98388_THERM_SHDN_THRESH_SHIFT, 16262306a36Sopenharmony_ci max98388_thermal_shutdown_text); 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_cistatic const char * const max98388_alc_thresh_single_text[] = { 16562306a36Sopenharmony_ci "3.625V", "3.550V", "3.475V", "3.400V", "3.325V", "3.250V", 16662306a36Sopenharmony_ci "3.175V", "3.100V", "3.025V", "2.950V", "2.875V", "2.800V", 16762306a36Sopenharmony_ci "2.725V", "2.650V", "2.575V", "2.500V" 16862306a36Sopenharmony_ci}; 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(max98388_alc_thresh_single_enum, 17162306a36Sopenharmony_ci MAX98388_R20E0_BP_ALC_THRESH, 17262306a36Sopenharmony_ci MAX98388_ALC_THRESH_SHIFT, 17362306a36Sopenharmony_ci max98388_alc_thresh_single_text); 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_cistatic const char * const max98388_alc_attack_rate_text[] = { 17662306a36Sopenharmony_ci "0", "10us", "20us", "40us", "80us", "160us", 17762306a36Sopenharmony_ci "320us", "640us", "1.28ms", "2.56ms", "5.12ms", "10.24ms", 17862306a36Sopenharmony_ci "20.48ms", "40.96ms", "81.92ms", "163.84ms" 17962306a36Sopenharmony_ci}; 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(max98388_alc_attack_rate_enum, 18262306a36Sopenharmony_ci MAX98388_R20E1_BP_ALC_RATES, 18362306a36Sopenharmony_ci MAX98388_ALC_ATTACK_RATE_SHIFT, 18462306a36Sopenharmony_ci max98388_alc_attack_rate_text); 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_cistatic const char * const max98388_alc_release_rate_text[] = { 18762306a36Sopenharmony_ci "20us", "40us", "80us", "160us", "320us", "640us", 18862306a36Sopenharmony_ci "1.28ms", "2.56ms", "5.12ms", "10.24ms", "20.48ms", "40.96ms", 18962306a36Sopenharmony_ci "81.92ms", "163.84ms", "327.68ms", "655.36ms" 19062306a36Sopenharmony_ci}; 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(max98388_alc_release_rate_enum, 19362306a36Sopenharmony_ci MAX98388_R20E1_BP_ALC_RATES, 19462306a36Sopenharmony_ci MAX98388_ALC_RELEASE_RATE_SHIFT, 19562306a36Sopenharmony_ci max98388_alc_release_rate_text); 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_cistatic const char * const max98388_alc_debounce_text[] = { 19862306a36Sopenharmony_ci "0.01ms", "0.1ms", "1ms", "10ms", "100ms", "250ms", "500ms", "hold" 19962306a36Sopenharmony_ci}; 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(max98388_alc_debouce_enum, 20262306a36Sopenharmony_ci MAX98388_R20E3_BP_ALC_REL, 20362306a36Sopenharmony_ci MAX98388_ALC_DEBOUNCE_TIME_SHIFT, 20462306a36Sopenharmony_ci max98388_alc_debounce_text); 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_cistatic const char * const max98388_alc_mute_delay_text[] = { 20762306a36Sopenharmony_ci "0.01ms", "0.05ms", "0.1ms", "0.5ms", "1ms", "5ms", "25ms", "250ms" 20862306a36Sopenharmony_ci}; 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(max98388_alc_mute_delay_enum, 21162306a36Sopenharmony_ci MAX98388_R20E4_BP_ALC_MUTE, 21262306a36Sopenharmony_ci MAX98388_ALC_MUTE_DELAY_SHIFT, 21362306a36Sopenharmony_ci max98388_alc_mute_delay_text); 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_cistatic const char * const max98388_spkmon_duration_text[] = { 21662306a36Sopenharmony_ci "10ms", "25ms", "50ms", "75ms", "100ms", "200ms", "300ms", "400ms", 21762306a36Sopenharmony_ci "500ms", "600ms", "700ms", "800ms", "900ms", "1000ms", "1100ms", "1200ms" 21862306a36Sopenharmony_ci}; 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(max98388_spkmon_duration_enum, 22162306a36Sopenharmony_ci MAX98388_R2033_SPK_MON_DURATION, 22262306a36Sopenharmony_ci MAX98388_SPKMON_DURATION_SHIFT, 22362306a36Sopenharmony_ci max98388_spkmon_duration_text); 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_cistatic const char * const max98388_spkmon_thresh_text[] = { 22662306a36Sopenharmony_ci "0.03V", "0.06V", "0.09V", "0.12V", "0.15V", "0.18V", "0.20V", "0.23V", 22762306a36Sopenharmony_ci "0.26V", "0.29V", "0.32V", "0.35V", "0.38V", "0.41V", "0.44V", "0.47V", 22862306a36Sopenharmony_ci "0.50V", "0.53V", "0.56V", "0.58V", "0.61V", "0.64V", "0.67V", "0.70V", 22962306a36Sopenharmony_ci "0.73V", "0.76V", "0.79V", "0.82V", "0.85V", "0.88V", "0.91V", "0.94V", 23062306a36Sopenharmony_ci "0.96V", "0.99V", "1.02V", "1.05V", "1.08V", "1.11V", "1.14V", "1.17V", 23162306a36Sopenharmony_ci "1.20V", "1.23V", "1.26V", "1.29V", "1.32V", "1.35V", "1.37V", "1.40V", 23262306a36Sopenharmony_ci "1.43V", "1.46V", "1.49V", "1.52V", "1.55V", "1.58V", "1.61V", "1.64V", 23362306a36Sopenharmony_ci "1.67V", "1.70V", "1.73V", "1.75V", "1.78V", "1.81V", "1.84V", "1.87V", 23462306a36Sopenharmony_ci "1.90V", "1.93V", "1.96V", "1.99V", "2.02V", "2.05V", "2.08V", "2.11V", 23562306a36Sopenharmony_ci "2.13V", "2.16V", "2.19V", "2.22V", "2.25V", "2.28V", "2.31V", "2.34V", 23662306a36Sopenharmony_ci "2.37V", "2.40V", "2.43V", "2.46V", "2.49V", "2.51V", "2.54V", "2.57V", 23762306a36Sopenharmony_ci "2.60V", "2.63V", "2.66V", "2.69V", "2.72V", "2.75V", "2.78V", "2.81V", 23862306a36Sopenharmony_ci "2.84V", "2.87V", "2.89V", "2.92V", "2.95V", "2.98V", "3.01V", "3.04V", 23962306a36Sopenharmony_ci "3.07V", "3.10V", "3.13V", "3.16V", "3.19V", "3.22V", "3.25V", "3.27V", 24062306a36Sopenharmony_ci "3.30V", "3.33V", "3.36V", "3.39V", "3.42V", "3.45V", "3.48V", "3.51V", 24162306a36Sopenharmony_ci "3.54V", "3.57V", "3.60V", "3.63V", "3.66V", "3.68V", "3.71V", "3.74V" 24262306a36Sopenharmony_ci}; 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(max98388_spkmon_thresh_enum, 24562306a36Sopenharmony_ci MAX98388_R2031_SPK_MON_THRESH, 24662306a36Sopenharmony_ci MAX98388_SPKMON_THRESH_SHIFT, 24762306a36Sopenharmony_ci max98388_spkmon_thresh_text); 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_cistatic const char * const max98388_spkmon_load_text[] = { 25062306a36Sopenharmony_ci "2.00ohm", "2.25ohm", "2.50ohm", "2.75ohm", "3.00ohm", "3.25ohm", 25162306a36Sopenharmony_ci "3.50ohm", "3.75ohm", "4.00ohm", "4.25ohm", "4.50ohm", "4.75ohm", 25262306a36Sopenharmony_ci "5.00ohm", "5.25ohm", "5.50ohm", "5.75ohm", "6.00ohm", "6.25ohm", 25362306a36Sopenharmony_ci "6.50ohm", "6.75ohm", "7.00ohm", "7.25ohm", "7.50ohm", "7.75ohm", 25462306a36Sopenharmony_ci "8.00ohm", "8.25ohm", "8.50ohm", "8.75ohm", "9.00ohm", "9.25ohm", 25562306a36Sopenharmony_ci "9.50ohm", "9.75ohm", "10.00ohm", "10.25ohm", "10.50ohm", "10.75ohm", 25662306a36Sopenharmony_ci "11.00ohm", "11.25ohm", "11.50ohm", "11.75ohm", "12.00ohm", "12.25ohm", 25762306a36Sopenharmony_ci "12.50ohm", "12.75ohm", "13.00ohm", "13.25ohm", "13.50ohm", "13.75ohm", 25862306a36Sopenharmony_ci "14.00ohm", "14.25ohm", "14.50ohm", "14.75ohm", "15.00ohm", "15.25ohm", 25962306a36Sopenharmony_ci "15.50ohm", "15.75ohm", "16.00ohm", "16.25ohm", "16.50ohm", "16.75ohm", 26062306a36Sopenharmony_ci "17.00ohm", "17.25ohm", "17.50ohm", "17.75ohm", "18.00ohm", "18.25ohm", 26162306a36Sopenharmony_ci "18.50ohm", "18.75ohm", "19.00ohm", "19.25ohm", "19.50ohm", "19.75ohm", 26262306a36Sopenharmony_ci "20.00ohm", "20.25ohm", "20.50ohm", "20.75ohm", "21.00ohm", "21.25ohm", 26362306a36Sopenharmony_ci "21.50ohm", "21.75ohm", "22.00ohm", "22.25ohm", "22.50ohm", "22.75ohm", 26462306a36Sopenharmony_ci "23.00ohm", "23.25ohm", "23.50ohm", "23.75ohm", "24.00ohm", "24.25ohm", 26562306a36Sopenharmony_ci "24.50ohm", "24.75ohm", "25.00ohm", "25.25ohm", "25.50ohm", "25.75ohm", 26662306a36Sopenharmony_ci "26.00ohm", "26.25ohm", "26.50ohm", "26.75ohm", "27.00ohm", "27.25ohm", 26762306a36Sopenharmony_ci "27.50ohm", "27.75ohm", "28.00ohm", "28.25ohm", "28.50ohm", "28.75ohm", 26862306a36Sopenharmony_ci "29.00ohm", "29.25ohm", "29.50ohm", "29.75ohm", "30.00ohm", "30.25ohm", 26962306a36Sopenharmony_ci "30.50ohm", "30.75ohm", "31.00ohm", "31.25ohm", "31.50ohm", "31.75ohm", 27062306a36Sopenharmony_ci "32.00ohm", "32.25ohm", "32.50ohm", "32.75ohm", "33.00ohm", "33.25ohm", 27162306a36Sopenharmony_ci "33.50ohm", "33.75ohm" 27262306a36Sopenharmony_ci}; 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(max98388_spkmon_load_enum, 27562306a36Sopenharmony_ci MAX98388_R2032_SPK_MON_LD_SEL, 27662306a36Sopenharmony_ci MAX98388_SPKMON_LOAD_SHIFT, 27762306a36Sopenharmony_ci max98388_spkmon_load_text); 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_cistatic const char * const max98388_edge_rate_text[] = { 28062306a36Sopenharmony_ci "Normal", "Reduced", "Maximum", "Increased", 28162306a36Sopenharmony_ci}; 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(max98388_edge_rate_falling_enum, 28462306a36Sopenharmony_ci MAX98388_R2094_SPK_AMP_ER_CTRL, 28562306a36Sopenharmony_ci MAX98388_EDGE_RATE_FALL_SHIFT, 28662306a36Sopenharmony_ci max98388_edge_rate_text); 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(max98388_edge_rate_rising_enum, 28962306a36Sopenharmony_ci MAX98388_R2094_SPK_AMP_ER_CTRL, 29062306a36Sopenharmony_ci MAX98388_EDGE_RATE_RISE_SHIFT, 29162306a36Sopenharmony_ci max98388_edge_rate_text); 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_cistatic const char * const max98388_ssm_mod_text[] = { 29462306a36Sopenharmony_ci "1.5%", "3.0%", "4.5%", "6.0%", 29562306a36Sopenharmony_ci}; 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(max98388_ssm_mod_enum, 29862306a36Sopenharmony_ci MAX98388_R2093_SPK_AMP_SSM_CFG, 29962306a36Sopenharmony_ci MAX98388_SPK_AMP_SSM_MOD_SHIFT, 30062306a36Sopenharmony_ci max98388_ssm_mod_text); 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_cistatic const struct snd_kcontrol_new max98388_snd_controls[] = { 30362306a36Sopenharmony_ci SOC_SINGLE("Ramp Up Switch", MAX98388_R2091_SPK_CH_CFG, 30462306a36Sopenharmony_ci MAX98388_SPK_CFG_VOL_RMPUP_SHIFT, 1, 0), 30562306a36Sopenharmony_ci SOC_SINGLE("Ramp Down Switch", MAX98388_R2091_SPK_CH_CFG, 30662306a36Sopenharmony_ci MAX98388_SPK_CFG_VOL_RMPDN_SHIFT, 1, 0), 30762306a36Sopenharmony_ci /* Two Cell Mode Enable */ 30862306a36Sopenharmony_ci SOC_SINGLE("OP Mode Switch", MAX98388_R2092_SPK_AMP_OUT_CFG, 30962306a36Sopenharmony_ci MAX98388_SPK_AMP_OUT_MODE_SHIFT, 1, 0), 31062306a36Sopenharmony_ci /* Speaker Amplifier Overcurrent Automatic Restart Enable */ 31162306a36Sopenharmony_ci SOC_SINGLE("OVC Autorestart Switch", MAX98388_R210E_AUTO_RESTART, 31262306a36Sopenharmony_ci MAX98388_OVC_AUTORESTART_SHIFT, 1, 0), 31362306a36Sopenharmony_ci /* Thermal Shutdown Automatic Restart Enable */ 31462306a36Sopenharmony_ci SOC_SINGLE("THERM Autorestart Switch", MAX98388_R210E_AUTO_RESTART, 31562306a36Sopenharmony_ci MAX98388_THERM_AUTORESTART_SHIFT, 1, 0), 31662306a36Sopenharmony_ci /* PVDD UVLO Auto Restart */ 31762306a36Sopenharmony_ci SOC_SINGLE("UVLO Autorestart Switch", MAX98388_R210E_AUTO_RESTART, 31862306a36Sopenharmony_ci MAX98388_PVDD_UVLO_AUTORESTART_SHIFT, 1, 0), 31962306a36Sopenharmony_ci /* Clock Monitor Automatic Restart Enable */ 32062306a36Sopenharmony_ci SOC_SINGLE("CMON Autorestart Switch", MAX98388_R210E_AUTO_RESTART, 32162306a36Sopenharmony_ci MAX98388_CMON_AUTORESTART_SHIFT, 1, 0), 32262306a36Sopenharmony_ci SOC_SINGLE("CLK Monitor Switch", MAX98388_R2037_ERR_MON_CTRL, 32362306a36Sopenharmony_ci MAX98388_CLOCK_MON_SHIFT, 1, 0), 32462306a36Sopenharmony_ci /* Pinknoise Generator Enable */ 32562306a36Sopenharmony_ci SOC_SINGLE("Pinknoise Gen Switch", MAX98388_R209E_SPK_CH_PINK_NOISE_EN, 32662306a36Sopenharmony_ci MAX98388_PINK_NOISE_GEN_SHIFT, 1, 0), 32762306a36Sopenharmony_ci /* Dither Enable */ 32862306a36Sopenharmony_ci SOC_SINGLE("Dither Switch", MAX98388_R2091_SPK_CH_CFG, 32962306a36Sopenharmony_ci MAX98388_SPK_CFG_DITH_EN_SHIFT, 1, 0), 33062306a36Sopenharmony_ci SOC_SINGLE("VI Dither Switch", MAX98388_R20A0_IV_DATA_DSP_CTRL, 33162306a36Sopenharmony_ci MAX98388_AMP_DSP_CTRL_DITH_SHIFT, 1, 0), 33262306a36Sopenharmony_ci /* DC Blocker Enable */ 33362306a36Sopenharmony_ci SOC_SINGLE("DC Blocker Switch", MAX98388_R2091_SPK_CH_CFG, 33462306a36Sopenharmony_ci MAX98388_SPK_CFG_DCBLK_SHIFT, 1, 0), 33562306a36Sopenharmony_ci SOC_SINGLE("Voltage DC Blocker Switch", MAX98388_R20A0_IV_DATA_DSP_CTRL, 33662306a36Sopenharmony_ci MAX98388_AMP_DSP_CTRL_VOL_DCBLK_SHIFT, 1, 0), 33762306a36Sopenharmony_ci SOC_SINGLE("Current DC Blocker Switch", MAX98388_R20A0_IV_DATA_DSP_CTRL, 33862306a36Sopenharmony_ci MAX98388_AMP_DSP_CTRL_CUR_DCBLK_SHIFT, 1, 0), 33962306a36Sopenharmony_ci /* Digital Volume */ 34062306a36Sopenharmony_ci SOC_SINGLE_TLV("Digital Volume", MAX98388_R2090_SPK_CH_VOL_CTRL, 34162306a36Sopenharmony_ci 0, 0x7F, 1, max98388_digital_tlv), 34262306a36Sopenharmony_ci /* Speaker Volume */ 34362306a36Sopenharmony_ci SOC_SINGLE_TLV("Speaker Volume", MAX98388_R2092_SPK_AMP_OUT_CFG, 34462306a36Sopenharmony_ci 0, 5, 0, max98388_amp_gain_tlv), 34562306a36Sopenharmony_ci SOC_ENUM("Thermal Warn Thresh", max98388_thermal_warning_thresh_enum), 34662306a36Sopenharmony_ci SOC_ENUM("Thermal SHDN Thresh", max98388_thermal_shutdown_thresh_enum), 34762306a36Sopenharmony_ci /* Brownout Protection Automatic Level Control */ 34862306a36Sopenharmony_ci SOC_SINGLE("ALC Switch", MAX98388_R20EF_BP_ALC_EN, 0, 1, 0), 34962306a36Sopenharmony_ci SOC_ENUM("ALC Thresh", max98388_alc_thresh_single_enum), 35062306a36Sopenharmony_ci SOC_ENUM("ALC Attack Rate", max98388_alc_attack_rate_enum), 35162306a36Sopenharmony_ci SOC_ENUM("ALC Release Rate", max98388_alc_release_rate_enum), 35262306a36Sopenharmony_ci SOC_ENUM("ALC Max Atten", max98388_alc_max_atten_enum), 35362306a36Sopenharmony_ci SOC_ENUM("ALC Debounce Time", max98388_alc_debouce_enum), 35462306a36Sopenharmony_ci SOC_SINGLE("ALC Unmute Ramp Switch", MAX98388_R20E4_BP_ALC_MUTE, 35562306a36Sopenharmony_ci MAX98388_ALC_UNMUTE_RAMP_EN_SHIFT, 1, 0), 35662306a36Sopenharmony_ci SOC_SINGLE("ALC Mute Ramp Switch", MAX98388_R20E4_BP_ALC_MUTE, 35762306a36Sopenharmony_ci MAX98388_ALC_MUTE_RAMP_EN_SHIFT, 1, 0), 35862306a36Sopenharmony_ci SOC_SINGLE("ALC Mute Switch", MAX98388_R20E4_BP_ALC_MUTE, 35962306a36Sopenharmony_ci MAX98388_ALC_MUTE_EN_SHIFT, 1, 0), 36062306a36Sopenharmony_ci SOC_ENUM("ALC Mute Delay", max98388_alc_mute_delay_enum), 36162306a36Sopenharmony_ci /* Speaker Monitor */ 36262306a36Sopenharmony_ci SOC_SINGLE("SPKMON Switch", MAX98388_R2037_ERR_MON_CTRL, 36362306a36Sopenharmony_ci MAX98388_SPK_MON_SHIFT, 1, 0), 36462306a36Sopenharmony_ci SOC_ENUM("SPKMON Thresh", max98388_spkmon_thresh_enum), 36562306a36Sopenharmony_ci SOC_ENUM("SPKMON Load", max98388_spkmon_load_enum), 36662306a36Sopenharmony_ci SOC_ENUM("SPKMON Duration", max98388_spkmon_duration_enum), 36762306a36Sopenharmony_ci /* General Parameters */ 36862306a36Sopenharmony_ci SOC_ENUM("Fall Slew Rate", max98388_edge_rate_falling_enum), 36962306a36Sopenharmony_ci SOC_ENUM("Rise Slew Rate", max98388_edge_rate_rising_enum), 37062306a36Sopenharmony_ci SOC_SINGLE("AMP SSM Switch", MAX98388_R2093_SPK_AMP_SSM_CFG, 37162306a36Sopenharmony_ci MAX98388_SPK_AMP_SSM_EN_SHIFT, 1, 0), 37262306a36Sopenharmony_ci SOC_ENUM("AMP SSM Mod", max98388_ssm_mod_enum), 37362306a36Sopenharmony_ci}; 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_cistatic const struct snd_soc_dapm_route max98388_audio_map[] = { 37662306a36Sopenharmony_ci /* Plabyack */ 37762306a36Sopenharmony_ci {"DAI Sel Mux", "Left", "Amp Enable"}, 37862306a36Sopenharmony_ci {"DAI Sel Mux", "Right", "Amp Enable"}, 37962306a36Sopenharmony_ci {"DAI Sel Mux", "LeftRight", "Amp Enable"}, 38062306a36Sopenharmony_ci {"BE_OUT", NULL, "DAI Sel Mux"}, 38162306a36Sopenharmony_ci /* Capture */ 38262306a36Sopenharmony_ci { "ADC Voltage", NULL, "VMON"}, 38362306a36Sopenharmony_ci { "ADC Current", NULL, "IMON"}, 38462306a36Sopenharmony_ci { "VI Sense", "Switch", "ADC Voltage"}, 38562306a36Sopenharmony_ci { "VI Sense", "Switch", "ADC Current"}, 38662306a36Sopenharmony_ci { "Voltage Sense", NULL, "VI Sense"}, 38762306a36Sopenharmony_ci { "Current Sense", NULL, "VI Sense"}, 38862306a36Sopenharmony_ci}; 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_cistatic void max98388_reset(struct max98388_priv *max98388, struct device *dev) 39162306a36Sopenharmony_ci{ 39262306a36Sopenharmony_ci int ret, reg, count; 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci /* Software Reset */ 39562306a36Sopenharmony_ci ret = regmap_update_bits(max98388->regmap, 39662306a36Sopenharmony_ci MAX98388_R2000_SW_RESET, 39762306a36Sopenharmony_ci MAX98388_SOFT_RESET, 39862306a36Sopenharmony_ci MAX98388_SOFT_RESET); 39962306a36Sopenharmony_ci if (ret) 40062306a36Sopenharmony_ci dev_err(dev, "Reset command failed. (ret:%d)\n", ret); 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_ci count = 0; 40362306a36Sopenharmony_ci while (count < 3) { 40462306a36Sopenharmony_ci usleep_range(10000, 11000); 40562306a36Sopenharmony_ci /* Software Reset Verification */ 40662306a36Sopenharmony_ci ret = regmap_read(max98388->regmap, 40762306a36Sopenharmony_ci MAX98388_R22FF_REV_ID, ®); 40862306a36Sopenharmony_ci if (!ret) { 40962306a36Sopenharmony_ci dev_info(dev, "Reset completed (retry:%d)\n", count); 41062306a36Sopenharmony_ci return; 41162306a36Sopenharmony_ci } 41262306a36Sopenharmony_ci count++; 41362306a36Sopenharmony_ci } 41462306a36Sopenharmony_ci dev_err(dev, "Reset failed. (ret:%d)\n", ret); 41562306a36Sopenharmony_ci} 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_cistatic int max98388_probe(struct snd_soc_component *component) 41862306a36Sopenharmony_ci{ 41962306a36Sopenharmony_ci struct max98388_priv *max98388 = snd_soc_component_get_drvdata(component); 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_ci /* Software Reset */ 42262306a36Sopenharmony_ci max98388_reset(max98388, component->dev); 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci /* General channel source configuration */ 42562306a36Sopenharmony_ci regmap_write(max98388->regmap, 42662306a36Sopenharmony_ci MAX98388_R2059_PCM_RX_SRC2, 42762306a36Sopenharmony_ci 0x10); 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci /* Enable DC blocker */ 43062306a36Sopenharmony_ci regmap_write(max98388->regmap, 43162306a36Sopenharmony_ci MAX98388_R2091_SPK_CH_CFG, 43262306a36Sopenharmony_ci 0x1); 43362306a36Sopenharmony_ci /* Enable IMON VMON DC blocker */ 43462306a36Sopenharmony_ci regmap_write(max98388->regmap, 43562306a36Sopenharmony_ci MAX98388_R20A0_IV_DATA_DSP_CTRL, 43662306a36Sopenharmony_ci 0x3); 43762306a36Sopenharmony_ci /* TX slot configuration */ 43862306a36Sopenharmony_ci regmap_write(max98388->regmap, 43962306a36Sopenharmony_ci MAX98388_R2044_PCM_TX_CTRL1, 44062306a36Sopenharmony_ci max98388->v_slot); 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_ci regmap_write(max98388->regmap, 44362306a36Sopenharmony_ci MAX98388_R2045_PCM_TX_CTRL2, 44462306a36Sopenharmony_ci max98388->i_slot); 44562306a36Sopenharmony_ci /* Enable Auto-restart behavior by default */ 44662306a36Sopenharmony_ci regmap_write(max98388->regmap, 44762306a36Sopenharmony_ci MAX98388_R210E_AUTO_RESTART, 0xF); 44862306a36Sopenharmony_ci /* Set interleave mode */ 44962306a36Sopenharmony_ci if (max98388->interleave_mode) 45062306a36Sopenharmony_ci regmap_update_bits(max98388->regmap, 45162306a36Sopenharmony_ci MAX98388_R2040_PCM_MODE_CFG, 45262306a36Sopenharmony_ci MAX98388_PCM_TX_CH_INTERLEAVE_MASK, 45362306a36Sopenharmony_ci MAX98388_PCM_TX_CH_INTERLEAVE_MASK); 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci /* Speaker Amplifier Channel Enable */ 45662306a36Sopenharmony_ci regmap_update_bits(max98388->regmap, 45762306a36Sopenharmony_ci MAX98388_R209F_SPK_CH_AMP_EN, 45862306a36Sopenharmony_ci MAX98388_SPK_EN_MASK, 1); 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_ci return 0; 46162306a36Sopenharmony_ci} 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_cistatic int max98388_dai_set_fmt(struct snd_soc_dai *codec_dai, 46462306a36Sopenharmony_ci unsigned int fmt) 46562306a36Sopenharmony_ci{ 46662306a36Sopenharmony_ci struct snd_soc_component *component = codec_dai->component; 46762306a36Sopenharmony_ci struct max98388_priv *max98388 = snd_soc_component_get_drvdata(component); 46862306a36Sopenharmony_ci unsigned int format = 0; 46962306a36Sopenharmony_ci unsigned int invert = 0; 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci dev_dbg(component->dev, "%s: fmt 0x%08X\n", __func__, fmt); 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 47462306a36Sopenharmony_ci case SND_SOC_DAIFMT_NB_NF: 47562306a36Sopenharmony_ci break; 47662306a36Sopenharmony_ci case SND_SOC_DAIFMT_IB_NF: 47762306a36Sopenharmony_ci invert = MAX98388_PCM_MODE_CFG_PCM_BCLKEDGE; 47862306a36Sopenharmony_ci break; 47962306a36Sopenharmony_ci default: 48062306a36Sopenharmony_ci dev_err(component->dev, "DAI invert mode unsupported\n"); 48162306a36Sopenharmony_ci return -EINVAL; 48262306a36Sopenharmony_ci } 48362306a36Sopenharmony_ci 48462306a36Sopenharmony_ci regmap_update_bits(max98388->regmap, 48562306a36Sopenharmony_ci MAX98388_R2041_PCM_CLK_SETUP, 48662306a36Sopenharmony_ci MAX98388_PCM_MODE_CFG_PCM_BCLKEDGE, 48762306a36Sopenharmony_ci invert); 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci /* interface format */ 49062306a36Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 49162306a36Sopenharmony_ci case SND_SOC_DAIFMT_I2S: 49262306a36Sopenharmony_ci format = MAX98388_PCM_FORMAT_I2S; 49362306a36Sopenharmony_ci break; 49462306a36Sopenharmony_ci case SND_SOC_DAIFMT_LEFT_J: 49562306a36Sopenharmony_ci format = MAX98388_PCM_FORMAT_LJ; 49662306a36Sopenharmony_ci break; 49762306a36Sopenharmony_ci case SND_SOC_DAIFMT_DSP_A: 49862306a36Sopenharmony_ci format = MAX98388_PCM_FORMAT_TDM_MODE1; 49962306a36Sopenharmony_ci break; 50062306a36Sopenharmony_ci case SND_SOC_DAIFMT_DSP_B: 50162306a36Sopenharmony_ci format = MAX98388_PCM_FORMAT_TDM_MODE0; 50262306a36Sopenharmony_ci break; 50362306a36Sopenharmony_ci default: 50462306a36Sopenharmony_ci return -EINVAL; 50562306a36Sopenharmony_ci } 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci regmap_update_bits(max98388->regmap, 50862306a36Sopenharmony_ci MAX98388_R2040_PCM_MODE_CFG, 50962306a36Sopenharmony_ci MAX98388_PCM_MODE_CFG_FORMAT_MASK, 51062306a36Sopenharmony_ci format << MAX98388_PCM_MODE_CFG_FORMAT_SHIFT); 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci return 0; 51362306a36Sopenharmony_ci} 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_ci/* BCLKs per LRCLK */ 51662306a36Sopenharmony_cistatic const int bclk_sel_table[] = { 51762306a36Sopenharmony_ci 32, 48, 64, 96, 128, 192, 256, 384, 512, 320, 51862306a36Sopenharmony_ci}; 51962306a36Sopenharmony_ci 52062306a36Sopenharmony_cistatic int max98388_get_bclk_sel(int bclk) 52162306a36Sopenharmony_ci{ 52262306a36Sopenharmony_ci int i; 52362306a36Sopenharmony_ci /* match BCLKs per LRCLK */ 52462306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(bclk_sel_table); i++) { 52562306a36Sopenharmony_ci if (bclk_sel_table[i] == bclk) 52662306a36Sopenharmony_ci return i + 2; 52762306a36Sopenharmony_ci } 52862306a36Sopenharmony_ci return 0; 52962306a36Sopenharmony_ci} 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_cistatic int max98388_set_clock(struct snd_soc_component *component, 53262306a36Sopenharmony_ci struct snd_pcm_hw_params *params) 53362306a36Sopenharmony_ci{ 53462306a36Sopenharmony_ci struct max98388_priv *max98388 = snd_soc_component_get_drvdata(component); 53562306a36Sopenharmony_ci /* BCLK/LRCLK ratio calculation */ 53662306a36Sopenharmony_ci int blr_clk_ratio = params_channels(params) * max98388->ch_size; 53762306a36Sopenharmony_ci int value; 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci if (!max98388->tdm_mode) { 54062306a36Sopenharmony_ci /* BCLK configuration */ 54162306a36Sopenharmony_ci value = max98388_get_bclk_sel(blr_clk_ratio); 54262306a36Sopenharmony_ci if (!value) { 54362306a36Sopenharmony_ci dev_err(component->dev, "format unsupported %d\n", 54462306a36Sopenharmony_ci params_format(params)); 54562306a36Sopenharmony_ci return -EINVAL; 54662306a36Sopenharmony_ci } 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_ci regmap_update_bits(max98388->regmap, 54962306a36Sopenharmony_ci MAX98388_R2041_PCM_CLK_SETUP, 55062306a36Sopenharmony_ci MAX98388_PCM_CLK_SETUP_BSEL_MASK, 55162306a36Sopenharmony_ci value); 55262306a36Sopenharmony_ci } 55362306a36Sopenharmony_ci return 0; 55462306a36Sopenharmony_ci} 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_cistatic int max98388_dai_hw_params(struct snd_pcm_substream *substream, 55762306a36Sopenharmony_ci struct snd_pcm_hw_params *params, 55862306a36Sopenharmony_ci struct snd_soc_dai *dai) 55962306a36Sopenharmony_ci{ 56062306a36Sopenharmony_ci struct snd_soc_component *component = dai->component; 56162306a36Sopenharmony_ci struct max98388_priv *max98388 = snd_soc_component_get_drvdata(component); 56262306a36Sopenharmony_ci unsigned int sampling_rate = 0; 56362306a36Sopenharmony_ci unsigned int chan_sz = 0; 56462306a36Sopenharmony_ci int ret, reg; 56562306a36Sopenharmony_ci int status = 0; 56662306a36Sopenharmony_ci 56762306a36Sopenharmony_ci /* pcm mode configuration */ 56862306a36Sopenharmony_ci switch (snd_pcm_format_width(params_format(params))) { 56962306a36Sopenharmony_ci case 16: 57062306a36Sopenharmony_ci chan_sz = MAX98388_PCM_MODE_CFG_CHANSZ_16; 57162306a36Sopenharmony_ci break; 57262306a36Sopenharmony_ci case 24: 57362306a36Sopenharmony_ci chan_sz = MAX98388_PCM_MODE_CFG_CHANSZ_24; 57462306a36Sopenharmony_ci break; 57562306a36Sopenharmony_ci case 32: 57662306a36Sopenharmony_ci chan_sz = MAX98388_PCM_MODE_CFG_CHANSZ_32; 57762306a36Sopenharmony_ci break; 57862306a36Sopenharmony_ci default: 57962306a36Sopenharmony_ci dev_err(component->dev, "format unsupported %d\n", 58062306a36Sopenharmony_ci params_format(params)); 58162306a36Sopenharmony_ci goto err; 58262306a36Sopenharmony_ci } 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_ci max98388->ch_size = snd_pcm_format_width(params_format(params)); 58562306a36Sopenharmony_ci 58662306a36Sopenharmony_ci ret = regmap_read(max98388->regmap, 58762306a36Sopenharmony_ci MAX98388_R2040_PCM_MODE_CFG, ®); 58862306a36Sopenharmony_ci if (ret < 0) 58962306a36Sopenharmony_ci goto err; 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_ci /* GLOBAL_EN OFF prior to the channel size re-configure */ 59262306a36Sopenharmony_ci if (chan_sz != (reg & MAX98388_PCM_MODE_CFG_CHANSZ_MASK)) { 59362306a36Sopenharmony_ci ret = regmap_read(max98388->regmap, 59462306a36Sopenharmony_ci MAX98388_R210F_GLOBAL_EN, &status); 59562306a36Sopenharmony_ci if (ret < 0) 59662306a36Sopenharmony_ci goto err; 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ci if (status) { 59962306a36Sopenharmony_ci regmap_write(max98388->regmap, 60062306a36Sopenharmony_ci MAX98388_R210F_GLOBAL_EN, 0); 60162306a36Sopenharmony_ci usleep_range(30000, 31000); 60262306a36Sopenharmony_ci } 60362306a36Sopenharmony_ci regmap_update_bits(max98388->regmap, 60462306a36Sopenharmony_ci MAX98388_R2040_PCM_MODE_CFG, 60562306a36Sopenharmony_ci MAX98388_PCM_MODE_CFG_CHANSZ_MASK, chan_sz); 60662306a36Sopenharmony_ci } 60762306a36Sopenharmony_ci dev_dbg(component->dev, "format supported %d", 60862306a36Sopenharmony_ci params_format(params)); 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci /* sampling rate configuration */ 61162306a36Sopenharmony_ci switch (params_rate(params)) { 61262306a36Sopenharmony_ci case 8000: 61362306a36Sopenharmony_ci sampling_rate = MAX98388_PCM_SR_8000; 61462306a36Sopenharmony_ci break; 61562306a36Sopenharmony_ci case 11025: 61662306a36Sopenharmony_ci sampling_rate = MAX98388_PCM_SR_11025; 61762306a36Sopenharmony_ci break; 61862306a36Sopenharmony_ci case 12000: 61962306a36Sopenharmony_ci sampling_rate = MAX98388_PCM_SR_12000; 62062306a36Sopenharmony_ci break; 62162306a36Sopenharmony_ci case 16000: 62262306a36Sopenharmony_ci sampling_rate = MAX98388_PCM_SR_16000; 62362306a36Sopenharmony_ci break; 62462306a36Sopenharmony_ci case 22050: 62562306a36Sopenharmony_ci sampling_rate = MAX98388_PCM_SR_22050; 62662306a36Sopenharmony_ci break; 62762306a36Sopenharmony_ci case 24000: 62862306a36Sopenharmony_ci sampling_rate = MAX98388_PCM_SR_24000; 62962306a36Sopenharmony_ci break; 63062306a36Sopenharmony_ci case 32000: 63162306a36Sopenharmony_ci sampling_rate = MAX98388_PCM_SR_32000; 63262306a36Sopenharmony_ci break; 63362306a36Sopenharmony_ci case 44100: 63462306a36Sopenharmony_ci sampling_rate = MAX98388_PCM_SR_44100; 63562306a36Sopenharmony_ci break; 63662306a36Sopenharmony_ci case 48000: 63762306a36Sopenharmony_ci sampling_rate = MAX98388_PCM_SR_48000; 63862306a36Sopenharmony_ci break; 63962306a36Sopenharmony_ci case 88200: 64062306a36Sopenharmony_ci sampling_rate = MAX98388_PCM_SR_88200; 64162306a36Sopenharmony_ci break; 64262306a36Sopenharmony_ci case 96000: 64362306a36Sopenharmony_ci sampling_rate = MAX98388_PCM_SR_96000; 64462306a36Sopenharmony_ci break; 64562306a36Sopenharmony_ci default: 64662306a36Sopenharmony_ci dev_err(component->dev, "rate %d not supported\n", 64762306a36Sopenharmony_ci params_rate(params)); 64862306a36Sopenharmony_ci goto err; 64962306a36Sopenharmony_ci } 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_ci /* set DAI_SR to correct LRCLK frequency */ 65262306a36Sopenharmony_ci regmap_update_bits(max98388->regmap, 65362306a36Sopenharmony_ci MAX98388_R2042_PCM_SR_SETUP, 65462306a36Sopenharmony_ci MAX98388_PCM_SR_MASK, 65562306a36Sopenharmony_ci sampling_rate); 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_ci /* set sampling rate of IV */ 65862306a36Sopenharmony_ci if (max98388->interleave_mode && 65962306a36Sopenharmony_ci sampling_rate > MAX98388_PCM_SR_16000) 66062306a36Sopenharmony_ci regmap_update_bits(max98388->regmap, 66162306a36Sopenharmony_ci MAX98388_R2042_PCM_SR_SETUP, 66262306a36Sopenharmony_ci MAX98388_PCM_SR_IV_MASK, 66362306a36Sopenharmony_ci (sampling_rate - 3) << MAX98388_PCM_SR_IV_SHIFT); 66462306a36Sopenharmony_ci else 66562306a36Sopenharmony_ci regmap_update_bits(max98388->regmap, 66662306a36Sopenharmony_ci MAX98388_R2042_PCM_SR_SETUP, 66762306a36Sopenharmony_ci MAX98388_PCM_SR_IV_MASK, 66862306a36Sopenharmony_ci sampling_rate << MAX98388_PCM_SR_IV_SHIFT); 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_ci ret = max98388_set_clock(component, params); 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ci if (status) { 67362306a36Sopenharmony_ci regmap_write(max98388->regmap, 67462306a36Sopenharmony_ci MAX98388_R210F_GLOBAL_EN, 1); 67562306a36Sopenharmony_ci usleep_range(30000, 31000); 67662306a36Sopenharmony_ci } 67762306a36Sopenharmony_ci 67862306a36Sopenharmony_ci return ret; 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_cierr: 68162306a36Sopenharmony_ci return -EINVAL; 68262306a36Sopenharmony_ci} 68362306a36Sopenharmony_ci 68462306a36Sopenharmony_ci#define MAX_NUM_SLOTS 16 68562306a36Sopenharmony_ci#define MAX_NUM_CH 2 68662306a36Sopenharmony_ci 68762306a36Sopenharmony_cistatic int max98388_dai_tdm_slot(struct snd_soc_dai *dai, 68862306a36Sopenharmony_ci unsigned int tx_mask, unsigned int rx_mask, 68962306a36Sopenharmony_ci int slots, int slot_width) 69062306a36Sopenharmony_ci{ 69162306a36Sopenharmony_ci struct snd_soc_component *component = dai->component; 69262306a36Sopenharmony_ci struct max98388_priv *max98388 = snd_soc_component_get_drvdata(component); 69362306a36Sopenharmony_ci int bsel = 0; 69462306a36Sopenharmony_ci unsigned int chan_sz = 0; 69562306a36Sopenharmony_ci unsigned int mask; 69662306a36Sopenharmony_ci int cnt, slot_found; 69762306a36Sopenharmony_ci int addr, bits; 69862306a36Sopenharmony_ci 69962306a36Sopenharmony_ci if (!tx_mask && !rx_mask && !slots && !slot_width) 70062306a36Sopenharmony_ci max98388->tdm_mode = false; 70162306a36Sopenharmony_ci else 70262306a36Sopenharmony_ci max98388->tdm_mode = true; 70362306a36Sopenharmony_ci 70462306a36Sopenharmony_ci /* BCLK configuration */ 70562306a36Sopenharmony_ci bsel = max98388_get_bclk_sel(slots * slot_width); 70662306a36Sopenharmony_ci if (bsel == 0) { 70762306a36Sopenharmony_ci dev_err(component->dev, "BCLK %d not supported\n", 70862306a36Sopenharmony_ci slots * slot_width); 70962306a36Sopenharmony_ci return -EINVAL; 71062306a36Sopenharmony_ci } 71162306a36Sopenharmony_ci 71262306a36Sopenharmony_ci regmap_update_bits(max98388->regmap, 71362306a36Sopenharmony_ci MAX98388_R2041_PCM_CLK_SETUP, 71462306a36Sopenharmony_ci MAX98388_PCM_CLK_SETUP_BSEL_MASK, 71562306a36Sopenharmony_ci bsel); 71662306a36Sopenharmony_ci 71762306a36Sopenharmony_ci /* Channel size configuration */ 71862306a36Sopenharmony_ci switch (slot_width) { 71962306a36Sopenharmony_ci case 16: 72062306a36Sopenharmony_ci chan_sz = MAX98388_PCM_MODE_CFG_CHANSZ_16; 72162306a36Sopenharmony_ci break; 72262306a36Sopenharmony_ci case 24: 72362306a36Sopenharmony_ci chan_sz = MAX98388_PCM_MODE_CFG_CHANSZ_24; 72462306a36Sopenharmony_ci break; 72562306a36Sopenharmony_ci case 32: 72662306a36Sopenharmony_ci chan_sz = MAX98388_PCM_MODE_CFG_CHANSZ_32; 72762306a36Sopenharmony_ci break; 72862306a36Sopenharmony_ci default: 72962306a36Sopenharmony_ci dev_err(component->dev, "format unsupported %d\n", 73062306a36Sopenharmony_ci slot_width); 73162306a36Sopenharmony_ci return -EINVAL; 73262306a36Sopenharmony_ci } 73362306a36Sopenharmony_ci 73462306a36Sopenharmony_ci regmap_update_bits(max98388->regmap, 73562306a36Sopenharmony_ci MAX98388_R2040_PCM_MODE_CFG, 73662306a36Sopenharmony_ci MAX98388_PCM_MODE_CFG_CHANSZ_MASK, chan_sz); 73762306a36Sopenharmony_ci 73862306a36Sopenharmony_ci /* Rx slot configuration */ 73962306a36Sopenharmony_ci slot_found = 0; 74062306a36Sopenharmony_ci mask = rx_mask; 74162306a36Sopenharmony_ci for (cnt = 0 ; cnt < MAX_NUM_SLOTS ; cnt++, mask >>= 1) { 74262306a36Sopenharmony_ci if (mask & 0x1) { 74362306a36Sopenharmony_ci if (slot_found == 0) 74462306a36Sopenharmony_ci regmap_update_bits(max98388->regmap, 74562306a36Sopenharmony_ci MAX98388_R2059_PCM_RX_SRC2, 74662306a36Sopenharmony_ci MAX98388_RX_SRC_CH0_SHIFT, 74762306a36Sopenharmony_ci cnt); 74862306a36Sopenharmony_ci else 74962306a36Sopenharmony_ci regmap_update_bits(max98388->regmap, 75062306a36Sopenharmony_ci MAX98388_R2059_PCM_RX_SRC2, 75162306a36Sopenharmony_ci MAX98388_RX_SRC_CH1_SHIFT, 75262306a36Sopenharmony_ci cnt); 75362306a36Sopenharmony_ci slot_found++; 75462306a36Sopenharmony_ci if (slot_found >= MAX_NUM_CH) 75562306a36Sopenharmony_ci break; 75662306a36Sopenharmony_ci } 75762306a36Sopenharmony_ci } 75862306a36Sopenharmony_ci 75962306a36Sopenharmony_ci /* speaker feedback slot configuration */ 76062306a36Sopenharmony_ci slot_found = 0; 76162306a36Sopenharmony_ci mask = tx_mask; 76262306a36Sopenharmony_ci for (cnt = 0 ; cnt < MAX_NUM_SLOTS ; cnt++, mask >>= 1) { 76362306a36Sopenharmony_ci if (mask & 0x1) { 76462306a36Sopenharmony_ci addr = MAX98388_R2044_PCM_TX_CTRL1 + (cnt / 8); 76562306a36Sopenharmony_ci bits = cnt % 8; 76662306a36Sopenharmony_ci regmap_update_bits(max98388->regmap, addr, bits, bits); 76762306a36Sopenharmony_ci if (slot_found >= MAX_NUM_CH) 76862306a36Sopenharmony_ci break; 76962306a36Sopenharmony_ci } 77062306a36Sopenharmony_ci } 77162306a36Sopenharmony_ci 77262306a36Sopenharmony_ci return 0; 77362306a36Sopenharmony_ci} 77462306a36Sopenharmony_ci 77562306a36Sopenharmony_ci#define MAX98388_RATES SNDRV_PCM_RATE_8000_96000 77662306a36Sopenharmony_ci 77762306a36Sopenharmony_ci#define MAX98388_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ 77862306a36Sopenharmony_ci SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) 77962306a36Sopenharmony_ci 78062306a36Sopenharmony_cistatic const struct snd_soc_dai_ops max98388_dai_ops = { 78162306a36Sopenharmony_ci .set_fmt = max98388_dai_set_fmt, 78262306a36Sopenharmony_ci .hw_params = max98388_dai_hw_params, 78362306a36Sopenharmony_ci .set_tdm_slot = max98388_dai_tdm_slot, 78462306a36Sopenharmony_ci}; 78562306a36Sopenharmony_ci 78662306a36Sopenharmony_cistatic bool max98388_readable_register(struct device *dev, 78762306a36Sopenharmony_ci unsigned int reg) 78862306a36Sopenharmony_ci{ 78962306a36Sopenharmony_ci switch (reg) { 79062306a36Sopenharmony_ci case MAX98388_R2001_INT_RAW1 ... MAX98388_R2002_INT_RAW2: 79162306a36Sopenharmony_ci case MAX98388_R2004_INT_STATE1... MAX98388_R2005_INT_STATE2: 79262306a36Sopenharmony_ci case MAX98388_R2020_THERM_WARN_THRESH: 79362306a36Sopenharmony_ci case MAX98388_R2031_SPK_MON_THRESH 79462306a36Sopenharmony_ci ... MAX98388_R2033_SPK_MON_DURATION: 79562306a36Sopenharmony_ci case MAX98388_R2037_ERR_MON_CTRL: 79662306a36Sopenharmony_ci case MAX98388_R2040_PCM_MODE_CFG 79762306a36Sopenharmony_ci ... MAX98388_R2042_PCM_SR_SETUP: 79862306a36Sopenharmony_ci case MAX98388_R2044_PCM_TX_CTRL1 79962306a36Sopenharmony_ci ... MAX98388_R2045_PCM_TX_CTRL2: 80062306a36Sopenharmony_ci case MAX98388_R2050_PCM_TX_HIZ_CTRL1 80162306a36Sopenharmony_ci ... MAX98388_R2059_PCM_RX_SRC2: 80262306a36Sopenharmony_ci case MAX98388_R205C_PCM_TX_DRIVE_STRENGTH 80362306a36Sopenharmony_ci ... MAX98388_R205F_PCM_TX_EN: 80462306a36Sopenharmony_ci case MAX98388_R2090_SPK_CH_VOL_CTRL 80562306a36Sopenharmony_ci ... MAX98388_R2094_SPK_AMP_ER_CTRL: 80662306a36Sopenharmony_ci case MAX98388_R209E_SPK_CH_PINK_NOISE_EN 80762306a36Sopenharmony_ci ... MAX98388_R209F_SPK_CH_AMP_EN: 80862306a36Sopenharmony_ci case MAX98388_R20A0_IV_DATA_DSP_CTRL: 80962306a36Sopenharmony_ci case MAX98388_R20A7_IV_DATA_EN: 81062306a36Sopenharmony_ci case MAX98388_R20E0_BP_ALC_THRESH ... MAX98388_R20E4_BP_ALC_MUTE: 81162306a36Sopenharmony_ci case MAX98388_R20EE_BP_INF_HOLD_REL ... MAX98388_R20EF_BP_ALC_EN: 81262306a36Sopenharmony_ci case MAX98388_R210E_AUTO_RESTART: 81362306a36Sopenharmony_ci case MAX98388_R210F_GLOBAL_EN: 81462306a36Sopenharmony_ci case MAX98388_R22FF_REV_ID: 81562306a36Sopenharmony_ci return true; 81662306a36Sopenharmony_ci default: 81762306a36Sopenharmony_ci return false; 81862306a36Sopenharmony_ci } 81962306a36Sopenharmony_ci}; 82062306a36Sopenharmony_ci 82162306a36Sopenharmony_cistatic bool max98388_volatile_reg(struct device *dev, unsigned int reg) 82262306a36Sopenharmony_ci{ 82362306a36Sopenharmony_ci switch (reg) { 82462306a36Sopenharmony_ci case MAX98388_R2001_INT_RAW1 ... MAX98388_R2005_INT_STATE2: 82562306a36Sopenharmony_ci case MAX98388_R210F_GLOBAL_EN: 82662306a36Sopenharmony_ci case MAX98388_R22FF_REV_ID: 82762306a36Sopenharmony_ci return true; 82862306a36Sopenharmony_ci default: 82962306a36Sopenharmony_ci return false; 83062306a36Sopenharmony_ci } 83162306a36Sopenharmony_ci} 83262306a36Sopenharmony_ci 83362306a36Sopenharmony_cistatic struct snd_soc_dai_driver max98388_dai[] = { 83462306a36Sopenharmony_ci { 83562306a36Sopenharmony_ci .name = "max98388-aif1", 83662306a36Sopenharmony_ci .playback = { 83762306a36Sopenharmony_ci .stream_name = "HiFi Playback", 83862306a36Sopenharmony_ci .channels_min = 1, 83962306a36Sopenharmony_ci .channels_max = 2, 84062306a36Sopenharmony_ci .rates = MAX98388_RATES, 84162306a36Sopenharmony_ci .formats = MAX98388_FORMATS, 84262306a36Sopenharmony_ci }, 84362306a36Sopenharmony_ci .capture = { 84462306a36Sopenharmony_ci .stream_name = "HiFi Capture", 84562306a36Sopenharmony_ci .channels_min = 1, 84662306a36Sopenharmony_ci .channels_max = 2, 84762306a36Sopenharmony_ci .rates = MAX98388_RATES, 84862306a36Sopenharmony_ci .formats = MAX98388_FORMATS, 84962306a36Sopenharmony_ci }, 85062306a36Sopenharmony_ci .ops = &max98388_dai_ops, 85162306a36Sopenharmony_ci } 85262306a36Sopenharmony_ci}; 85362306a36Sopenharmony_ci 85462306a36Sopenharmony_cistatic int max98388_suspend(struct device *dev) 85562306a36Sopenharmony_ci{ 85662306a36Sopenharmony_ci struct max98388_priv *max98388 = dev_get_drvdata(dev); 85762306a36Sopenharmony_ci 85862306a36Sopenharmony_ci regcache_cache_only(max98388->regmap, true); 85962306a36Sopenharmony_ci regcache_mark_dirty(max98388->regmap); 86062306a36Sopenharmony_ci 86162306a36Sopenharmony_ci return 0; 86262306a36Sopenharmony_ci} 86362306a36Sopenharmony_ci 86462306a36Sopenharmony_cistatic int max98388_resume(struct device *dev) 86562306a36Sopenharmony_ci{ 86662306a36Sopenharmony_ci struct max98388_priv *max98388 = dev_get_drvdata(dev); 86762306a36Sopenharmony_ci 86862306a36Sopenharmony_ci regcache_cache_only(max98388->regmap, false); 86962306a36Sopenharmony_ci max98388_reset(max98388, dev); 87062306a36Sopenharmony_ci regcache_sync(max98388->regmap); 87162306a36Sopenharmony_ci 87262306a36Sopenharmony_ci return 0; 87362306a36Sopenharmony_ci} 87462306a36Sopenharmony_ci 87562306a36Sopenharmony_cistatic const struct dev_pm_ops max98388_pm = { 87662306a36Sopenharmony_ci SYSTEM_SLEEP_PM_OPS(max98388_suspend, max98388_resume) 87762306a36Sopenharmony_ci}; 87862306a36Sopenharmony_ci 87962306a36Sopenharmony_cistatic const struct regmap_config max98388_regmap = { 88062306a36Sopenharmony_ci .reg_bits = 16, 88162306a36Sopenharmony_ci .val_bits = 8, 88262306a36Sopenharmony_ci .max_register = MAX98388_R22FF_REV_ID, 88362306a36Sopenharmony_ci .reg_defaults = max98388_reg, 88462306a36Sopenharmony_ci .num_reg_defaults = ARRAY_SIZE(max98388_reg), 88562306a36Sopenharmony_ci .readable_reg = max98388_readable_register, 88662306a36Sopenharmony_ci .volatile_reg = max98388_volatile_reg, 88762306a36Sopenharmony_ci .cache_type = REGCACHE_RBTREE, 88862306a36Sopenharmony_ci}; 88962306a36Sopenharmony_ci 89062306a36Sopenharmony_cistatic const struct snd_soc_component_driver soc_codec_dev_max98388 = { 89162306a36Sopenharmony_ci .probe = max98388_probe, 89262306a36Sopenharmony_ci .controls = max98388_snd_controls, 89362306a36Sopenharmony_ci .num_controls = ARRAY_SIZE(max98388_snd_controls), 89462306a36Sopenharmony_ci .dapm_widgets = max98388_dapm_widgets, 89562306a36Sopenharmony_ci .num_dapm_widgets = ARRAY_SIZE(max98388_dapm_widgets), 89662306a36Sopenharmony_ci .dapm_routes = max98388_audio_map, 89762306a36Sopenharmony_ci .num_dapm_routes = ARRAY_SIZE(max98388_audio_map), 89862306a36Sopenharmony_ci .use_pmdown_time = 1, 89962306a36Sopenharmony_ci .endianness = 1, 90062306a36Sopenharmony_ci}; 90162306a36Sopenharmony_ci 90262306a36Sopenharmony_cistatic void max98388_read_deveice_property(struct device *dev, 90362306a36Sopenharmony_ci struct max98388_priv *max98388) 90462306a36Sopenharmony_ci{ 90562306a36Sopenharmony_ci int value; 90662306a36Sopenharmony_ci 90762306a36Sopenharmony_ci if (!device_property_read_u32(dev, "adi,vmon-slot-no", &value)) 90862306a36Sopenharmony_ci max98388->v_slot = value & 0xF; 90962306a36Sopenharmony_ci else 91062306a36Sopenharmony_ci max98388->v_slot = 0; 91162306a36Sopenharmony_ci 91262306a36Sopenharmony_ci if (!device_property_read_u32(dev, "adi,imon-slot-no", &value)) 91362306a36Sopenharmony_ci max98388->i_slot = value & 0xF; 91462306a36Sopenharmony_ci else 91562306a36Sopenharmony_ci max98388->i_slot = 1; 91662306a36Sopenharmony_ci 91762306a36Sopenharmony_ci if (device_property_read_bool(dev, "adi,interleave-mode")) 91862306a36Sopenharmony_ci max98388->interleave_mode = true; 91962306a36Sopenharmony_ci else 92062306a36Sopenharmony_ci max98388->interleave_mode = false; 92162306a36Sopenharmony_ci} 92262306a36Sopenharmony_ci 92362306a36Sopenharmony_cistatic int max98388_i2c_probe(struct i2c_client *i2c) 92462306a36Sopenharmony_ci{ 92562306a36Sopenharmony_ci int ret = 0; 92662306a36Sopenharmony_ci int reg = 0; 92762306a36Sopenharmony_ci 92862306a36Sopenharmony_ci struct max98388_priv *max98388 = NULL; 92962306a36Sopenharmony_ci 93062306a36Sopenharmony_ci max98388 = devm_kzalloc(&i2c->dev, sizeof(*max98388), GFP_KERNEL); 93162306a36Sopenharmony_ci if (!max98388) 93262306a36Sopenharmony_ci return -ENOMEM; 93362306a36Sopenharmony_ci 93462306a36Sopenharmony_ci i2c_set_clientdata(i2c, max98388); 93562306a36Sopenharmony_ci 93662306a36Sopenharmony_ci /* regmap initialization */ 93762306a36Sopenharmony_ci max98388->regmap = devm_regmap_init_i2c(i2c, &max98388_regmap); 93862306a36Sopenharmony_ci if (IS_ERR(max98388->regmap)) 93962306a36Sopenharmony_ci return dev_err_probe(&i2c->dev, PTR_ERR(max98388->regmap), 94062306a36Sopenharmony_ci "Failed to allocate register map.\n"); 94162306a36Sopenharmony_ci 94262306a36Sopenharmony_ci /* voltage/current slot & gpio configuration */ 94362306a36Sopenharmony_ci max98388_read_deveice_property(&i2c->dev, max98388); 94462306a36Sopenharmony_ci 94562306a36Sopenharmony_ci /* Device Reset */ 94662306a36Sopenharmony_ci max98388->reset_gpio = devm_gpiod_get_optional(&i2c->dev, 94762306a36Sopenharmony_ci "reset", GPIOD_OUT_HIGH); 94862306a36Sopenharmony_ci if (IS_ERR(max98388->reset_gpio)) 94962306a36Sopenharmony_ci return dev_err_probe(&i2c->dev, PTR_ERR(max98388->reset_gpio), 95062306a36Sopenharmony_ci "Unable to request GPIO\n"); 95162306a36Sopenharmony_ci 95262306a36Sopenharmony_ci if (max98388->reset_gpio) { 95362306a36Sopenharmony_ci usleep_range(5000, 6000); 95462306a36Sopenharmony_ci gpiod_set_value_cansleep(max98388->reset_gpio, 0); 95562306a36Sopenharmony_ci /* Wait for the hw reset done */ 95662306a36Sopenharmony_ci usleep_range(5000, 6000); 95762306a36Sopenharmony_ci } 95862306a36Sopenharmony_ci 95962306a36Sopenharmony_ci /* Read Revision ID */ 96062306a36Sopenharmony_ci ret = regmap_read(max98388->regmap, 96162306a36Sopenharmony_ci MAX98388_R22FF_REV_ID, ®); 96262306a36Sopenharmony_ci if (ret < 0) 96362306a36Sopenharmony_ci return dev_err_probe(&i2c->dev, ret, 96462306a36Sopenharmony_ci "Failed to read the revision ID\n"); 96562306a36Sopenharmony_ci 96662306a36Sopenharmony_ci dev_info(&i2c->dev, "MAX98388 revisionID: 0x%02X\n", reg); 96762306a36Sopenharmony_ci 96862306a36Sopenharmony_ci /* codec registration */ 96962306a36Sopenharmony_ci ret = devm_snd_soc_register_component(&i2c->dev, 97062306a36Sopenharmony_ci &soc_codec_dev_max98388, 97162306a36Sopenharmony_ci max98388_dai, 97262306a36Sopenharmony_ci ARRAY_SIZE(max98388_dai)); 97362306a36Sopenharmony_ci if (ret < 0) 97462306a36Sopenharmony_ci dev_err(&i2c->dev, "Failed to register codec: %d\n", ret); 97562306a36Sopenharmony_ci 97662306a36Sopenharmony_ci return ret; 97762306a36Sopenharmony_ci} 97862306a36Sopenharmony_ci 97962306a36Sopenharmony_cistatic const struct i2c_device_id max98388_i2c_id[] = { 98062306a36Sopenharmony_ci { "max98388", 0}, 98162306a36Sopenharmony_ci { }, 98262306a36Sopenharmony_ci}; 98362306a36Sopenharmony_ci 98462306a36Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, max98388_i2c_id); 98562306a36Sopenharmony_ci 98662306a36Sopenharmony_cistatic const struct of_device_id max98388_of_match[] = { 98762306a36Sopenharmony_ci { .compatible = "adi,max98388", }, 98862306a36Sopenharmony_ci { } 98962306a36Sopenharmony_ci}; 99062306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, max98388_of_match); 99162306a36Sopenharmony_ci 99262306a36Sopenharmony_cistatic const struct acpi_device_id max98388_acpi_match[] = { 99362306a36Sopenharmony_ci { "ADS8388", 0 }, 99462306a36Sopenharmony_ci {}, 99562306a36Sopenharmony_ci}; 99662306a36Sopenharmony_ciMODULE_DEVICE_TABLE(acpi, max98388_acpi_match); 99762306a36Sopenharmony_ci 99862306a36Sopenharmony_cistatic struct i2c_driver max98388_i2c_driver = { 99962306a36Sopenharmony_ci .driver = { 100062306a36Sopenharmony_ci .name = "max98388", 100162306a36Sopenharmony_ci .of_match_table = max98388_of_match, 100262306a36Sopenharmony_ci .acpi_match_table = max98388_acpi_match, 100362306a36Sopenharmony_ci .pm = pm_sleep_ptr(&max98388_pm), 100462306a36Sopenharmony_ci }, 100562306a36Sopenharmony_ci .probe = max98388_i2c_probe, 100662306a36Sopenharmony_ci .id_table = max98388_i2c_id, 100762306a36Sopenharmony_ci}; 100862306a36Sopenharmony_ci 100962306a36Sopenharmony_cimodule_i2c_driver(max98388_i2c_driver) 101062306a36Sopenharmony_ci 101162306a36Sopenharmony_ciMODULE_DESCRIPTION("ALSA SoC MAX98388 driver"); 101262306a36Sopenharmony_ciMODULE_AUTHOR("Ryan Lee <ryans.lee@analog.com>"); 101362306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 1014