162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * max98927.c -- MAX98927 ALSA Soc Audio driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2016-2017 Maxim Integrated Products 662306a36Sopenharmony_ci * Author: Ryan Lee <ryans.lee@maximintegrated.com> 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/acpi.h> 1062306a36Sopenharmony_ci#include <linux/i2c.h> 1162306a36Sopenharmony_ci#include <linux/module.h> 1262306a36Sopenharmony_ci#include <linux/regmap.h> 1362306a36Sopenharmony_ci#include <linux/slab.h> 1462306a36Sopenharmony_ci#include <linux/cdev.h> 1562306a36Sopenharmony_ci#include <sound/pcm.h> 1662306a36Sopenharmony_ci#include <sound/pcm_params.h> 1762306a36Sopenharmony_ci#include <sound/soc.h> 1862306a36Sopenharmony_ci#include <linux/gpio.h> 1962306a36Sopenharmony_ci#include <linux/gpio/consumer.h> 2062306a36Sopenharmony_ci#include <linux/of_gpio.h> 2162306a36Sopenharmony_ci#include <sound/tlv.h> 2262306a36Sopenharmony_ci#include "max98927.h" 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_cistatic struct reg_default max98927_reg[] = { 2562306a36Sopenharmony_ci {MAX98927_R0001_INT_RAW1, 0x00}, 2662306a36Sopenharmony_ci {MAX98927_R0002_INT_RAW2, 0x00}, 2762306a36Sopenharmony_ci {MAX98927_R0003_INT_RAW3, 0x00}, 2862306a36Sopenharmony_ci {MAX98927_R0004_INT_STATE1, 0x00}, 2962306a36Sopenharmony_ci {MAX98927_R0005_INT_STATE2, 0x00}, 3062306a36Sopenharmony_ci {MAX98927_R0006_INT_STATE3, 0x00}, 3162306a36Sopenharmony_ci {MAX98927_R0007_INT_FLAG1, 0x00}, 3262306a36Sopenharmony_ci {MAX98927_R0008_INT_FLAG2, 0x00}, 3362306a36Sopenharmony_ci {MAX98927_R0009_INT_FLAG3, 0x00}, 3462306a36Sopenharmony_ci {MAX98927_R000A_INT_EN1, 0x00}, 3562306a36Sopenharmony_ci {MAX98927_R000B_INT_EN2, 0x00}, 3662306a36Sopenharmony_ci {MAX98927_R000C_INT_EN3, 0x00}, 3762306a36Sopenharmony_ci {MAX98927_R000D_INT_FLAG_CLR1, 0x00}, 3862306a36Sopenharmony_ci {MAX98927_R000E_INT_FLAG_CLR2, 0x00}, 3962306a36Sopenharmony_ci {MAX98927_R000F_INT_FLAG_CLR3, 0x00}, 4062306a36Sopenharmony_ci {MAX98927_R0010_IRQ_CTRL, 0x00}, 4162306a36Sopenharmony_ci {MAX98927_R0011_CLK_MON, 0x00}, 4262306a36Sopenharmony_ci {MAX98927_R0012_WDOG_CTRL, 0x00}, 4362306a36Sopenharmony_ci {MAX98927_R0013_WDOG_RST, 0x00}, 4462306a36Sopenharmony_ci {MAX98927_R0014_MEAS_ADC_THERM_WARN_THRESH, 0x75}, 4562306a36Sopenharmony_ci {MAX98927_R0015_MEAS_ADC_THERM_SHDN_THRESH, 0x8c}, 4662306a36Sopenharmony_ci {MAX98927_R0016_MEAS_ADC_THERM_HYSTERESIS, 0x08}, 4762306a36Sopenharmony_ci {MAX98927_R0017_PIN_CFG, 0x55}, 4862306a36Sopenharmony_ci {MAX98927_R0018_PCM_RX_EN_A, 0x00}, 4962306a36Sopenharmony_ci {MAX98927_R0019_PCM_RX_EN_B, 0x00}, 5062306a36Sopenharmony_ci {MAX98927_R001A_PCM_TX_EN_A, 0x00}, 5162306a36Sopenharmony_ci {MAX98927_R001B_PCM_TX_EN_B, 0x00}, 5262306a36Sopenharmony_ci {MAX98927_R001C_PCM_TX_HIZ_CTRL_A, 0x00}, 5362306a36Sopenharmony_ci {MAX98927_R001D_PCM_TX_HIZ_CTRL_B, 0x00}, 5462306a36Sopenharmony_ci {MAX98927_R001E_PCM_TX_CH_SRC_A, 0x00}, 5562306a36Sopenharmony_ci {MAX98927_R001F_PCM_TX_CH_SRC_B, 0x00}, 5662306a36Sopenharmony_ci {MAX98927_R0020_PCM_MODE_CFG, 0x40}, 5762306a36Sopenharmony_ci {MAX98927_R0021_PCM_MASTER_MODE, 0x00}, 5862306a36Sopenharmony_ci {MAX98927_R0022_PCM_CLK_SETUP, 0x22}, 5962306a36Sopenharmony_ci {MAX98927_R0023_PCM_SR_SETUP1, 0x00}, 6062306a36Sopenharmony_ci {MAX98927_R0024_PCM_SR_SETUP2, 0x00}, 6162306a36Sopenharmony_ci {MAX98927_R0025_PCM_TO_SPK_MONOMIX_A, 0x00}, 6262306a36Sopenharmony_ci {MAX98927_R0026_PCM_TO_SPK_MONOMIX_B, 0x00}, 6362306a36Sopenharmony_ci {MAX98927_R0027_ICC_RX_EN_A, 0x00}, 6462306a36Sopenharmony_ci {MAX98927_R0028_ICC_RX_EN_B, 0x00}, 6562306a36Sopenharmony_ci {MAX98927_R002B_ICC_TX_EN_A, 0x00}, 6662306a36Sopenharmony_ci {MAX98927_R002C_ICC_TX_EN_B, 0x00}, 6762306a36Sopenharmony_ci {MAX98927_R002E_ICC_HIZ_MANUAL_MODE, 0x00}, 6862306a36Sopenharmony_ci {MAX98927_R002F_ICC_TX_HIZ_EN_A, 0x00}, 6962306a36Sopenharmony_ci {MAX98927_R0030_ICC_TX_HIZ_EN_B, 0x00}, 7062306a36Sopenharmony_ci {MAX98927_R0031_ICC_LNK_EN, 0x00}, 7162306a36Sopenharmony_ci {MAX98927_R0032_PDM_TX_EN, 0x00}, 7262306a36Sopenharmony_ci {MAX98927_R0033_PDM_TX_HIZ_CTRL, 0x00}, 7362306a36Sopenharmony_ci {MAX98927_R0034_PDM_TX_CTRL, 0x00}, 7462306a36Sopenharmony_ci {MAX98927_R0035_PDM_RX_CTRL, 0x00}, 7562306a36Sopenharmony_ci {MAX98927_R0036_AMP_VOL_CTRL, 0x00}, 7662306a36Sopenharmony_ci {MAX98927_R0037_AMP_DSP_CFG, 0x02}, 7762306a36Sopenharmony_ci {MAX98927_R0038_TONE_GEN_DC_CFG, 0x00}, 7862306a36Sopenharmony_ci {MAX98927_R0039_DRE_CTRL, 0x01}, 7962306a36Sopenharmony_ci {MAX98927_R003A_AMP_EN, 0x00}, 8062306a36Sopenharmony_ci {MAX98927_R003B_SPK_SRC_SEL, 0x00}, 8162306a36Sopenharmony_ci {MAX98927_R003C_SPK_GAIN, 0x00}, 8262306a36Sopenharmony_ci {MAX98927_R003D_SSM_CFG, 0x04}, 8362306a36Sopenharmony_ci {MAX98927_R003E_MEAS_EN, 0x00}, 8462306a36Sopenharmony_ci {MAX98927_R003F_MEAS_DSP_CFG, 0x04}, 8562306a36Sopenharmony_ci {MAX98927_R0040_BOOST_CTRL0, 0x00}, 8662306a36Sopenharmony_ci {MAX98927_R0041_BOOST_CTRL3, 0x00}, 8762306a36Sopenharmony_ci {MAX98927_R0042_BOOST_CTRL1, 0x00}, 8862306a36Sopenharmony_ci {MAX98927_R0043_MEAS_ADC_CFG, 0x00}, 8962306a36Sopenharmony_ci {MAX98927_R0044_MEAS_ADC_BASE_MSB, 0x01}, 9062306a36Sopenharmony_ci {MAX98927_R0045_MEAS_ADC_BASE_LSB, 0x00}, 9162306a36Sopenharmony_ci {MAX98927_R0046_ADC_CH0_DIVIDE, 0x00}, 9262306a36Sopenharmony_ci {MAX98927_R0047_ADC_CH1_DIVIDE, 0x00}, 9362306a36Sopenharmony_ci {MAX98927_R0048_ADC_CH2_DIVIDE, 0x00}, 9462306a36Sopenharmony_ci {MAX98927_R0049_ADC_CH0_FILT_CFG, 0x00}, 9562306a36Sopenharmony_ci {MAX98927_R004A_ADC_CH1_FILT_CFG, 0x00}, 9662306a36Sopenharmony_ci {MAX98927_R004B_ADC_CH2_FILT_CFG, 0x00}, 9762306a36Sopenharmony_ci {MAX98927_R004C_MEAS_ADC_CH0_READ, 0x00}, 9862306a36Sopenharmony_ci {MAX98927_R004D_MEAS_ADC_CH1_READ, 0x00}, 9962306a36Sopenharmony_ci {MAX98927_R004E_MEAS_ADC_CH2_READ, 0x00}, 10062306a36Sopenharmony_ci {MAX98927_R0051_BROWNOUT_STATUS, 0x00}, 10162306a36Sopenharmony_ci {MAX98927_R0052_BROWNOUT_EN, 0x00}, 10262306a36Sopenharmony_ci {MAX98927_R0053_BROWNOUT_INFINITE_HOLD, 0x00}, 10362306a36Sopenharmony_ci {MAX98927_R0054_BROWNOUT_INFINITE_HOLD_CLR, 0x00}, 10462306a36Sopenharmony_ci {MAX98927_R0055_BROWNOUT_LVL_HOLD, 0x00}, 10562306a36Sopenharmony_ci {MAX98927_R005A_BROWNOUT_LVL1_THRESH, 0x00}, 10662306a36Sopenharmony_ci {MAX98927_R005B_BROWNOUT_LVL2_THRESH, 0x00}, 10762306a36Sopenharmony_ci {MAX98927_R005C_BROWNOUT_LVL3_THRESH, 0x00}, 10862306a36Sopenharmony_ci {MAX98927_R005D_BROWNOUT_LVL4_THRESH, 0x00}, 10962306a36Sopenharmony_ci {MAX98927_R005E_BROWNOUT_THRESH_HYSTERYSIS, 0x00}, 11062306a36Sopenharmony_ci {MAX98927_R005F_BROWNOUT_AMP_LIMITER_ATK_REL, 0x00}, 11162306a36Sopenharmony_ci {MAX98927_R0060_BROWNOUT_AMP_GAIN_ATK_REL, 0x00}, 11262306a36Sopenharmony_ci {MAX98927_R0061_BROWNOUT_AMP1_CLIP_MODE, 0x00}, 11362306a36Sopenharmony_ci {MAX98927_R0072_BROWNOUT_LVL1_CUR_LIMIT, 0x00}, 11462306a36Sopenharmony_ci {MAX98927_R0073_BROWNOUT_LVL1_AMP1_CTRL1, 0x00}, 11562306a36Sopenharmony_ci {MAX98927_R0074_BROWNOUT_LVL1_AMP1_CTRL2, 0x00}, 11662306a36Sopenharmony_ci {MAX98927_R0075_BROWNOUT_LVL1_AMP1_CTRL3, 0x00}, 11762306a36Sopenharmony_ci {MAX98927_R0076_BROWNOUT_LVL2_CUR_LIMIT, 0x00}, 11862306a36Sopenharmony_ci {MAX98927_R0077_BROWNOUT_LVL2_AMP1_CTRL1, 0x00}, 11962306a36Sopenharmony_ci {MAX98927_R0078_BROWNOUT_LVL2_AMP1_CTRL2, 0x00}, 12062306a36Sopenharmony_ci {MAX98927_R0079_BROWNOUT_LVL2_AMP1_CTRL3, 0x00}, 12162306a36Sopenharmony_ci {MAX98927_R007A_BROWNOUT_LVL3_CUR_LIMIT, 0x00}, 12262306a36Sopenharmony_ci {MAX98927_R007B_BROWNOUT_LVL3_AMP1_CTRL1, 0x00}, 12362306a36Sopenharmony_ci {MAX98927_R007C_BROWNOUT_LVL3_AMP1_CTRL2, 0x00}, 12462306a36Sopenharmony_ci {MAX98927_R007D_BROWNOUT_LVL3_AMP1_CTRL3, 0x00}, 12562306a36Sopenharmony_ci {MAX98927_R007E_BROWNOUT_LVL4_CUR_LIMIT, 0x00}, 12662306a36Sopenharmony_ci {MAX98927_R007F_BROWNOUT_LVL4_AMP1_CTRL1, 0x00}, 12762306a36Sopenharmony_ci {MAX98927_R0080_BROWNOUT_LVL4_AMP1_CTRL2, 0x00}, 12862306a36Sopenharmony_ci {MAX98927_R0081_BROWNOUT_LVL4_AMP1_CTRL3, 0x00}, 12962306a36Sopenharmony_ci {MAX98927_R0082_ENV_TRACK_VOUT_HEADROOM, 0x00}, 13062306a36Sopenharmony_ci {MAX98927_R0083_ENV_TRACK_BOOST_VOUT_DELAY, 0x00}, 13162306a36Sopenharmony_ci {MAX98927_R0084_ENV_TRACK_REL_RATE, 0x00}, 13262306a36Sopenharmony_ci {MAX98927_R0085_ENV_TRACK_HOLD_RATE, 0x00}, 13362306a36Sopenharmony_ci {MAX98927_R0086_ENV_TRACK_CTRL, 0x00}, 13462306a36Sopenharmony_ci {MAX98927_R0087_ENV_TRACK_BOOST_VOUT_READ, 0x00}, 13562306a36Sopenharmony_ci {MAX98927_R00FF_GLOBAL_SHDN, 0x00}, 13662306a36Sopenharmony_ci {MAX98927_R0100_SOFT_RESET, 0x00}, 13762306a36Sopenharmony_ci {MAX98927_R01FF_REV_ID, 0x40}, 13862306a36Sopenharmony_ci}; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_cistatic int max98927_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) 14162306a36Sopenharmony_ci{ 14262306a36Sopenharmony_ci struct snd_soc_component *component = codec_dai->component; 14362306a36Sopenharmony_ci struct max98927_priv *max98927 = snd_soc_component_get_drvdata(component); 14462306a36Sopenharmony_ci unsigned int mode = 0; 14562306a36Sopenharmony_ci unsigned int format = 0; 14662306a36Sopenharmony_ci bool use_pdm = false; 14762306a36Sopenharmony_ci unsigned int invert = 0; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci dev_dbg(component->dev, "%s: fmt 0x%08X\n", __func__, fmt); 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { 15262306a36Sopenharmony_ci case SND_SOC_DAIFMT_CBC_CFC: 15362306a36Sopenharmony_ci max98927->provider = false; 15462306a36Sopenharmony_ci mode = MAX98927_PCM_MASTER_MODE_SLAVE; 15562306a36Sopenharmony_ci break; 15662306a36Sopenharmony_ci case SND_SOC_DAIFMT_CBP_CFP: 15762306a36Sopenharmony_ci max98927->provider = true; 15862306a36Sopenharmony_ci mode = MAX98927_PCM_MASTER_MODE_MASTER; 15962306a36Sopenharmony_ci break; 16062306a36Sopenharmony_ci default: 16162306a36Sopenharmony_ci dev_err(component->dev, "DAI clock mode unsupported\n"); 16262306a36Sopenharmony_ci return -EINVAL; 16362306a36Sopenharmony_ci } 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci regmap_update_bits(max98927->regmap, MAX98927_R0021_PCM_MASTER_MODE, 16662306a36Sopenharmony_ci MAX98927_PCM_MASTER_MODE_MASK, mode); 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 16962306a36Sopenharmony_ci case SND_SOC_DAIFMT_NB_NF: 17062306a36Sopenharmony_ci break; 17162306a36Sopenharmony_ci case SND_SOC_DAIFMT_IB_NF: 17262306a36Sopenharmony_ci invert = MAX98927_PCM_MODE_CFG_PCM_BCLKEDGE; 17362306a36Sopenharmony_ci break; 17462306a36Sopenharmony_ci default: 17562306a36Sopenharmony_ci dev_err(component->dev, "DAI invert mode unsupported\n"); 17662306a36Sopenharmony_ci return -EINVAL; 17762306a36Sopenharmony_ci } 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci regmap_update_bits(max98927->regmap, MAX98927_R0020_PCM_MODE_CFG, 18062306a36Sopenharmony_ci MAX98927_PCM_MODE_CFG_PCM_BCLKEDGE, invert); 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci /* interface format */ 18362306a36Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 18462306a36Sopenharmony_ci case SND_SOC_DAIFMT_I2S: 18562306a36Sopenharmony_ci format = MAX98927_PCM_FORMAT_I2S; 18662306a36Sopenharmony_ci break; 18762306a36Sopenharmony_ci case SND_SOC_DAIFMT_LEFT_J: 18862306a36Sopenharmony_ci format = MAX98927_PCM_FORMAT_LJ; 18962306a36Sopenharmony_ci break; 19062306a36Sopenharmony_ci case SND_SOC_DAIFMT_DSP_A: 19162306a36Sopenharmony_ci format = MAX98927_PCM_FORMAT_TDM_MODE1; 19262306a36Sopenharmony_ci break; 19362306a36Sopenharmony_ci case SND_SOC_DAIFMT_DSP_B: 19462306a36Sopenharmony_ci format = MAX98927_PCM_FORMAT_TDM_MODE0; 19562306a36Sopenharmony_ci break; 19662306a36Sopenharmony_ci case SND_SOC_DAIFMT_PDM: 19762306a36Sopenharmony_ci use_pdm = true; 19862306a36Sopenharmony_ci break; 19962306a36Sopenharmony_ci default: 20062306a36Sopenharmony_ci return -EINVAL; 20162306a36Sopenharmony_ci } 20262306a36Sopenharmony_ci max98927->iface = fmt & SND_SOC_DAIFMT_FORMAT_MASK; 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci if (!use_pdm) { 20562306a36Sopenharmony_ci /* pcm channel configuration */ 20662306a36Sopenharmony_ci regmap_update_bits(max98927->regmap, MAX98927_R0018_PCM_RX_EN_A, 20762306a36Sopenharmony_ci MAX98927_PCM_RX_CH0_EN | MAX98927_PCM_RX_CH1_EN, 20862306a36Sopenharmony_ci MAX98927_PCM_RX_CH0_EN | MAX98927_PCM_RX_CH1_EN); 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci regmap_update_bits(max98927->regmap, 21162306a36Sopenharmony_ci MAX98927_R0020_PCM_MODE_CFG, 21262306a36Sopenharmony_ci MAX98927_PCM_MODE_CFG_FORMAT_MASK, 21362306a36Sopenharmony_ci format << MAX98927_PCM_MODE_CFG_FORMAT_SHIFT); 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci regmap_update_bits(max98927->regmap, MAX98927_R003B_SPK_SRC_SEL, 21662306a36Sopenharmony_ci MAX98927_SPK_SRC_MASK, 0); 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci regmap_update_bits(max98927->regmap, MAX98927_R0035_PDM_RX_CTRL, 21962306a36Sopenharmony_ci MAX98927_PDM_RX_EN_MASK, 0); 22062306a36Sopenharmony_ci } else { 22162306a36Sopenharmony_ci /* pdm channel configuration */ 22262306a36Sopenharmony_ci regmap_update_bits(max98927->regmap, MAX98927_R0035_PDM_RX_CTRL, 22362306a36Sopenharmony_ci MAX98927_PDM_RX_EN_MASK, 1); 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci regmap_update_bits(max98927->regmap, MAX98927_R003B_SPK_SRC_SEL, 22662306a36Sopenharmony_ci MAX98927_SPK_SRC_MASK, 3); 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci regmap_update_bits(max98927->regmap, MAX98927_R0018_PCM_RX_EN_A, 22962306a36Sopenharmony_ci MAX98927_PCM_RX_CH0_EN | MAX98927_PCM_RX_CH1_EN, 23062306a36Sopenharmony_ci 0); 23162306a36Sopenharmony_ci } 23262306a36Sopenharmony_ci return 0; 23362306a36Sopenharmony_ci} 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci/* codec MCLK rate in master mode */ 23662306a36Sopenharmony_cistatic const int rate_table[] = { 23762306a36Sopenharmony_ci 5644800, 6000000, 6144000, 6500000, 23862306a36Sopenharmony_ci 9600000, 11289600, 12000000, 12288000, 23962306a36Sopenharmony_ci 13000000, 19200000, 24062306a36Sopenharmony_ci}; 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci/* BCLKs per LRCLK */ 24362306a36Sopenharmony_cistatic const int bclk_sel_table[] = { 24462306a36Sopenharmony_ci 32, 48, 64, 96, 128, 192, 256, 384, 512, 24562306a36Sopenharmony_ci}; 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_cistatic int max98927_get_bclk_sel(int bclk) 24862306a36Sopenharmony_ci{ 24962306a36Sopenharmony_ci int i; 25062306a36Sopenharmony_ci /* match BCLKs per LRCLK */ 25162306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(bclk_sel_table); i++) { 25262306a36Sopenharmony_ci if (bclk_sel_table[i] == bclk) 25362306a36Sopenharmony_ci return i + 2; 25462306a36Sopenharmony_ci } 25562306a36Sopenharmony_ci return 0; 25662306a36Sopenharmony_ci} 25762306a36Sopenharmony_cistatic int max98927_set_clock(struct max98927_priv *max98927, 25862306a36Sopenharmony_ci struct snd_pcm_hw_params *params) 25962306a36Sopenharmony_ci{ 26062306a36Sopenharmony_ci struct snd_soc_component *component = max98927->component; 26162306a36Sopenharmony_ci /* BCLK/LRCLK ratio calculation */ 26262306a36Sopenharmony_ci int blr_clk_ratio = params_channels(params) * max98927->ch_size; 26362306a36Sopenharmony_ci int value; 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci if (max98927->provider) { 26662306a36Sopenharmony_ci int i; 26762306a36Sopenharmony_ci /* match rate to closest value */ 26862306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(rate_table); i++) { 26962306a36Sopenharmony_ci if (rate_table[i] >= max98927->sysclk) 27062306a36Sopenharmony_ci break; 27162306a36Sopenharmony_ci } 27262306a36Sopenharmony_ci if (i == ARRAY_SIZE(rate_table)) { 27362306a36Sopenharmony_ci dev_err(component->dev, "failed to find proper clock rate.\n"); 27462306a36Sopenharmony_ci return -EINVAL; 27562306a36Sopenharmony_ci } 27662306a36Sopenharmony_ci regmap_update_bits(max98927->regmap, 27762306a36Sopenharmony_ci MAX98927_R0021_PCM_MASTER_MODE, 27862306a36Sopenharmony_ci MAX98927_PCM_MASTER_MODE_MCLK_MASK, 27962306a36Sopenharmony_ci i << MAX98927_PCM_MASTER_MODE_MCLK_RATE_SHIFT); 28062306a36Sopenharmony_ci } 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci if (!max98927->tdm_mode) { 28362306a36Sopenharmony_ci /* BCLK configuration */ 28462306a36Sopenharmony_ci value = max98927_get_bclk_sel(blr_clk_ratio); 28562306a36Sopenharmony_ci if (!value) { 28662306a36Sopenharmony_ci dev_err(component->dev, "format unsupported %d\n", 28762306a36Sopenharmony_ci params_format(params)); 28862306a36Sopenharmony_ci return -EINVAL; 28962306a36Sopenharmony_ci } 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci regmap_update_bits(max98927->regmap, 29262306a36Sopenharmony_ci MAX98927_R0022_PCM_CLK_SETUP, 29362306a36Sopenharmony_ci MAX98927_PCM_CLK_SETUP_BSEL_MASK, value); 29462306a36Sopenharmony_ci } 29562306a36Sopenharmony_ci return 0; 29662306a36Sopenharmony_ci} 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_cistatic int max98927_dai_hw_params(struct snd_pcm_substream *substream, 29962306a36Sopenharmony_ci struct snd_pcm_hw_params *params, 30062306a36Sopenharmony_ci struct snd_soc_dai *dai) 30162306a36Sopenharmony_ci{ 30262306a36Sopenharmony_ci struct snd_soc_component *component = dai->component; 30362306a36Sopenharmony_ci struct max98927_priv *max98927 = snd_soc_component_get_drvdata(component); 30462306a36Sopenharmony_ci unsigned int sampling_rate = 0; 30562306a36Sopenharmony_ci unsigned int chan_sz = 0; 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci /* pcm mode configuration */ 30862306a36Sopenharmony_ci switch (snd_pcm_format_width(params_format(params))) { 30962306a36Sopenharmony_ci case 16: 31062306a36Sopenharmony_ci chan_sz = MAX98927_PCM_MODE_CFG_CHANSZ_16; 31162306a36Sopenharmony_ci break; 31262306a36Sopenharmony_ci case 24: 31362306a36Sopenharmony_ci chan_sz = MAX98927_PCM_MODE_CFG_CHANSZ_24; 31462306a36Sopenharmony_ci break; 31562306a36Sopenharmony_ci case 32: 31662306a36Sopenharmony_ci chan_sz = MAX98927_PCM_MODE_CFG_CHANSZ_32; 31762306a36Sopenharmony_ci break; 31862306a36Sopenharmony_ci default: 31962306a36Sopenharmony_ci dev_err(component->dev, "format unsupported %d\n", 32062306a36Sopenharmony_ci params_format(params)); 32162306a36Sopenharmony_ci goto err; 32262306a36Sopenharmony_ci } 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci max98927->ch_size = snd_pcm_format_width(params_format(params)); 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci regmap_update_bits(max98927->regmap, MAX98927_R0020_PCM_MODE_CFG, 32762306a36Sopenharmony_ci MAX98927_PCM_MODE_CFG_CHANSZ_MASK, chan_sz); 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci dev_dbg(component->dev, "format supported %d", 33062306a36Sopenharmony_ci params_format(params)); 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci /* sampling rate configuration */ 33362306a36Sopenharmony_ci switch (params_rate(params)) { 33462306a36Sopenharmony_ci case 8000: 33562306a36Sopenharmony_ci sampling_rate = MAX98927_PCM_SR_SET1_SR_8000; 33662306a36Sopenharmony_ci break; 33762306a36Sopenharmony_ci case 11025: 33862306a36Sopenharmony_ci sampling_rate = MAX98927_PCM_SR_SET1_SR_11025; 33962306a36Sopenharmony_ci break; 34062306a36Sopenharmony_ci case 12000: 34162306a36Sopenharmony_ci sampling_rate = MAX98927_PCM_SR_SET1_SR_12000; 34262306a36Sopenharmony_ci break; 34362306a36Sopenharmony_ci case 16000: 34462306a36Sopenharmony_ci sampling_rate = MAX98927_PCM_SR_SET1_SR_16000; 34562306a36Sopenharmony_ci break; 34662306a36Sopenharmony_ci case 22050: 34762306a36Sopenharmony_ci sampling_rate = MAX98927_PCM_SR_SET1_SR_22050; 34862306a36Sopenharmony_ci break; 34962306a36Sopenharmony_ci case 24000: 35062306a36Sopenharmony_ci sampling_rate = MAX98927_PCM_SR_SET1_SR_24000; 35162306a36Sopenharmony_ci break; 35262306a36Sopenharmony_ci case 32000: 35362306a36Sopenharmony_ci sampling_rate = MAX98927_PCM_SR_SET1_SR_32000; 35462306a36Sopenharmony_ci break; 35562306a36Sopenharmony_ci case 44100: 35662306a36Sopenharmony_ci sampling_rate = MAX98927_PCM_SR_SET1_SR_44100; 35762306a36Sopenharmony_ci break; 35862306a36Sopenharmony_ci case 48000: 35962306a36Sopenharmony_ci sampling_rate = MAX98927_PCM_SR_SET1_SR_48000; 36062306a36Sopenharmony_ci break; 36162306a36Sopenharmony_ci default: 36262306a36Sopenharmony_ci dev_err(component->dev, "rate %d not supported\n", 36362306a36Sopenharmony_ci params_rate(params)); 36462306a36Sopenharmony_ci goto err; 36562306a36Sopenharmony_ci } 36662306a36Sopenharmony_ci /* set DAI_SR to correct LRCLK frequency */ 36762306a36Sopenharmony_ci regmap_update_bits(max98927->regmap, MAX98927_R0023_PCM_SR_SETUP1, 36862306a36Sopenharmony_ci MAX98927_PCM_SR_SET1_SR_MASK, sampling_rate); 36962306a36Sopenharmony_ci regmap_update_bits(max98927->regmap, MAX98927_R0024_PCM_SR_SETUP2, 37062306a36Sopenharmony_ci MAX98927_PCM_SR_SET2_SR_MASK, 37162306a36Sopenharmony_ci sampling_rate << MAX98927_PCM_SR_SET2_SR_SHIFT); 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci /* set sampling rate of IV */ 37462306a36Sopenharmony_ci if (max98927->interleave_mode && 37562306a36Sopenharmony_ci sampling_rate > MAX98927_PCM_SR_SET1_SR_16000) 37662306a36Sopenharmony_ci regmap_update_bits(max98927->regmap, 37762306a36Sopenharmony_ci MAX98927_R0024_PCM_SR_SETUP2, 37862306a36Sopenharmony_ci MAX98927_PCM_SR_SET2_IVADC_SR_MASK, 37962306a36Sopenharmony_ci sampling_rate - 3); 38062306a36Sopenharmony_ci else 38162306a36Sopenharmony_ci regmap_update_bits(max98927->regmap, 38262306a36Sopenharmony_ci MAX98927_R0024_PCM_SR_SETUP2, 38362306a36Sopenharmony_ci MAX98927_PCM_SR_SET2_IVADC_SR_MASK, 38462306a36Sopenharmony_ci sampling_rate); 38562306a36Sopenharmony_ci return max98927_set_clock(max98927, params); 38662306a36Sopenharmony_cierr: 38762306a36Sopenharmony_ci return -EINVAL; 38862306a36Sopenharmony_ci} 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_cistatic int max98927_dai_tdm_slot(struct snd_soc_dai *dai, 39162306a36Sopenharmony_ci unsigned int tx_mask, unsigned int rx_mask, 39262306a36Sopenharmony_ci int slots, int slot_width) 39362306a36Sopenharmony_ci{ 39462306a36Sopenharmony_ci struct snd_soc_component *component = dai->component; 39562306a36Sopenharmony_ci struct max98927_priv *max98927 = snd_soc_component_get_drvdata(component); 39662306a36Sopenharmony_ci int bsel = 0; 39762306a36Sopenharmony_ci unsigned int chan_sz = 0; 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci max98927->tdm_mode = true; 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci /* BCLK configuration */ 40262306a36Sopenharmony_ci bsel = max98927_get_bclk_sel(slots * slot_width); 40362306a36Sopenharmony_ci if (bsel == 0) { 40462306a36Sopenharmony_ci dev_err(component->dev, "BCLK %d not supported\n", 40562306a36Sopenharmony_ci slots * slot_width); 40662306a36Sopenharmony_ci return -EINVAL; 40762306a36Sopenharmony_ci } 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci regmap_update_bits(max98927->regmap, MAX98927_R0022_PCM_CLK_SETUP, 41062306a36Sopenharmony_ci MAX98927_PCM_CLK_SETUP_BSEL_MASK, bsel); 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci /* Channel size configuration */ 41362306a36Sopenharmony_ci switch (slot_width) { 41462306a36Sopenharmony_ci case 16: 41562306a36Sopenharmony_ci chan_sz = MAX98927_PCM_MODE_CFG_CHANSZ_16; 41662306a36Sopenharmony_ci break; 41762306a36Sopenharmony_ci case 24: 41862306a36Sopenharmony_ci chan_sz = MAX98927_PCM_MODE_CFG_CHANSZ_24; 41962306a36Sopenharmony_ci break; 42062306a36Sopenharmony_ci case 32: 42162306a36Sopenharmony_ci chan_sz = MAX98927_PCM_MODE_CFG_CHANSZ_32; 42262306a36Sopenharmony_ci break; 42362306a36Sopenharmony_ci default: 42462306a36Sopenharmony_ci dev_err(component->dev, "format unsupported %d\n", 42562306a36Sopenharmony_ci slot_width); 42662306a36Sopenharmony_ci return -EINVAL; 42762306a36Sopenharmony_ci } 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci regmap_update_bits(max98927->regmap, MAX98927_R0020_PCM_MODE_CFG, 43062306a36Sopenharmony_ci MAX98927_PCM_MODE_CFG_CHANSZ_MASK, chan_sz); 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci /* Rx slot configuration */ 43362306a36Sopenharmony_ci regmap_write(max98927->regmap, MAX98927_R0018_PCM_RX_EN_A, 43462306a36Sopenharmony_ci rx_mask & 0xFF); 43562306a36Sopenharmony_ci regmap_write(max98927->regmap, MAX98927_R0019_PCM_RX_EN_B, 43662306a36Sopenharmony_ci (rx_mask & 0xFF00) >> 8); 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_ci /* Tx slot configuration */ 43962306a36Sopenharmony_ci regmap_write(max98927->regmap, MAX98927_R001A_PCM_TX_EN_A, 44062306a36Sopenharmony_ci tx_mask & 0xFF); 44162306a36Sopenharmony_ci regmap_write(max98927->regmap, MAX98927_R001B_PCM_TX_EN_B, 44262306a36Sopenharmony_ci (tx_mask & 0xFF00) >> 8); 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ci /* Tx slot Hi-Z configuration */ 44562306a36Sopenharmony_ci regmap_write(max98927->regmap, MAX98927_R001C_PCM_TX_HIZ_CTRL_A, 44662306a36Sopenharmony_ci ~tx_mask & 0xFF); 44762306a36Sopenharmony_ci regmap_write(max98927->regmap, MAX98927_R001D_PCM_TX_HIZ_CTRL_B, 44862306a36Sopenharmony_ci (~tx_mask & 0xFF00) >> 8); 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_ci return 0; 45162306a36Sopenharmony_ci} 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_ci#define MAX98927_RATES SNDRV_PCM_RATE_8000_48000 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci#define MAX98927_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ 45662306a36Sopenharmony_ci SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_cistatic int max98927_dai_set_sysclk(struct snd_soc_dai *dai, 45962306a36Sopenharmony_ci int clk_id, unsigned int freq, int dir) 46062306a36Sopenharmony_ci{ 46162306a36Sopenharmony_ci struct snd_soc_component *component = dai->component; 46262306a36Sopenharmony_ci struct max98927_priv *max98927 = snd_soc_component_get_drvdata(component); 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci max98927->sysclk = freq; 46562306a36Sopenharmony_ci return 0; 46662306a36Sopenharmony_ci} 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_cistatic const struct snd_soc_dai_ops max98927_dai_ops = { 46962306a36Sopenharmony_ci .set_sysclk = max98927_dai_set_sysclk, 47062306a36Sopenharmony_ci .set_fmt = max98927_dai_set_fmt, 47162306a36Sopenharmony_ci .hw_params = max98927_dai_hw_params, 47262306a36Sopenharmony_ci .set_tdm_slot = max98927_dai_tdm_slot, 47362306a36Sopenharmony_ci}; 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_cistatic int max98927_dac_event(struct snd_soc_dapm_widget *w, 47662306a36Sopenharmony_ci struct snd_kcontrol *kcontrol, int event) 47762306a36Sopenharmony_ci{ 47862306a36Sopenharmony_ci struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 47962306a36Sopenharmony_ci struct max98927_priv *max98927 = snd_soc_component_get_drvdata(component); 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_ci switch (event) { 48262306a36Sopenharmony_ci case SND_SOC_DAPM_PRE_PMU: 48362306a36Sopenharmony_ci max98927->tdm_mode = false; 48462306a36Sopenharmony_ci break; 48562306a36Sopenharmony_ci case SND_SOC_DAPM_POST_PMU: 48662306a36Sopenharmony_ci regmap_update_bits(max98927->regmap, MAX98927_R003A_AMP_EN, 48762306a36Sopenharmony_ci MAX98927_AMP_EN_MASK, 1); 48862306a36Sopenharmony_ci regmap_update_bits(max98927->regmap, MAX98927_R00FF_GLOBAL_SHDN, 48962306a36Sopenharmony_ci MAX98927_GLOBAL_EN_MASK, 1); 49062306a36Sopenharmony_ci break; 49162306a36Sopenharmony_ci case SND_SOC_DAPM_POST_PMD: 49262306a36Sopenharmony_ci regmap_update_bits(max98927->regmap, MAX98927_R00FF_GLOBAL_SHDN, 49362306a36Sopenharmony_ci MAX98927_GLOBAL_EN_MASK, 0); 49462306a36Sopenharmony_ci regmap_update_bits(max98927->regmap, MAX98927_R003A_AMP_EN, 49562306a36Sopenharmony_ci MAX98927_AMP_EN_MASK, 0); 49662306a36Sopenharmony_ci break; 49762306a36Sopenharmony_ci default: 49862306a36Sopenharmony_ci return 0; 49962306a36Sopenharmony_ci } 50062306a36Sopenharmony_ci return 0; 50162306a36Sopenharmony_ci} 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_cistatic const char * const max98927_switch_text[] = { 50462306a36Sopenharmony_ci "Left", "Right", "LeftRight"}; 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_cistatic const struct soc_enum dai_sel_enum = 50762306a36Sopenharmony_ci SOC_ENUM_SINGLE(MAX98927_R0025_PCM_TO_SPK_MONOMIX_A, 50862306a36Sopenharmony_ci MAX98927_PCM_TO_SPK_MONOMIX_CFG_SHIFT, 3, 50962306a36Sopenharmony_ci max98927_switch_text); 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_cistatic const struct snd_kcontrol_new max98927_dai_controls = 51262306a36Sopenharmony_ci SOC_DAPM_ENUM("DAI Sel", dai_sel_enum); 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_cistatic const struct snd_kcontrol_new max98927_vi_control = 51562306a36Sopenharmony_ci SOC_DAPM_SINGLE("Switch", MAX98927_R003F_MEAS_DSP_CFG, 2, 1, 0); 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_cistatic const struct snd_soc_dapm_widget max98927_dapm_widgets[] = { 51862306a36Sopenharmony_ci SND_SOC_DAPM_DAC_E("Amp Enable", "HiFi Playback", MAX98927_R003A_AMP_EN, 51962306a36Sopenharmony_ci 0, 0, max98927_dac_event, 52062306a36Sopenharmony_ci SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), 52162306a36Sopenharmony_ci SND_SOC_DAPM_MUX("DAI Sel Mux", SND_SOC_NOPM, 0, 0, 52262306a36Sopenharmony_ci &max98927_dai_controls), 52362306a36Sopenharmony_ci SND_SOC_DAPM_OUTPUT("BE_OUT"), 52462306a36Sopenharmony_ci SND_SOC_DAPM_AIF_OUT("Voltage Sense", "HiFi Capture", 0, 52562306a36Sopenharmony_ci MAX98927_R003E_MEAS_EN, 0, 0), 52662306a36Sopenharmony_ci SND_SOC_DAPM_AIF_OUT("Current Sense", "HiFi Capture", 0, 52762306a36Sopenharmony_ci MAX98927_R003E_MEAS_EN, 1, 0), 52862306a36Sopenharmony_ci SND_SOC_DAPM_SWITCH("VI Sense", SND_SOC_NOPM, 0, 0, 52962306a36Sopenharmony_ci &max98927_vi_control), 53062306a36Sopenharmony_ci SND_SOC_DAPM_SIGGEN("VMON"), 53162306a36Sopenharmony_ci SND_SOC_DAPM_SIGGEN("IMON"), 53262306a36Sopenharmony_ci}; 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_cistatic DECLARE_TLV_DB_SCALE(max98927_spk_tlv, 300, 300, 0); 53562306a36Sopenharmony_cistatic DECLARE_TLV_DB_SCALE(max98927_digital_tlv, -1600, 25, 0); 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_cistatic bool max98927_readable_register(struct device *dev, unsigned int reg) 53862306a36Sopenharmony_ci{ 53962306a36Sopenharmony_ci switch (reg) { 54062306a36Sopenharmony_ci case MAX98927_R0001_INT_RAW1 ... MAX98927_R0028_ICC_RX_EN_B: 54162306a36Sopenharmony_ci case MAX98927_R002B_ICC_TX_EN_A ... MAX98927_R002C_ICC_TX_EN_B: 54262306a36Sopenharmony_ci case MAX98927_R002E_ICC_HIZ_MANUAL_MODE 54362306a36Sopenharmony_ci ... MAX98927_R004E_MEAS_ADC_CH2_READ: 54462306a36Sopenharmony_ci case MAX98927_R0051_BROWNOUT_STATUS 54562306a36Sopenharmony_ci ... MAX98927_R0055_BROWNOUT_LVL_HOLD: 54662306a36Sopenharmony_ci case MAX98927_R005A_BROWNOUT_LVL1_THRESH 54762306a36Sopenharmony_ci ... MAX98927_R0061_BROWNOUT_AMP1_CLIP_MODE: 54862306a36Sopenharmony_ci case MAX98927_R0072_BROWNOUT_LVL1_CUR_LIMIT 54962306a36Sopenharmony_ci ... MAX98927_R0087_ENV_TRACK_BOOST_VOUT_READ: 55062306a36Sopenharmony_ci case MAX98927_R00FF_GLOBAL_SHDN: 55162306a36Sopenharmony_ci case MAX98927_R0100_SOFT_RESET: 55262306a36Sopenharmony_ci case MAX98927_R01FF_REV_ID: 55362306a36Sopenharmony_ci return true; 55462306a36Sopenharmony_ci default: 55562306a36Sopenharmony_ci return false; 55662306a36Sopenharmony_ci } 55762306a36Sopenharmony_ci}; 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_cistatic bool max98927_volatile_reg(struct device *dev, unsigned int reg) 56062306a36Sopenharmony_ci{ 56162306a36Sopenharmony_ci switch (reg) { 56262306a36Sopenharmony_ci case MAX98927_R0001_INT_RAW1 ... MAX98927_R0009_INT_FLAG3: 56362306a36Sopenharmony_ci case MAX98927_R004C_MEAS_ADC_CH0_READ: 56462306a36Sopenharmony_ci case MAX98927_R004D_MEAS_ADC_CH1_READ: 56562306a36Sopenharmony_ci case MAX98927_R004E_MEAS_ADC_CH2_READ: 56662306a36Sopenharmony_ci case MAX98927_R0051_BROWNOUT_STATUS: 56762306a36Sopenharmony_ci case MAX98927_R0087_ENV_TRACK_BOOST_VOUT_READ: 56862306a36Sopenharmony_ci case MAX98927_R01FF_REV_ID: 56962306a36Sopenharmony_ci case MAX98927_R0100_SOFT_RESET: 57062306a36Sopenharmony_ci return true; 57162306a36Sopenharmony_ci default: 57262306a36Sopenharmony_ci return false; 57362306a36Sopenharmony_ci } 57462306a36Sopenharmony_ci} 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_cistatic const char * const max98927_boost_voltage_text[] = { 57762306a36Sopenharmony_ci "6.5V", "6.625V", "6.75V", "6.875V", "7V", "7.125V", "7.25V", "7.375V", 57862306a36Sopenharmony_ci "7.5V", "7.625V", "7.75V", "7.875V", "8V", "8.125V", "8.25V", "8.375V", 57962306a36Sopenharmony_ci "8.5V", "8.625V", "8.75V", "8.875V", "9V", "9.125V", "9.25V", "9.375V", 58062306a36Sopenharmony_ci "9.5V", "9.625V", "9.75V", "9.875V", "10V" 58162306a36Sopenharmony_ci}; 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(max98927_boost_voltage, 58462306a36Sopenharmony_ci MAX98927_R0040_BOOST_CTRL0, 0, 58562306a36Sopenharmony_ci max98927_boost_voltage_text); 58662306a36Sopenharmony_ci 58762306a36Sopenharmony_cistatic const char * const max98927_current_limit_text[] = { 58862306a36Sopenharmony_ci "1.00A", "1.10A", "1.20A", "1.30A", "1.40A", "1.50A", "1.60A", "1.70A", 58962306a36Sopenharmony_ci "1.80A", "1.90A", "2.00A", "2.10A", "2.20A", "2.30A", "2.40A", "2.50A", 59062306a36Sopenharmony_ci "2.60A", "2.70A", "2.80A", "2.90A", "3.00A", "3.10A", "3.20A", "3.30A", 59162306a36Sopenharmony_ci "3.40A", "3.50A", "3.60A", "3.70A", "3.80A", "3.90A", "4.00A", "4.10A" 59262306a36Sopenharmony_ci}; 59362306a36Sopenharmony_ci 59462306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(max98927_current_limit, 59562306a36Sopenharmony_ci MAX98927_R0042_BOOST_CTRL1, 1, 59662306a36Sopenharmony_ci max98927_current_limit_text); 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_cistatic const struct snd_kcontrol_new max98927_snd_controls[] = { 59962306a36Sopenharmony_ci SOC_SINGLE_TLV("Speaker Volume", MAX98927_R003C_SPK_GAIN, 0, 6, 0, 60062306a36Sopenharmony_ci max98927_spk_tlv), 60162306a36Sopenharmony_ci SOC_SINGLE_TLV("Digital Volume", MAX98927_R0036_AMP_VOL_CTRL, 60262306a36Sopenharmony_ci 0, (1 << MAX98927_AMP_VOL_WIDTH) - 1, 0, 60362306a36Sopenharmony_ci max98927_digital_tlv), 60462306a36Sopenharmony_ci SOC_SINGLE("Amp DSP Switch", MAX98927_R0052_BROWNOUT_EN, 60562306a36Sopenharmony_ci MAX98927_BROWNOUT_DSP_SHIFT, 1, 0), 60662306a36Sopenharmony_ci SOC_SINGLE("Ramp Switch", MAX98927_R0037_AMP_DSP_CFG, 60762306a36Sopenharmony_ci MAX98927_AMP_DSP_CFG_RMP_SHIFT, 1, 0), 60862306a36Sopenharmony_ci SOC_SINGLE("DRE Switch", MAX98927_R0039_DRE_CTRL, MAX98927_DRE_EN_SHIFT, 60962306a36Sopenharmony_ci 1, 0), 61062306a36Sopenharmony_ci SOC_SINGLE("Volume Location Switch", MAX98927_R0036_AMP_VOL_CTRL, 61162306a36Sopenharmony_ci MAX98927_AMP_VOL_SEL_SHIFT, 1, 0), 61262306a36Sopenharmony_ci SOC_ENUM("Boost Output Voltage", max98927_boost_voltage), 61362306a36Sopenharmony_ci SOC_ENUM("Current Limit", max98927_current_limit), 61462306a36Sopenharmony_ci}; 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_cistatic const struct snd_soc_dapm_route max98927_audio_map[] = { 61762306a36Sopenharmony_ci /* Plabyack */ 61862306a36Sopenharmony_ci {"DAI Sel Mux", "Left", "Amp Enable"}, 61962306a36Sopenharmony_ci {"DAI Sel Mux", "Right", "Amp Enable"}, 62062306a36Sopenharmony_ci {"DAI Sel Mux", "LeftRight", "Amp Enable"}, 62162306a36Sopenharmony_ci {"BE_OUT", NULL, "DAI Sel Mux"}, 62262306a36Sopenharmony_ci /* Capture */ 62362306a36Sopenharmony_ci { "VI Sense", "Switch", "VMON" }, 62462306a36Sopenharmony_ci { "VI Sense", "Switch", "IMON" }, 62562306a36Sopenharmony_ci { "Voltage Sense", NULL, "VI Sense" }, 62662306a36Sopenharmony_ci { "Current Sense", NULL, "VI Sense" }, 62762306a36Sopenharmony_ci}; 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_cistatic struct snd_soc_dai_driver max98927_dai[] = { 63062306a36Sopenharmony_ci { 63162306a36Sopenharmony_ci .name = "max98927-aif1", 63262306a36Sopenharmony_ci .playback = { 63362306a36Sopenharmony_ci .stream_name = "HiFi Playback", 63462306a36Sopenharmony_ci .channels_min = 1, 63562306a36Sopenharmony_ci .channels_max = 2, 63662306a36Sopenharmony_ci .rates = MAX98927_RATES, 63762306a36Sopenharmony_ci .formats = MAX98927_FORMATS, 63862306a36Sopenharmony_ci }, 63962306a36Sopenharmony_ci .capture = { 64062306a36Sopenharmony_ci .stream_name = "HiFi Capture", 64162306a36Sopenharmony_ci .channels_min = 1, 64262306a36Sopenharmony_ci .channels_max = 2, 64362306a36Sopenharmony_ci .rates = MAX98927_RATES, 64462306a36Sopenharmony_ci .formats = MAX98927_FORMATS, 64562306a36Sopenharmony_ci }, 64662306a36Sopenharmony_ci .ops = &max98927_dai_ops, 64762306a36Sopenharmony_ci } 64862306a36Sopenharmony_ci}; 64962306a36Sopenharmony_ci 65062306a36Sopenharmony_cistatic int max98927_probe(struct snd_soc_component *component) 65162306a36Sopenharmony_ci{ 65262306a36Sopenharmony_ci struct max98927_priv *max98927 = snd_soc_component_get_drvdata(component); 65362306a36Sopenharmony_ci 65462306a36Sopenharmony_ci max98927->component = component; 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_ci /* Software Reset */ 65762306a36Sopenharmony_ci regmap_write(max98927->regmap, MAX98927_R0100_SOFT_RESET, 65862306a36Sopenharmony_ci MAX98927_SOFT_RESET); 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci /* IV default slot configuration */ 66162306a36Sopenharmony_ci regmap_write(max98927->regmap, MAX98927_R001C_PCM_TX_HIZ_CTRL_A, 0xFF); 66262306a36Sopenharmony_ci regmap_write(max98927->regmap, MAX98927_R001D_PCM_TX_HIZ_CTRL_B, 0xFF); 66362306a36Sopenharmony_ci regmap_write(max98927->regmap, MAX98927_R0025_PCM_TO_SPK_MONOMIX_A, 66462306a36Sopenharmony_ci 0x80); 66562306a36Sopenharmony_ci regmap_write(max98927->regmap, MAX98927_R0026_PCM_TO_SPK_MONOMIX_B, 66662306a36Sopenharmony_ci 0x1); 66762306a36Sopenharmony_ci /* Set inital volume (+13dB) */ 66862306a36Sopenharmony_ci regmap_write(max98927->regmap, MAX98927_R0036_AMP_VOL_CTRL, 0x38); 66962306a36Sopenharmony_ci regmap_write(max98927->regmap, MAX98927_R003C_SPK_GAIN, 0x05); 67062306a36Sopenharmony_ci /* Enable DC blocker */ 67162306a36Sopenharmony_ci regmap_write(max98927->regmap, MAX98927_R0037_AMP_DSP_CFG, 0x03); 67262306a36Sopenharmony_ci /* Enable IMON VMON DC blocker */ 67362306a36Sopenharmony_ci regmap_write(max98927->regmap, MAX98927_R003F_MEAS_DSP_CFG, 0xF7); 67462306a36Sopenharmony_ci /* Boost Output Voltage & Current limit */ 67562306a36Sopenharmony_ci regmap_write(max98927->regmap, MAX98927_R0040_BOOST_CTRL0, 0x1C); 67662306a36Sopenharmony_ci regmap_write(max98927->regmap, MAX98927_R0042_BOOST_CTRL1, 0x3E); 67762306a36Sopenharmony_ci /* Measurement ADC config */ 67862306a36Sopenharmony_ci regmap_write(max98927->regmap, MAX98927_R0043_MEAS_ADC_CFG, 0x04); 67962306a36Sopenharmony_ci regmap_write(max98927->regmap, MAX98927_R0044_MEAS_ADC_BASE_MSB, 0x00); 68062306a36Sopenharmony_ci regmap_write(max98927->regmap, MAX98927_R0045_MEAS_ADC_BASE_LSB, 0x24); 68162306a36Sopenharmony_ci /* Brownout Level */ 68262306a36Sopenharmony_ci regmap_write(max98927->regmap, MAX98927_R007F_BROWNOUT_LVL4_AMP1_CTRL1, 68362306a36Sopenharmony_ci 0x06); 68462306a36Sopenharmony_ci /* Envelope Tracking configuration */ 68562306a36Sopenharmony_ci regmap_write(max98927->regmap, MAX98927_R0082_ENV_TRACK_VOUT_HEADROOM, 68662306a36Sopenharmony_ci 0x08); 68762306a36Sopenharmony_ci regmap_write(max98927->regmap, MAX98927_R0086_ENV_TRACK_CTRL, 0x01); 68862306a36Sopenharmony_ci regmap_write(max98927->regmap, MAX98927_R0087_ENV_TRACK_BOOST_VOUT_READ, 68962306a36Sopenharmony_ci 0x10); 69062306a36Sopenharmony_ci 69162306a36Sopenharmony_ci /* voltage, current slot configuration */ 69262306a36Sopenharmony_ci regmap_write(max98927->regmap, MAX98927_R001E_PCM_TX_CH_SRC_A, 69362306a36Sopenharmony_ci (max98927->i_l_slot << MAX98927_PCM_TX_CH_SRC_A_I_SHIFT | max98927->v_l_slot) & 0xFF); 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_ci if (max98927->v_l_slot < 8) { 69662306a36Sopenharmony_ci regmap_update_bits(max98927->regmap, 69762306a36Sopenharmony_ci MAX98927_R001C_PCM_TX_HIZ_CTRL_A, 69862306a36Sopenharmony_ci 1 << max98927->v_l_slot, 0); 69962306a36Sopenharmony_ci regmap_update_bits(max98927->regmap, MAX98927_R001A_PCM_TX_EN_A, 70062306a36Sopenharmony_ci 1 << max98927->v_l_slot, 70162306a36Sopenharmony_ci 1 << max98927->v_l_slot); 70262306a36Sopenharmony_ci } else { 70362306a36Sopenharmony_ci regmap_update_bits(max98927->regmap, 70462306a36Sopenharmony_ci MAX98927_R001D_PCM_TX_HIZ_CTRL_B, 70562306a36Sopenharmony_ci 1 << (max98927->v_l_slot - 8), 0); 70662306a36Sopenharmony_ci regmap_update_bits(max98927->regmap, MAX98927_R001B_PCM_TX_EN_B, 70762306a36Sopenharmony_ci 1 << (max98927->v_l_slot - 8), 70862306a36Sopenharmony_ci 1 << (max98927->v_l_slot - 8)); 70962306a36Sopenharmony_ci } 71062306a36Sopenharmony_ci 71162306a36Sopenharmony_ci if (max98927->i_l_slot < 8) { 71262306a36Sopenharmony_ci regmap_update_bits(max98927->regmap, 71362306a36Sopenharmony_ci MAX98927_R001C_PCM_TX_HIZ_CTRL_A, 71462306a36Sopenharmony_ci 1 << max98927->i_l_slot, 0); 71562306a36Sopenharmony_ci regmap_update_bits(max98927->regmap, MAX98927_R001A_PCM_TX_EN_A, 71662306a36Sopenharmony_ci 1 << max98927->i_l_slot, 71762306a36Sopenharmony_ci 1 << max98927->i_l_slot); 71862306a36Sopenharmony_ci } else { 71962306a36Sopenharmony_ci regmap_update_bits(max98927->regmap, 72062306a36Sopenharmony_ci MAX98927_R001D_PCM_TX_HIZ_CTRL_B, 72162306a36Sopenharmony_ci 1 << (max98927->i_l_slot - 8), 0); 72262306a36Sopenharmony_ci regmap_update_bits(max98927->regmap, MAX98927_R001B_PCM_TX_EN_B, 72362306a36Sopenharmony_ci 1 << (max98927->i_l_slot - 8), 72462306a36Sopenharmony_ci 1 << (max98927->i_l_slot - 8)); 72562306a36Sopenharmony_ci } 72662306a36Sopenharmony_ci 72762306a36Sopenharmony_ci /* Set interleave mode */ 72862306a36Sopenharmony_ci if (max98927->interleave_mode) 72962306a36Sopenharmony_ci regmap_update_bits(max98927->regmap, 73062306a36Sopenharmony_ci MAX98927_R001F_PCM_TX_CH_SRC_B, 73162306a36Sopenharmony_ci MAX98927_PCM_TX_CH_INTERLEAVE_MASK, 73262306a36Sopenharmony_ci MAX98927_PCM_TX_CH_INTERLEAVE_MASK); 73362306a36Sopenharmony_ci return 0; 73462306a36Sopenharmony_ci} 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 73762306a36Sopenharmony_cistatic int max98927_suspend(struct device *dev) 73862306a36Sopenharmony_ci{ 73962306a36Sopenharmony_ci struct max98927_priv *max98927 = dev_get_drvdata(dev); 74062306a36Sopenharmony_ci 74162306a36Sopenharmony_ci regcache_cache_only(max98927->regmap, true); 74262306a36Sopenharmony_ci regcache_mark_dirty(max98927->regmap); 74362306a36Sopenharmony_ci return 0; 74462306a36Sopenharmony_ci} 74562306a36Sopenharmony_cistatic int max98927_resume(struct device *dev) 74662306a36Sopenharmony_ci{ 74762306a36Sopenharmony_ci struct max98927_priv *max98927 = dev_get_drvdata(dev); 74862306a36Sopenharmony_ci 74962306a36Sopenharmony_ci regmap_write(max98927->regmap, MAX98927_R0100_SOFT_RESET, 75062306a36Sopenharmony_ci MAX98927_SOFT_RESET); 75162306a36Sopenharmony_ci regcache_cache_only(max98927->regmap, false); 75262306a36Sopenharmony_ci regcache_sync(max98927->regmap); 75362306a36Sopenharmony_ci return 0; 75462306a36Sopenharmony_ci} 75562306a36Sopenharmony_ci#endif 75662306a36Sopenharmony_ci 75762306a36Sopenharmony_cistatic const struct dev_pm_ops max98927_pm = { 75862306a36Sopenharmony_ci SET_SYSTEM_SLEEP_PM_OPS(max98927_suspend, max98927_resume) 75962306a36Sopenharmony_ci}; 76062306a36Sopenharmony_ci 76162306a36Sopenharmony_cistatic const struct snd_soc_component_driver soc_component_dev_max98927 = { 76262306a36Sopenharmony_ci .probe = max98927_probe, 76362306a36Sopenharmony_ci .controls = max98927_snd_controls, 76462306a36Sopenharmony_ci .num_controls = ARRAY_SIZE(max98927_snd_controls), 76562306a36Sopenharmony_ci .dapm_widgets = max98927_dapm_widgets, 76662306a36Sopenharmony_ci .num_dapm_widgets = ARRAY_SIZE(max98927_dapm_widgets), 76762306a36Sopenharmony_ci .dapm_routes = max98927_audio_map, 76862306a36Sopenharmony_ci .num_dapm_routes = ARRAY_SIZE(max98927_audio_map), 76962306a36Sopenharmony_ci .idle_bias_on = 1, 77062306a36Sopenharmony_ci .use_pmdown_time = 1, 77162306a36Sopenharmony_ci .endianness = 1, 77262306a36Sopenharmony_ci}; 77362306a36Sopenharmony_ci 77462306a36Sopenharmony_cistatic const struct regmap_config max98927_regmap = { 77562306a36Sopenharmony_ci .reg_bits = 16, 77662306a36Sopenharmony_ci .val_bits = 8, 77762306a36Sopenharmony_ci .max_register = MAX98927_R01FF_REV_ID, 77862306a36Sopenharmony_ci .reg_defaults = max98927_reg, 77962306a36Sopenharmony_ci .num_reg_defaults = ARRAY_SIZE(max98927_reg), 78062306a36Sopenharmony_ci .readable_reg = max98927_readable_register, 78162306a36Sopenharmony_ci .volatile_reg = max98927_volatile_reg, 78262306a36Sopenharmony_ci .cache_type = REGCACHE_RBTREE, 78362306a36Sopenharmony_ci}; 78462306a36Sopenharmony_ci 78562306a36Sopenharmony_cistatic void max98927_slot_config(struct i2c_client *i2c, 78662306a36Sopenharmony_ci struct max98927_priv *max98927) 78762306a36Sopenharmony_ci{ 78862306a36Sopenharmony_ci int value; 78962306a36Sopenharmony_ci struct device *dev = &i2c->dev; 79062306a36Sopenharmony_ci 79162306a36Sopenharmony_ci if (!device_property_read_u32(dev, "vmon-slot-no", &value)) 79262306a36Sopenharmony_ci max98927->v_l_slot = value & 0xF; 79362306a36Sopenharmony_ci else 79462306a36Sopenharmony_ci max98927->v_l_slot = 0; 79562306a36Sopenharmony_ci 79662306a36Sopenharmony_ci if (!device_property_read_u32(dev, "imon-slot-no", &value)) 79762306a36Sopenharmony_ci max98927->i_l_slot = value & 0xF; 79862306a36Sopenharmony_ci else 79962306a36Sopenharmony_ci max98927->i_l_slot = 1; 80062306a36Sopenharmony_ci} 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_cistatic int max98927_i2c_probe(struct i2c_client *i2c) 80362306a36Sopenharmony_ci{ 80462306a36Sopenharmony_ci 80562306a36Sopenharmony_ci int ret = 0, value; 80662306a36Sopenharmony_ci int reg = 0; 80762306a36Sopenharmony_ci struct max98927_priv *max98927 = NULL; 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_ci max98927 = devm_kzalloc(&i2c->dev, sizeof(*max98927), GFP_KERNEL); 81062306a36Sopenharmony_ci if (!max98927) { 81162306a36Sopenharmony_ci ret = -ENOMEM; 81262306a36Sopenharmony_ci return ret; 81362306a36Sopenharmony_ci } 81462306a36Sopenharmony_ci i2c_set_clientdata(i2c, max98927); 81562306a36Sopenharmony_ci 81662306a36Sopenharmony_ci /* update interleave mode info */ 81762306a36Sopenharmony_ci if (of_property_read_bool(i2c->dev.of_node, "maxim,interleave-mode")) { 81862306a36Sopenharmony_ci max98927->interleave_mode = true; 81962306a36Sopenharmony_ci } else { 82062306a36Sopenharmony_ci if (!of_property_read_u32(i2c->dev.of_node, "interleave_mode", 82162306a36Sopenharmony_ci &value)) 82262306a36Sopenharmony_ci if (value > 0) 82362306a36Sopenharmony_ci max98927->interleave_mode = true; 82462306a36Sopenharmony_ci } 82562306a36Sopenharmony_ci 82662306a36Sopenharmony_ci /* regmap initialization */ 82762306a36Sopenharmony_ci max98927->regmap 82862306a36Sopenharmony_ci = devm_regmap_init_i2c(i2c, &max98927_regmap); 82962306a36Sopenharmony_ci if (IS_ERR(max98927->regmap)) { 83062306a36Sopenharmony_ci ret = PTR_ERR(max98927->regmap); 83162306a36Sopenharmony_ci dev_err(&i2c->dev, 83262306a36Sopenharmony_ci "Failed to allocate regmap: %d\n", ret); 83362306a36Sopenharmony_ci return ret; 83462306a36Sopenharmony_ci } 83562306a36Sopenharmony_ci 83662306a36Sopenharmony_ci max98927->reset_gpio = devm_gpiod_get_optional(&i2c->dev, "reset", 83762306a36Sopenharmony_ci GPIOD_OUT_HIGH); 83862306a36Sopenharmony_ci if (IS_ERR(max98927->reset_gpio)) { 83962306a36Sopenharmony_ci ret = PTR_ERR(max98927->reset_gpio); 84062306a36Sopenharmony_ci return dev_err_probe(&i2c->dev, ret, "failed to request GPIO reset pin"); 84162306a36Sopenharmony_ci } 84262306a36Sopenharmony_ci 84362306a36Sopenharmony_ci if (max98927->reset_gpio) { 84462306a36Sopenharmony_ci gpiod_set_value_cansleep(max98927->reset_gpio, 0); 84562306a36Sopenharmony_ci /* Wait for i2c port to be ready */ 84662306a36Sopenharmony_ci usleep_range(5000, 6000); 84762306a36Sopenharmony_ci } 84862306a36Sopenharmony_ci 84962306a36Sopenharmony_ci /* Check Revision ID */ 85062306a36Sopenharmony_ci ret = regmap_read(max98927->regmap, MAX98927_R01FF_REV_ID, ®); 85162306a36Sopenharmony_ci if (ret < 0) { 85262306a36Sopenharmony_ci dev_err(&i2c->dev, 85362306a36Sopenharmony_ci "Failed to read: 0x%02X\n", MAX98927_R01FF_REV_ID); 85462306a36Sopenharmony_ci return ret; 85562306a36Sopenharmony_ci } 85662306a36Sopenharmony_ci dev_info(&i2c->dev, "MAX98927 revisionID: 0x%02X\n", reg); 85762306a36Sopenharmony_ci 85862306a36Sopenharmony_ci /* voltage/current slot configuration */ 85962306a36Sopenharmony_ci max98927_slot_config(i2c, max98927); 86062306a36Sopenharmony_ci 86162306a36Sopenharmony_ci /* codec registeration */ 86262306a36Sopenharmony_ci ret = devm_snd_soc_register_component(&i2c->dev, 86362306a36Sopenharmony_ci &soc_component_dev_max98927, 86462306a36Sopenharmony_ci max98927_dai, ARRAY_SIZE(max98927_dai)); 86562306a36Sopenharmony_ci if (ret < 0) 86662306a36Sopenharmony_ci dev_err(&i2c->dev, "Failed to register component: %d\n", ret); 86762306a36Sopenharmony_ci 86862306a36Sopenharmony_ci return ret; 86962306a36Sopenharmony_ci} 87062306a36Sopenharmony_ci 87162306a36Sopenharmony_cistatic void max98927_i2c_remove(struct i2c_client *i2c) 87262306a36Sopenharmony_ci{ 87362306a36Sopenharmony_ci struct max98927_priv *max98927 = i2c_get_clientdata(i2c); 87462306a36Sopenharmony_ci 87562306a36Sopenharmony_ci if (max98927->reset_gpio) 87662306a36Sopenharmony_ci gpiod_set_value_cansleep(max98927->reset_gpio, 1); 87762306a36Sopenharmony_ci} 87862306a36Sopenharmony_ci 87962306a36Sopenharmony_cistatic const struct i2c_device_id max98927_i2c_id[] = { 88062306a36Sopenharmony_ci { "max98927", 0}, 88162306a36Sopenharmony_ci { }, 88262306a36Sopenharmony_ci}; 88362306a36Sopenharmony_ci 88462306a36Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, max98927_i2c_id); 88562306a36Sopenharmony_ci 88662306a36Sopenharmony_ci#if defined(CONFIG_OF) 88762306a36Sopenharmony_cistatic const struct of_device_id max98927_of_match[] = { 88862306a36Sopenharmony_ci { .compatible = "maxim,max98927", }, 88962306a36Sopenharmony_ci { } 89062306a36Sopenharmony_ci}; 89162306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, max98927_of_match); 89262306a36Sopenharmony_ci#endif 89362306a36Sopenharmony_ci 89462306a36Sopenharmony_ci#ifdef CONFIG_ACPI 89562306a36Sopenharmony_cistatic const struct acpi_device_id max98927_acpi_match[] = { 89662306a36Sopenharmony_ci { "MX98927", 0 }, 89762306a36Sopenharmony_ci {}, 89862306a36Sopenharmony_ci}; 89962306a36Sopenharmony_ciMODULE_DEVICE_TABLE(acpi, max98927_acpi_match); 90062306a36Sopenharmony_ci#endif 90162306a36Sopenharmony_ci 90262306a36Sopenharmony_cistatic struct i2c_driver max98927_i2c_driver = { 90362306a36Sopenharmony_ci .driver = { 90462306a36Sopenharmony_ci .name = "max98927", 90562306a36Sopenharmony_ci .of_match_table = of_match_ptr(max98927_of_match), 90662306a36Sopenharmony_ci .acpi_match_table = ACPI_PTR(max98927_acpi_match), 90762306a36Sopenharmony_ci .pm = &max98927_pm, 90862306a36Sopenharmony_ci }, 90962306a36Sopenharmony_ci .probe = max98927_i2c_probe, 91062306a36Sopenharmony_ci .remove = max98927_i2c_remove, 91162306a36Sopenharmony_ci .id_table = max98927_i2c_id, 91262306a36Sopenharmony_ci}; 91362306a36Sopenharmony_ci 91462306a36Sopenharmony_cimodule_i2c_driver(max98927_i2c_driver) 91562306a36Sopenharmony_ci 91662306a36Sopenharmony_ciMODULE_DESCRIPTION("ALSA SoC MAX98927 driver"); 91762306a36Sopenharmony_ciMODULE_AUTHOR("Ryan Lee <ryans.lee@maximintegrated.com>"); 91862306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 919