1*a6e3f4f3SSteve Lee // SPDX-License-Identifier: GPL-2.0-or-later 2*a6e3f4f3SSteve Lee /* 3*a6e3f4f3SSteve Lee * max98390.c -- MAX98390 ALSA Soc Audio driver 4*a6e3f4f3SSteve Lee * 5*a6e3f4f3SSteve Lee * Copyright (C) 2020 Maxim Integrated Products 6*a6e3f4f3SSteve Lee * 7*a6e3f4f3SSteve Lee */ 8*a6e3f4f3SSteve Lee 9*a6e3f4f3SSteve Lee #include <linux/acpi.h> 10*a6e3f4f3SSteve Lee #include <linux/cdev.h> 11*a6e3f4f3SSteve Lee #include <linux/dmi.h> 12*a6e3f4f3SSteve Lee #include <linux/firmware.h> 13*a6e3f4f3SSteve Lee #include <linux/gpio.h> 14*a6e3f4f3SSteve Lee #include <linux/i2c.h> 15*a6e3f4f3SSteve Lee #include <linux/module.h> 16*a6e3f4f3SSteve Lee #include <linux/of_gpio.h> 17*a6e3f4f3SSteve Lee #include <linux/regmap.h> 18*a6e3f4f3SSteve Lee #include <linux/slab.h> 19*a6e3f4f3SSteve Lee #include <linux/time.h> 20*a6e3f4f3SSteve Lee #include <sound/pcm.h> 21*a6e3f4f3SSteve Lee #include <sound/pcm_params.h> 22*a6e3f4f3SSteve Lee #include <sound/soc.h> 23*a6e3f4f3SSteve Lee #include <sound/tlv.h> 24*a6e3f4f3SSteve Lee 25*a6e3f4f3SSteve Lee #include "max98390.h" 26*a6e3f4f3SSteve Lee 27*a6e3f4f3SSteve Lee static struct reg_default max98390_reg_defaults[] = { 28*a6e3f4f3SSteve Lee {MAX98390_INT_EN1, 0xf0}, 29*a6e3f4f3SSteve Lee {MAX98390_INT_EN2, 0x00}, 30*a6e3f4f3SSteve Lee {MAX98390_INT_EN3, 0x00}, 31*a6e3f4f3SSteve Lee {MAX98390_INT_FLAG_CLR1, 0x00}, 32*a6e3f4f3SSteve Lee {MAX98390_INT_FLAG_CLR2, 0x00}, 33*a6e3f4f3SSteve Lee {MAX98390_INT_FLAG_CLR3, 0x00}, 34*a6e3f4f3SSteve Lee {MAX98390_IRQ_CTRL, 0x01}, 35*a6e3f4f3SSteve Lee {MAX98390_CLK_MON, 0x6d}, 36*a6e3f4f3SSteve Lee {MAX98390_DAT_MON, 0x03}, 37*a6e3f4f3SSteve Lee {MAX98390_WDOG_CTRL, 0x00}, 38*a6e3f4f3SSteve Lee {MAX98390_WDOG_RST, 0x00}, 39*a6e3f4f3SSteve Lee {MAX98390_MEAS_ADC_THERM_WARN_THRESH, 0x75}, 40*a6e3f4f3SSteve Lee {MAX98390_MEAS_ADC_THERM_SHDN_THRESH, 0x8c}, 41*a6e3f4f3SSteve Lee {MAX98390_MEAS_ADC_THERM_HYSTERESIS, 0x08}, 42*a6e3f4f3SSteve Lee {MAX98390_PIN_CFG, 0x55}, 43*a6e3f4f3SSteve Lee {MAX98390_PCM_RX_EN_A, 0x00}, 44*a6e3f4f3SSteve Lee {MAX98390_PCM_RX_EN_B, 0x00}, 45*a6e3f4f3SSteve Lee {MAX98390_PCM_TX_EN_A, 0x00}, 46*a6e3f4f3SSteve Lee {MAX98390_PCM_TX_EN_B, 0x00}, 47*a6e3f4f3SSteve Lee {MAX98390_PCM_TX_HIZ_CTRL_A, 0xff}, 48*a6e3f4f3SSteve Lee {MAX98390_PCM_TX_HIZ_CTRL_B, 0xff}, 49*a6e3f4f3SSteve Lee {MAX98390_PCM_CH_SRC_1, 0x00}, 50*a6e3f4f3SSteve Lee {MAX98390_PCM_CH_SRC_2, 0x00}, 51*a6e3f4f3SSteve Lee {MAX98390_PCM_CH_SRC_3, 0x00}, 52*a6e3f4f3SSteve Lee {MAX98390_PCM_MODE_CFG, 0xc0}, 53*a6e3f4f3SSteve Lee {MAX98390_PCM_MASTER_MODE, 0x1c}, 54*a6e3f4f3SSteve Lee {MAX98390_PCM_CLK_SETUP, 0x44}, 55*a6e3f4f3SSteve Lee {MAX98390_PCM_SR_SETUP, 0x08}, 56*a6e3f4f3SSteve Lee {MAX98390_ICC_RX_EN_A, 0x00}, 57*a6e3f4f3SSteve Lee {MAX98390_ICC_RX_EN_B, 0x00}, 58*a6e3f4f3SSteve Lee {MAX98390_ICC_TX_EN_A, 0x00}, 59*a6e3f4f3SSteve Lee {MAX98390_ICC_TX_EN_B, 0x00}, 60*a6e3f4f3SSteve Lee {MAX98390_ICC_HIZ_MANUAL_MODE, 0x00}, 61*a6e3f4f3SSteve Lee {MAX98390_ICC_TX_HIZ_EN_A, 0x00}, 62*a6e3f4f3SSteve Lee {MAX98390_ICC_TX_HIZ_EN_B, 0x00}, 63*a6e3f4f3SSteve Lee {MAX98390_ICC_LNK_EN, 0x00}, 64*a6e3f4f3SSteve Lee {MAX98390_R2039_AMP_DSP_CFG, 0x0f}, 65*a6e3f4f3SSteve Lee {MAX98390_R203A_AMP_EN, 0x81}, 66*a6e3f4f3SSteve Lee {MAX98390_TONE_GEN_DC_CFG, 0x00}, 67*a6e3f4f3SSteve Lee {MAX98390_SPK_SRC_SEL, 0x00}, 68*a6e3f4f3SSteve Lee {MAX98390_SSM_CFG, 0x85}, 69*a6e3f4f3SSteve Lee {MAX98390_MEAS_EN, 0x03}, 70*a6e3f4f3SSteve Lee {MAX98390_MEAS_DSP_CFG, 0x0f}, 71*a6e3f4f3SSteve Lee {MAX98390_BOOST_CTRL0, 0x1c}, 72*a6e3f4f3SSteve Lee {MAX98390_BOOST_CTRL3, 0x01}, 73*a6e3f4f3SSteve Lee {MAX98390_BOOST_CTRL1, 0x40}, 74*a6e3f4f3SSteve Lee {MAX98390_MEAS_ADC_CFG, 0x07}, 75*a6e3f4f3SSteve Lee {MAX98390_MEAS_ADC_BASE_MSB, 0x00}, 76*a6e3f4f3SSteve Lee {MAX98390_MEAS_ADC_BASE_LSB, 0x23}, 77*a6e3f4f3SSteve Lee {MAX98390_ADC_CH0_DIVIDE, 0x00}, 78*a6e3f4f3SSteve Lee {MAX98390_ADC_CH1_DIVIDE, 0x00}, 79*a6e3f4f3SSteve Lee {MAX98390_ADC_CH2_DIVIDE, 0x00}, 80*a6e3f4f3SSteve Lee {MAX98390_ADC_CH0_FILT_CFG, 0x00}, 81*a6e3f4f3SSteve Lee {MAX98390_ADC_CH1_FILT_CFG, 0x00}, 82*a6e3f4f3SSteve Lee {MAX98390_ADC_CH2_FILT_CFG, 0x00}, 83*a6e3f4f3SSteve Lee {MAX98390_PWR_GATE_CTL, 0x2c}, 84*a6e3f4f3SSteve Lee {MAX98390_BROWNOUT_EN, 0x00}, 85*a6e3f4f3SSteve Lee {MAX98390_BROWNOUT_INFINITE_HOLD, 0x00}, 86*a6e3f4f3SSteve Lee {MAX98390_BROWNOUT_INFINITE_HOLD_CLR, 0x00}, 87*a6e3f4f3SSteve Lee {MAX98390_BROWNOUT_LVL_HOLD, 0x00}, 88*a6e3f4f3SSteve Lee {MAX98390_BROWNOUT_LVL1_THRESH, 0x00}, 89*a6e3f4f3SSteve Lee {MAX98390_BROWNOUT_LVL2_THRESH, 0x00}, 90*a6e3f4f3SSteve Lee {MAX98390_BROWNOUT_LVL3_THRESH, 0x00}, 91*a6e3f4f3SSteve Lee {MAX98390_BROWNOUT_LVL4_THRESH, 0x00}, 92*a6e3f4f3SSteve Lee {MAX98390_BROWNOUT_THRESH_HYSTERYSIS, 0x00}, 93*a6e3f4f3SSteve Lee {MAX98390_BROWNOUT_AMP_LIMITER_ATK_REL, 0x1f}, 94*a6e3f4f3SSteve Lee {MAX98390_BROWNOUT_AMP_GAIN_ATK_REL, 0x00}, 95*a6e3f4f3SSteve Lee {MAX98390_BROWNOUT_AMP1_CLIP_MODE, 0x00}, 96*a6e3f4f3SSteve Lee {MAX98390_BROWNOUT_LVL1_CUR_LIMIT, 0x00}, 97*a6e3f4f3SSteve Lee {MAX98390_BROWNOUT_LVL1_AMP1_CTRL1, 0x00}, 98*a6e3f4f3SSteve Lee {MAX98390_BROWNOUT_LVL1_AMP1_CTRL2, 0x00}, 99*a6e3f4f3SSteve Lee {MAX98390_BROWNOUT_LVL1_AMP1_CTRL3, 0x00}, 100*a6e3f4f3SSteve Lee {MAX98390_BROWNOUT_LVL2_CUR_LIMIT, 0x00}, 101*a6e3f4f3SSteve Lee {MAX98390_BROWNOUT_LVL2_AMP1_CTRL1, 0x00}, 102*a6e3f4f3SSteve Lee {MAX98390_BROWNOUT_LVL2_AMP1_CTRL2, 0x00}, 103*a6e3f4f3SSteve Lee {MAX98390_BROWNOUT_LVL2_AMP1_CTRL3, 0x00}, 104*a6e3f4f3SSteve Lee {MAX98390_BROWNOUT_LVL3_CUR_LIMIT, 0x00}, 105*a6e3f4f3SSteve Lee {MAX98390_BROWNOUT_LVL3_AMP1_CTRL1, 0x00}, 106*a6e3f4f3SSteve Lee {MAX98390_BROWNOUT_LVL3_AMP1_CTRL2, 0x00}, 107*a6e3f4f3SSteve Lee {MAX98390_BROWNOUT_LVL3_AMP1_CTRL3, 0x00}, 108*a6e3f4f3SSteve Lee {MAX98390_BROWNOUT_LVL4_CUR_LIMIT, 0x00}, 109*a6e3f4f3SSteve Lee {MAX98390_BROWNOUT_LVL4_AMP1_CTRL1, 0x00}, 110*a6e3f4f3SSteve Lee {MAX98390_BROWNOUT_LVL4_AMP1_CTRL2, 0x00}, 111*a6e3f4f3SSteve Lee {MAX98390_BROWNOUT_LVL4_AMP1_CTRL3, 0x00}, 112*a6e3f4f3SSteve Lee {MAX98390_BROWNOUT_ILIM_HLD, 0x00}, 113*a6e3f4f3SSteve Lee {MAX98390_BROWNOUT_LIM_HLD, 0x00}, 114*a6e3f4f3SSteve Lee {MAX98390_BROWNOUT_CLIP_HLD, 0x00}, 115*a6e3f4f3SSteve Lee {MAX98390_BROWNOUT_GAIN_HLD, 0x00}, 116*a6e3f4f3SSteve Lee {MAX98390_ENV_TRACK_VOUT_HEADROOM, 0x0f}, 117*a6e3f4f3SSteve Lee {MAX98390_ENV_TRACK_BOOST_VOUT_DELAY, 0x80}, 118*a6e3f4f3SSteve Lee {MAX98390_ENV_TRACK_REL_RATE, 0x07}, 119*a6e3f4f3SSteve Lee {MAX98390_ENV_TRACK_HOLD_RATE, 0x07}, 120*a6e3f4f3SSteve Lee {MAX98390_ENV_TRACK_CTRL, 0x01}, 121*a6e3f4f3SSteve Lee {MAX98390_BOOST_BYPASS1, 0x49}, 122*a6e3f4f3SSteve Lee {MAX98390_BOOST_BYPASS2, 0x2b}, 123*a6e3f4f3SSteve Lee {MAX98390_BOOST_BYPASS3, 0x08}, 124*a6e3f4f3SSteve Lee {MAX98390_FET_SCALING1, 0x00}, 125*a6e3f4f3SSteve Lee {MAX98390_FET_SCALING2, 0x03}, 126*a6e3f4f3SSteve Lee {MAX98390_FET_SCALING3, 0x00}, 127*a6e3f4f3SSteve Lee {MAX98390_FET_SCALING4, 0x07}, 128*a6e3f4f3SSteve Lee {MAX98390_SPK_SPEEDUP, 0x00}, 129*a6e3f4f3SSteve Lee {DSMIG_WB_DRC_RELEASE_TIME_1, 0x00}, 130*a6e3f4f3SSteve Lee {DSMIG_WB_DRC_RELEASE_TIME_2, 0x00}, 131*a6e3f4f3SSteve Lee {DSMIG_WB_DRC_ATTACK_TIME_1, 0x00}, 132*a6e3f4f3SSteve Lee {DSMIG_WB_DRC_ATTACK_TIME_2, 0x00}, 133*a6e3f4f3SSteve Lee {DSMIG_WB_DRC_COMPRESSION_RATIO, 0x00}, 134*a6e3f4f3SSteve Lee {DSMIG_WB_DRC_COMPRESSION_THRESHOLD, 0x00}, 135*a6e3f4f3SSteve Lee {DSMIG_WB_DRC_MAKEUPGAIN, 0x00}, 136*a6e3f4f3SSteve Lee {DSMIG_WB_DRC_NOISE_GATE_THRESHOLD, 0x00}, 137*a6e3f4f3SSteve Lee {DSMIG_WBDRC_HPF_ENABLE, 0x00}, 138*a6e3f4f3SSteve Lee {DSMIG_WB_DRC_TEST_SMOOTHER_OUT_EN, 0x00}, 139*a6e3f4f3SSteve Lee {DSMIG_PPR_THRESHOLD, 0x00}, 140*a6e3f4f3SSteve Lee {DSM_STEREO_BASS_CHANNEL_SELECT, 0x00}, 141*a6e3f4f3SSteve Lee {DSM_TPROT_THRESHOLD_BYTE0, 0x00}, 142*a6e3f4f3SSteve Lee {DSM_TPROT_THRESHOLD_BYTE1, 0x00}, 143*a6e3f4f3SSteve Lee {DSM_TPROT_ROOM_TEMPERATURE_BYTE0, 0x00}, 144*a6e3f4f3SSteve Lee {DSM_TPROT_ROOM_TEMPERATURE_BYTE1, 0x00}, 145*a6e3f4f3SSteve Lee {DSM_TPROT_RECIP_RDC_ROOM_BYTE0, 0x00}, 146*a6e3f4f3SSteve Lee {DSM_TPROT_RECIP_RDC_ROOM_BYTE1, 0x00}, 147*a6e3f4f3SSteve Lee {DSM_TPROT_RECIP_RDC_ROOM_BYTE2, 0x00}, 148*a6e3f4f3SSteve Lee {DSM_TPROT_RECIP_TCONST_BYTE0, 0x00}, 149*a6e3f4f3SSteve Lee {DSM_TPROT_RECIP_TCONST_BYTE1, 0x00}, 150*a6e3f4f3SSteve Lee {DSM_TPROT_RECIP_TCONST_BYTE2, 0x00}, 151*a6e3f4f3SSteve Lee {DSM_THERMAL_ATTENUATION_SETTINGS, 0x00}, 152*a6e3f4f3SSteve Lee {DSM_THERMAL_PILOT_TONE_ATTENUATION, 0x00}, 153*a6e3f4f3SSteve Lee {DSM_TPROT_PG_TEMP_THRESH_BYTE0, 0x00}, 154*a6e3f4f3SSteve Lee {DSM_TPROT_PG_TEMP_THRESH_BYTE1, 0x00}, 155*a6e3f4f3SSteve Lee {DSMIG_DEBUZZER_THRESHOLD, 0x00}, 156*a6e3f4f3SSteve Lee {DSMIG_DEBUZZER_ALPHA_COEF_TEST_ONLY, 0x08}, 157*a6e3f4f3SSteve Lee {DSM_VOL_ENA, 0x20}, 158*a6e3f4f3SSteve Lee {DSM_VOL_CTRL, 0xa0}, 159*a6e3f4f3SSteve Lee {DSMIG_EN, 0x00}, 160*a6e3f4f3SSteve Lee {MAX98390_R23E1_DSP_GLOBAL_EN, 0x00}, 161*a6e3f4f3SSteve Lee {MAX98390_R23FF_GLOBAL_EN, 0x00}, 162*a6e3f4f3SSteve Lee }; 163*a6e3f4f3SSteve Lee 164*a6e3f4f3SSteve Lee static int max98390_dsm_calibrate(struct snd_soc_component *component); 165*a6e3f4f3SSteve Lee 166*a6e3f4f3SSteve Lee static int max98390_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) 167*a6e3f4f3SSteve Lee { 168*a6e3f4f3SSteve Lee struct snd_soc_component *component = codec_dai->component; 169*a6e3f4f3SSteve Lee struct max98390_priv *max98390 = 170*a6e3f4f3SSteve Lee snd_soc_component_get_drvdata(component); 171*a6e3f4f3SSteve Lee unsigned int mode; 172*a6e3f4f3SSteve Lee unsigned int format; 173*a6e3f4f3SSteve Lee unsigned int invert = 0; 174*a6e3f4f3SSteve Lee 175*a6e3f4f3SSteve Lee dev_dbg(component->dev, "%s: fmt 0x%08X\n", __func__, fmt); 176*a6e3f4f3SSteve Lee 177*a6e3f4f3SSteve Lee switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 178*a6e3f4f3SSteve Lee case SND_SOC_DAIFMT_CBS_CFS: 179*a6e3f4f3SSteve Lee mode = MAX98390_PCM_MASTER_MODE_SLAVE; 180*a6e3f4f3SSteve Lee break; 181*a6e3f4f3SSteve Lee case SND_SOC_DAIFMT_CBM_CFM: 182*a6e3f4f3SSteve Lee max98390->master = true; 183*a6e3f4f3SSteve Lee mode = MAX98390_PCM_MASTER_MODE_MASTER; 184*a6e3f4f3SSteve Lee break; 185*a6e3f4f3SSteve Lee default: 186*a6e3f4f3SSteve Lee dev_err(component->dev, "DAI clock mode unsupported\n"); 187*a6e3f4f3SSteve Lee return -EINVAL; 188*a6e3f4f3SSteve Lee } 189*a6e3f4f3SSteve Lee 190*a6e3f4f3SSteve Lee regmap_update_bits(max98390->regmap, 191*a6e3f4f3SSteve Lee MAX98390_PCM_MASTER_MODE, 192*a6e3f4f3SSteve Lee MAX98390_PCM_MASTER_MODE_MASK, 193*a6e3f4f3SSteve Lee mode); 194*a6e3f4f3SSteve Lee 195*a6e3f4f3SSteve Lee switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 196*a6e3f4f3SSteve Lee case SND_SOC_DAIFMT_NB_NF: 197*a6e3f4f3SSteve Lee break; 198*a6e3f4f3SSteve Lee case SND_SOC_DAIFMT_IB_NF: 199*a6e3f4f3SSteve Lee invert = MAX98390_PCM_MODE_CFG_PCM_BCLKEDGE; 200*a6e3f4f3SSteve Lee break; 201*a6e3f4f3SSteve Lee default: 202*a6e3f4f3SSteve Lee dev_err(component->dev, "DAI invert mode unsupported\n"); 203*a6e3f4f3SSteve Lee return -EINVAL; 204*a6e3f4f3SSteve Lee } 205*a6e3f4f3SSteve Lee 206*a6e3f4f3SSteve Lee regmap_update_bits(max98390->regmap, 207*a6e3f4f3SSteve Lee MAX98390_PCM_MODE_CFG, 208*a6e3f4f3SSteve Lee MAX98390_PCM_MODE_CFG_PCM_BCLKEDGE, 209*a6e3f4f3SSteve Lee invert); 210*a6e3f4f3SSteve Lee 211*a6e3f4f3SSteve Lee /* interface format */ 212*a6e3f4f3SSteve Lee switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 213*a6e3f4f3SSteve Lee case SND_SOC_DAIFMT_I2S: 214*a6e3f4f3SSteve Lee format = MAX98390_PCM_FORMAT_I2S; 215*a6e3f4f3SSteve Lee break; 216*a6e3f4f3SSteve Lee case SND_SOC_DAIFMT_LEFT_J: 217*a6e3f4f3SSteve Lee format = MAX98390_PCM_FORMAT_LJ; 218*a6e3f4f3SSteve Lee break; 219*a6e3f4f3SSteve Lee case SND_SOC_DAIFMT_DSP_A: 220*a6e3f4f3SSteve Lee format = MAX98390_PCM_FORMAT_TDM_MODE1; 221*a6e3f4f3SSteve Lee break; 222*a6e3f4f3SSteve Lee case SND_SOC_DAIFMT_DSP_B: 223*a6e3f4f3SSteve Lee format = MAX98390_PCM_FORMAT_TDM_MODE0; 224*a6e3f4f3SSteve Lee break; 225*a6e3f4f3SSteve Lee default: 226*a6e3f4f3SSteve Lee return -EINVAL; 227*a6e3f4f3SSteve Lee } 228*a6e3f4f3SSteve Lee 229*a6e3f4f3SSteve Lee regmap_update_bits(max98390->regmap, 230*a6e3f4f3SSteve Lee MAX98390_PCM_MODE_CFG, 231*a6e3f4f3SSteve Lee MAX98390_PCM_MODE_CFG_FORMAT_MASK, 232*a6e3f4f3SSteve Lee format << MAX98390_PCM_MODE_CFG_FORMAT_SHIFT); 233*a6e3f4f3SSteve Lee 234*a6e3f4f3SSteve Lee return 0; 235*a6e3f4f3SSteve Lee } 236*a6e3f4f3SSteve Lee 237*a6e3f4f3SSteve Lee static int max98390_get_bclk_sel(int bclk) 238*a6e3f4f3SSteve Lee { 239*a6e3f4f3SSteve Lee int i; 240*a6e3f4f3SSteve Lee /* BCLKs per LRCLK */ 241*a6e3f4f3SSteve Lee static int bclk_sel_table[] = { 242*a6e3f4f3SSteve Lee 32, 48, 64, 96, 128, 192, 256, 320, 384, 512, 243*a6e3f4f3SSteve Lee }; 244*a6e3f4f3SSteve Lee /* match BCLKs per LRCLK */ 245*a6e3f4f3SSteve Lee for (i = 0; i < ARRAY_SIZE(bclk_sel_table); i++) { 246*a6e3f4f3SSteve Lee if (bclk_sel_table[i] == bclk) 247*a6e3f4f3SSteve Lee return i + 2; 248*a6e3f4f3SSteve Lee } 249*a6e3f4f3SSteve Lee return 0; 250*a6e3f4f3SSteve Lee } 251*a6e3f4f3SSteve Lee 252*a6e3f4f3SSteve Lee static int max98390_set_clock(struct snd_soc_component *component, 253*a6e3f4f3SSteve Lee struct snd_pcm_hw_params *params) 254*a6e3f4f3SSteve Lee { 255*a6e3f4f3SSteve Lee struct max98390_priv *max98390 = 256*a6e3f4f3SSteve Lee snd_soc_component_get_drvdata(component); 257*a6e3f4f3SSteve Lee /* codec MCLK rate in master mode */ 258*a6e3f4f3SSteve Lee static int rate_table[] = { 259*a6e3f4f3SSteve Lee 5644800, 6000000, 6144000, 6500000, 260*a6e3f4f3SSteve Lee 9600000, 11289600, 12000000, 12288000, 261*a6e3f4f3SSteve Lee 13000000, 19200000, 262*a6e3f4f3SSteve Lee }; 263*a6e3f4f3SSteve Lee /* BCLK/LRCLK ratio calculation */ 264*a6e3f4f3SSteve Lee int blr_clk_ratio = params_channels(params) 265*a6e3f4f3SSteve Lee * snd_pcm_format_width(params_format(params)); 266*a6e3f4f3SSteve Lee int value; 267*a6e3f4f3SSteve Lee 268*a6e3f4f3SSteve Lee if (max98390->master) { 269*a6e3f4f3SSteve Lee int i; 270*a6e3f4f3SSteve Lee /* match rate to closest value */ 271*a6e3f4f3SSteve Lee for (i = 0; i < ARRAY_SIZE(rate_table); i++) { 272*a6e3f4f3SSteve Lee if (rate_table[i] >= max98390->sysclk) 273*a6e3f4f3SSteve Lee break; 274*a6e3f4f3SSteve Lee } 275*a6e3f4f3SSteve Lee if (i == ARRAY_SIZE(rate_table)) { 276*a6e3f4f3SSteve Lee dev_err(component->dev, "failed to find proper clock rate.\n"); 277*a6e3f4f3SSteve Lee return -EINVAL; 278*a6e3f4f3SSteve Lee } 279*a6e3f4f3SSteve Lee 280*a6e3f4f3SSteve Lee regmap_update_bits(max98390->regmap, 281*a6e3f4f3SSteve Lee MAX98390_PCM_MASTER_MODE, 282*a6e3f4f3SSteve Lee MAX98390_PCM_MASTER_MODE_MCLK_MASK, 283*a6e3f4f3SSteve Lee i << MAX98390_PCM_MASTER_MODE_MCLK_RATE_SHIFT); 284*a6e3f4f3SSteve Lee } 285*a6e3f4f3SSteve Lee 286*a6e3f4f3SSteve Lee if (!max98390->tdm_mode) { 287*a6e3f4f3SSteve Lee /* BCLK configuration */ 288*a6e3f4f3SSteve Lee value = max98390_get_bclk_sel(blr_clk_ratio); 289*a6e3f4f3SSteve Lee if (!value) { 290*a6e3f4f3SSteve Lee dev_err(component->dev, "format unsupported %d\n", 291*a6e3f4f3SSteve Lee params_format(params)); 292*a6e3f4f3SSteve Lee return -EINVAL; 293*a6e3f4f3SSteve Lee } 294*a6e3f4f3SSteve Lee 295*a6e3f4f3SSteve Lee regmap_update_bits(max98390->regmap, 296*a6e3f4f3SSteve Lee MAX98390_PCM_CLK_SETUP, 297*a6e3f4f3SSteve Lee MAX98390_PCM_CLK_SETUP_BSEL_MASK, 298*a6e3f4f3SSteve Lee value); 299*a6e3f4f3SSteve Lee } 300*a6e3f4f3SSteve Lee return 0; 301*a6e3f4f3SSteve Lee } 302*a6e3f4f3SSteve Lee 303*a6e3f4f3SSteve Lee static int max98390_dai_hw_params(struct snd_pcm_substream *substream, 304*a6e3f4f3SSteve Lee struct snd_pcm_hw_params *params, 305*a6e3f4f3SSteve Lee struct snd_soc_dai *dai) 306*a6e3f4f3SSteve Lee { 307*a6e3f4f3SSteve Lee struct snd_soc_component *component = 308*a6e3f4f3SSteve Lee dai->component; 309*a6e3f4f3SSteve Lee struct max98390_priv *max98390 = 310*a6e3f4f3SSteve Lee snd_soc_component_get_drvdata(component); 311*a6e3f4f3SSteve Lee 312*a6e3f4f3SSteve Lee unsigned int sampling_rate; 313*a6e3f4f3SSteve Lee unsigned int chan_sz; 314*a6e3f4f3SSteve Lee 315*a6e3f4f3SSteve Lee /* pcm mode configuration */ 316*a6e3f4f3SSteve Lee switch (snd_pcm_format_width(params_format(params))) { 317*a6e3f4f3SSteve Lee case 16: 318*a6e3f4f3SSteve Lee chan_sz = MAX98390_PCM_MODE_CFG_CHANSZ_16; 319*a6e3f4f3SSteve Lee break; 320*a6e3f4f3SSteve Lee case 24: 321*a6e3f4f3SSteve Lee chan_sz = MAX98390_PCM_MODE_CFG_CHANSZ_24; 322*a6e3f4f3SSteve Lee break; 323*a6e3f4f3SSteve Lee case 32: 324*a6e3f4f3SSteve Lee chan_sz = MAX98390_PCM_MODE_CFG_CHANSZ_32; 325*a6e3f4f3SSteve Lee break; 326*a6e3f4f3SSteve Lee default: 327*a6e3f4f3SSteve Lee dev_err(component->dev, "format unsupported %d\n", 328*a6e3f4f3SSteve Lee params_format(params)); 329*a6e3f4f3SSteve Lee goto err; 330*a6e3f4f3SSteve Lee } 331*a6e3f4f3SSteve Lee 332*a6e3f4f3SSteve Lee regmap_update_bits(max98390->regmap, 333*a6e3f4f3SSteve Lee MAX98390_PCM_MODE_CFG, 334*a6e3f4f3SSteve Lee MAX98390_PCM_MODE_CFG_CHANSZ_MASK, chan_sz); 335*a6e3f4f3SSteve Lee 336*a6e3f4f3SSteve Lee dev_dbg(component->dev, "format supported %d", 337*a6e3f4f3SSteve Lee params_format(params)); 338*a6e3f4f3SSteve Lee 339*a6e3f4f3SSteve Lee /* sampling rate configuration */ 340*a6e3f4f3SSteve Lee switch (params_rate(params)) { 341*a6e3f4f3SSteve Lee case 8000: 342*a6e3f4f3SSteve Lee sampling_rate = MAX98390_PCM_SR_SET1_SR_8000; 343*a6e3f4f3SSteve Lee break; 344*a6e3f4f3SSteve Lee case 11025: 345*a6e3f4f3SSteve Lee sampling_rate = MAX98390_PCM_SR_SET1_SR_11025; 346*a6e3f4f3SSteve Lee break; 347*a6e3f4f3SSteve Lee case 12000: 348*a6e3f4f3SSteve Lee sampling_rate = MAX98390_PCM_SR_SET1_SR_12000; 349*a6e3f4f3SSteve Lee break; 350*a6e3f4f3SSteve Lee case 16000: 351*a6e3f4f3SSteve Lee sampling_rate = MAX98390_PCM_SR_SET1_SR_16000; 352*a6e3f4f3SSteve Lee break; 353*a6e3f4f3SSteve Lee case 22050: 354*a6e3f4f3SSteve Lee sampling_rate = MAX98390_PCM_SR_SET1_SR_22050; 355*a6e3f4f3SSteve Lee break; 356*a6e3f4f3SSteve Lee case 24000: 357*a6e3f4f3SSteve Lee sampling_rate = MAX98390_PCM_SR_SET1_SR_24000; 358*a6e3f4f3SSteve Lee break; 359*a6e3f4f3SSteve Lee case 32000: 360*a6e3f4f3SSteve Lee sampling_rate = MAX98390_PCM_SR_SET1_SR_32000; 361*a6e3f4f3SSteve Lee break; 362*a6e3f4f3SSteve Lee case 44100: 363*a6e3f4f3SSteve Lee sampling_rate = MAX98390_PCM_SR_SET1_SR_44100; 364*a6e3f4f3SSteve Lee break; 365*a6e3f4f3SSteve Lee case 48000: 366*a6e3f4f3SSteve Lee sampling_rate = MAX98390_PCM_SR_SET1_SR_48000; 367*a6e3f4f3SSteve Lee break; 368*a6e3f4f3SSteve Lee default: 369*a6e3f4f3SSteve Lee dev_err(component->dev, "rate %d not supported\n", 370*a6e3f4f3SSteve Lee params_rate(params)); 371*a6e3f4f3SSteve Lee goto err; 372*a6e3f4f3SSteve Lee } 373*a6e3f4f3SSteve Lee 374*a6e3f4f3SSteve Lee /* set DAI_SR to correct LRCLK frequency */ 375*a6e3f4f3SSteve Lee regmap_update_bits(max98390->regmap, 376*a6e3f4f3SSteve Lee MAX98390_PCM_SR_SETUP, 377*a6e3f4f3SSteve Lee MAX98390_PCM_SR_SET1_SR_MASK, 378*a6e3f4f3SSteve Lee sampling_rate); 379*a6e3f4f3SSteve Lee 380*a6e3f4f3SSteve Lee return max98390_set_clock(component, params); 381*a6e3f4f3SSteve Lee err: 382*a6e3f4f3SSteve Lee return -EINVAL; 383*a6e3f4f3SSteve Lee } 384*a6e3f4f3SSteve Lee 385*a6e3f4f3SSteve Lee static int max98390_dai_tdm_slot(struct snd_soc_dai *dai, 386*a6e3f4f3SSteve Lee unsigned int tx_mask, unsigned int rx_mask, 387*a6e3f4f3SSteve Lee int slots, int slot_width) 388*a6e3f4f3SSteve Lee { 389*a6e3f4f3SSteve Lee struct snd_soc_component *component = dai->component; 390*a6e3f4f3SSteve Lee struct max98390_priv *max98390 = 391*a6e3f4f3SSteve Lee snd_soc_component_get_drvdata(component); 392*a6e3f4f3SSteve Lee 393*a6e3f4f3SSteve Lee int bsel; 394*a6e3f4f3SSteve Lee unsigned int chan_sz; 395*a6e3f4f3SSteve Lee 396*a6e3f4f3SSteve Lee if (!tx_mask && !rx_mask && !slots && !slot_width) 397*a6e3f4f3SSteve Lee max98390->tdm_mode = false; 398*a6e3f4f3SSteve Lee else 399*a6e3f4f3SSteve Lee max98390->tdm_mode = true; 400*a6e3f4f3SSteve Lee 401*a6e3f4f3SSteve Lee dev_dbg(component->dev, 402*a6e3f4f3SSteve Lee "Tdm mode : %d\n", max98390->tdm_mode); 403*a6e3f4f3SSteve Lee 404*a6e3f4f3SSteve Lee /* BCLK configuration */ 405*a6e3f4f3SSteve Lee bsel = max98390_get_bclk_sel(slots * slot_width); 406*a6e3f4f3SSteve Lee if (!bsel) { 407*a6e3f4f3SSteve Lee dev_err(component->dev, "BCLK %d not supported\n", 408*a6e3f4f3SSteve Lee slots * slot_width); 409*a6e3f4f3SSteve Lee return -EINVAL; 410*a6e3f4f3SSteve Lee } 411*a6e3f4f3SSteve Lee 412*a6e3f4f3SSteve Lee regmap_update_bits(max98390->regmap, 413*a6e3f4f3SSteve Lee MAX98390_PCM_CLK_SETUP, 414*a6e3f4f3SSteve Lee MAX98390_PCM_CLK_SETUP_BSEL_MASK, 415*a6e3f4f3SSteve Lee bsel); 416*a6e3f4f3SSteve Lee 417*a6e3f4f3SSteve Lee /* Channel size configuration */ 418*a6e3f4f3SSteve Lee switch (slot_width) { 419*a6e3f4f3SSteve Lee case 16: 420*a6e3f4f3SSteve Lee chan_sz = MAX98390_PCM_MODE_CFG_CHANSZ_16; 421*a6e3f4f3SSteve Lee break; 422*a6e3f4f3SSteve Lee case 24: 423*a6e3f4f3SSteve Lee chan_sz = MAX98390_PCM_MODE_CFG_CHANSZ_24; 424*a6e3f4f3SSteve Lee break; 425*a6e3f4f3SSteve Lee case 32: 426*a6e3f4f3SSteve Lee chan_sz = MAX98390_PCM_MODE_CFG_CHANSZ_32; 427*a6e3f4f3SSteve Lee break; 428*a6e3f4f3SSteve Lee default: 429*a6e3f4f3SSteve Lee dev_err(component->dev, "format unsupported %d\n", 430*a6e3f4f3SSteve Lee slot_width); 431*a6e3f4f3SSteve Lee return -EINVAL; 432*a6e3f4f3SSteve Lee } 433*a6e3f4f3SSteve Lee 434*a6e3f4f3SSteve Lee regmap_update_bits(max98390->regmap, 435*a6e3f4f3SSteve Lee MAX98390_PCM_MODE_CFG, 436*a6e3f4f3SSteve Lee MAX98390_PCM_MODE_CFG_CHANSZ_MASK, chan_sz); 437*a6e3f4f3SSteve Lee 438*a6e3f4f3SSteve Lee /* Rx slot configuration */ 439*a6e3f4f3SSteve Lee regmap_write(max98390->regmap, 440*a6e3f4f3SSteve Lee MAX98390_PCM_RX_EN_A, 441*a6e3f4f3SSteve Lee rx_mask & 0xFF); 442*a6e3f4f3SSteve Lee regmap_write(max98390->regmap, 443*a6e3f4f3SSteve Lee MAX98390_PCM_RX_EN_B, 444*a6e3f4f3SSteve Lee (rx_mask & 0xFF00) >> 8); 445*a6e3f4f3SSteve Lee 446*a6e3f4f3SSteve Lee /* Tx slot Hi-Z configuration */ 447*a6e3f4f3SSteve Lee regmap_write(max98390->regmap, 448*a6e3f4f3SSteve Lee MAX98390_PCM_TX_HIZ_CTRL_A, 449*a6e3f4f3SSteve Lee ~tx_mask & 0xFF); 450*a6e3f4f3SSteve Lee regmap_write(max98390->regmap, 451*a6e3f4f3SSteve Lee MAX98390_PCM_TX_HIZ_CTRL_B, 452*a6e3f4f3SSteve Lee (~tx_mask & 0xFF00) >> 8); 453*a6e3f4f3SSteve Lee 454*a6e3f4f3SSteve Lee return 0; 455*a6e3f4f3SSteve Lee } 456*a6e3f4f3SSteve Lee 457*a6e3f4f3SSteve Lee static int max98390_dai_set_sysclk(struct snd_soc_dai *dai, 458*a6e3f4f3SSteve Lee int clk_id, unsigned int freq, int dir) 459*a6e3f4f3SSteve Lee { 460*a6e3f4f3SSteve Lee struct snd_soc_component *component = dai->component; 461*a6e3f4f3SSteve Lee struct max98390_priv *max98390 = 462*a6e3f4f3SSteve Lee snd_soc_component_get_drvdata(component); 463*a6e3f4f3SSteve Lee 464*a6e3f4f3SSteve Lee max98390->sysclk = freq; 465*a6e3f4f3SSteve Lee return 0; 466*a6e3f4f3SSteve Lee } 467*a6e3f4f3SSteve Lee 468*a6e3f4f3SSteve Lee static const struct snd_soc_dai_ops max98390_dai_ops = { 469*a6e3f4f3SSteve Lee .set_sysclk = max98390_dai_set_sysclk, 470*a6e3f4f3SSteve Lee .set_fmt = max98390_dai_set_fmt, 471*a6e3f4f3SSteve Lee .hw_params = max98390_dai_hw_params, 472*a6e3f4f3SSteve Lee .set_tdm_slot = max98390_dai_tdm_slot, 473*a6e3f4f3SSteve Lee }; 474*a6e3f4f3SSteve Lee 475*a6e3f4f3SSteve Lee static int max98390_dac_event(struct snd_soc_dapm_widget *w, 476*a6e3f4f3SSteve Lee struct snd_kcontrol *kcontrol, int event) 477*a6e3f4f3SSteve Lee { 478*a6e3f4f3SSteve Lee struct snd_soc_component *component = 479*a6e3f4f3SSteve Lee snd_soc_dapm_to_component(w->dapm); 480*a6e3f4f3SSteve Lee struct max98390_priv *max98390 = 481*a6e3f4f3SSteve Lee snd_soc_component_get_drvdata(component); 482*a6e3f4f3SSteve Lee 483*a6e3f4f3SSteve Lee switch (event) { 484*a6e3f4f3SSteve Lee case SND_SOC_DAPM_POST_PMU: 485*a6e3f4f3SSteve Lee regmap_update_bits(max98390->regmap, 486*a6e3f4f3SSteve Lee MAX98390_R203A_AMP_EN, 487*a6e3f4f3SSteve Lee MAX98390_AMP_EN_MASK, 1); 488*a6e3f4f3SSteve Lee regmap_update_bits(max98390->regmap, 489*a6e3f4f3SSteve Lee MAX98390_R23FF_GLOBAL_EN, 490*a6e3f4f3SSteve Lee MAX98390_GLOBAL_EN_MASK, 1); 491*a6e3f4f3SSteve Lee break; 492*a6e3f4f3SSteve Lee case SND_SOC_DAPM_POST_PMD: 493*a6e3f4f3SSteve Lee regmap_update_bits(max98390->regmap, 494*a6e3f4f3SSteve Lee MAX98390_R23FF_GLOBAL_EN, 495*a6e3f4f3SSteve Lee MAX98390_GLOBAL_EN_MASK, 0); 496*a6e3f4f3SSteve Lee regmap_update_bits(max98390->regmap, 497*a6e3f4f3SSteve Lee MAX98390_R203A_AMP_EN, 498*a6e3f4f3SSteve Lee MAX98390_AMP_EN_MASK, 0); 499*a6e3f4f3SSteve Lee break; 500*a6e3f4f3SSteve Lee } 501*a6e3f4f3SSteve Lee return 0; 502*a6e3f4f3SSteve Lee } 503*a6e3f4f3SSteve Lee 504*a6e3f4f3SSteve Lee static const char * const max98390_switch_text[] = { 505*a6e3f4f3SSteve Lee "Left", "Right", "LeftRight"}; 506*a6e3f4f3SSteve Lee 507*a6e3f4f3SSteve Lee static const char * const max98390_boost_voltage_text[] = { 508*a6e3f4f3SSteve Lee "6.5V", "6.625V", "6.75V", "6.875V", "7V", "7.125V", "7.25V", "7.375V", 509*a6e3f4f3SSteve Lee "7.5V", "7.625V", "7.75V", "7.875V", "8V", "8.125V", "8.25V", "8.375V", 510*a6e3f4f3SSteve Lee "8.5V", "8.625V", "8.75V", "8.875V", "9V", "9.125V", "9.25V", "9.375V", 511*a6e3f4f3SSteve Lee "9.5V", "9.625V", "9.75V", "9.875V", "10V" 512*a6e3f4f3SSteve Lee }; 513*a6e3f4f3SSteve Lee 514*a6e3f4f3SSteve Lee static SOC_ENUM_SINGLE_DECL(max98390_boost_voltage, 515*a6e3f4f3SSteve Lee MAX98390_BOOST_CTRL0, 0, 516*a6e3f4f3SSteve Lee max98390_boost_voltage_text); 517*a6e3f4f3SSteve Lee 518*a6e3f4f3SSteve Lee static DECLARE_TLV_DB_SCALE(max98390_spk_tlv, 300, 300, 0); 519*a6e3f4f3SSteve Lee static DECLARE_TLV_DB_SCALE(max98390_digital_tlv, -8000, 50, 0); 520*a6e3f4f3SSteve Lee 521*a6e3f4f3SSteve Lee static const char * const max98390_current_limit_text[] = { 522*a6e3f4f3SSteve Lee "0.00A", "0.50A", "1.00A", "1.05A", "1.10A", "1.15A", "1.20A", "1.25A", 523*a6e3f4f3SSteve Lee "1.30A", "1.35A", "1.40A", "1.45A", "1.50A", "1.55A", "1.60A", "1.65A", 524*a6e3f4f3SSteve Lee "1.70A", "1.75A", "1.80A", "1.85A", "1.90A", "1.95A", "2.00A", "2.05A", 525*a6e3f4f3SSteve Lee "2.10A", "2.15A", "2.20A", "2.25A", "2.30A", "2.35A", "2.40A", "2.45A", 526*a6e3f4f3SSteve Lee "2.50A", "2.55A", "2.60A", "2.65A", "2.70A", "2.75A", "2.80A", "2.85A", 527*a6e3f4f3SSteve Lee "2.90A", "2.95A", "3.00A", "3.05A", "3.10A", "3.15A", "3.20A", "3.25A", 528*a6e3f4f3SSteve Lee "3.30A", "3.35A", "3.40A", "3.45A", "3.50A", "3.55A", "3.60A", "3.65A", 529*a6e3f4f3SSteve Lee "3.70A", "3.75A", "3.80A", "3.85A", "3.90A", "3.95A", "4.00A", "4.05A", 530*a6e3f4f3SSteve Lee "4.10A" 531*a6e3f4f3SSteve Lee }; 532*a6e3f4f3SSteve Lee 533*a6e3f4f3SSteve Lee static SOC_ENUM_SINGLE_DECL(max98390_current_limit, 534*a6e3f4f3SSteve Lee MAX98390_BOOST_CTRL1, 0, 535*a6e3f4f3SSteve Lee max98390_current_limit_text); 536*a6e3f4f3SSteve Lee 537*a6e3f4f3SSteve Lee static int max98390_ref_rdc_put(struct snd_kcontrol *kcontrol, 538*a6e3f4f3SSteve Lee struct snd_ctl_elem_value *ucontrol) 539*a6e3f4f3SSteve Lee { 540*a6e3f4f3SSteve Lee struct snd_soc_component *component = 541*a6e3f4f3SSteve Lee snd_soc_kcontrol_component(kcontrol); 542*a6e3f4f3SSteve Lee struct max98390_priv *max98390 = 543*a6e3f4f3SSteve Lee snd_soc_component_get_drvdata(component); 544*a6e3f4f3SSteve Lee 545*a6e3f4f3SSteve Lee max98390->ref_rdc_value = ucontrol->value.integer.value[0]; 546*a6e3f4f3SSteve Lee 547*a6e3f4f3SSteve Lee regmap_write(max98390->regmap, DSM_TPROT_RECIP_RDC_ROOM_BYTE0, 548*a6e3f4f3SSteve Lee max98390->ref_rdc_value & 0x000000ff); 549*a6e3f4f3SSteve Lee regmap_write(max98390->regmap, DSM_TPROT_RECIP_RDC_ROOM_BYTE1, 550*a6e3f4f3SSteve Lee (max98390->ref_rdc_value >> 8) & 0x000000ff); 551*a6e3f4f3SSteve Lee regmap_write(max98390->regmap, DSM_TPROT_RECIP_RDC_ROOM_BYTE2, 552*a6e3f4f3SSteve Lee (max98390->ref_rdc_value >> 16) & 0x000000ff); 553*a6e3f4f3SSteve Lee 554*a6e3f4f3SSteve Lee return 0; 555*a6e3f4f3SSteve Lee } 556*a6e3f4f3SSteve Lee 557*a6e3f4f3SSteve Lee static int max98390_ref_rdc_get(struct snd_kcontrol *kcontrol, 558*a6e3f4f3SSteve Lee struct snd_ctl_elem_value *ucontrol) 559*a6e3f4f3SSteve Lee { 560*a6e3f4f3SSteve Lee struct snd_soc_component *component = 561*a6e3f4f3SSteve Lee snd_soc_kcontrol_component(kcontrol); 562*a6e3f4f3SSteve Lee struct max98390_priv *max98390 = 563*a6e3f4f3SSteve Lee snd_soc_component_get_drvdata(component); 564*a6e3f4f3SSteve Lee 565*a6e3f4f3SSteve Lee ucontrol->value.integer.value[0] = max98390->ref_rdc_value; 566*a6e3f4f3SSteve Lee 567*a6e3f4f3SSteve Lee return 0; 568*a6e3f4f3SSteve Lee } 569*a6e3f4f3SSteve Lee 570*a6e3f4f3SSteve Lee static int max98390_ambient_temp_put(struct snd_kcontrol *kcontrol, 571*a6e3f4f3SSteve Lee struct snd_ctl_elem_value *ucontrol) 572*a6e3f4f3SSteve Lee { 573*a6e3f4f3SSteve Lee struct snd_soc_component *component = 574*a6e3f4f3SSteve Lee snd_soc_kcontrol_component(kcontrol); 575*a6e3f4f3SSteve Lee struct max98390_priv *max98390 = 576*a6e3f4f3SSteve Lee snd_soc_component_get_drvdata(component); 577*a6e3f4f3SSteve Lee 578*a6e3f4f3SSteve Lee max98390->ambient_temp_value = ucontrol->value.integer.value[0]; 579*a6e3f4f3SSteve Lee 580*a6e3f4f3SSteve Lee regmap_write(max98390->regmap, DSM_TPROT_ROOM_TEMPERATURE_BYTE1, 581*a6e3f4f3SSteve Lee (max98390->ambient_temp_value >> 8) & 0x000000ff); 582*a6e3f4f3SSteve Lee regmap_write(max98390->regmap, DSM_TPROT_ROOM_TEMPERATURE_BYTE0, 583*a6e3f4f3SSteve Lee (max98390->ambient_temp_value) & 0x000000ff); 584*a6e3f4f3SSteve Lee 585*a6e3f4f3SSteve Lee return 0; 586*a6e3f4f3SSteve Lee } 587*a6e3f4f3SSteve Lee 588*a6e3f4f3SSteve Lee static int max98390_ambient_temp_get(struct snd_kcontrol *kcontrol, 589*a6e3f4f3SSteve Lee struct snd_ctl_elem_value *ucontrol) 590*a6e3f4f3SSteve Lee { 591*a6e3f4f3SSteve Lee struct snd_soc_component *component = 592*a6e3f4f3SSteve Lee snd_soc_kcontrol_component(kcontrol); 593*a6e3f4f3SSteve Lee struct max98390_priv *max98390 = 594*a6e3f4f3SSteve Lee snd_soc_component_get_drvdata(component); 595*a6e3f4f3SSteve Lee 596*a6e3f4f3SSteve Lee ucontrol->value.integer.value[0] = max98390->ambient_temp_value; 597*a6e3f4f3SSteve Lee 598*a6e3f4f3SSteve Lee return 0; 599*a6e3f4f3SSteve Lee } 600*a6e3f4f3SSteve Lee 601*a6e3f4f3SSteve Lee static int max98390_adaptive_rdc_put(struct snd_kcontrol *kcontrol, 602*a6e3f4f3SSteve Lee struct snd_ctl_elem_value *ucontrol) 603*a6e3f4f3SSteve Lee { 604*a6e3f4f3SSteve Lee struct snd_soc_component *component = 605*a6e3f4f3SSteve Lee snd_soc_kcontrol_component(kcontrol); 606*a6e3f4f3SSteve Lee 607*a6e3f4f3SSteve Lee dev_warn(component->dev, "Put adaptive rdc not supported\n"); 608*a6e3f4f3SSteve Lee 609*a6e3f4f3SSteve Lee return 0; 610*a6e3f4f3SSteve Lee } 611*a6e3f4f3SSteve Lee 612*a6e3f4f3SSteve Lee static int max98390_adaptive_rdc_get(struct snd_kcontrol *kcontrol, 613*a6e3f4f3SSteve Lee struct snd_ctl_elem_value *ucontrol) 614*a6e3f4f3SSteve Lee { 615*a6e3f4f3SSteve Lee int rdc, rdc0; 616*a6e3f4f3SSteve Lee struct snd_soc_component *component = 617*a6e3f4f3SSteve Lee snd_soc_kcontrol_component(kcontrol); 618*a6e3f4f3SSteve Lee struct max98390_priv *max98390 = 619*a6e3f4f3SSteve Lee snd_soc_component_get_drvdata(component); 620*a6e3f4f3SSteve Lee 621*a6e3f4f3SSteve Lee regmap_read(max98390->regmap, THERMAL_RDC_RD_BACK_BYTE1, &rdc); 622*a6e3f4f3SSteve Lee regmap_read(max98390->regmap, THERMAL_RDC_RD_BACK_BYTE0, &rdc0); 623*a6e3f4f3SSteve Lee ucontrol->value.integer.value[0] = rdc0 | rdc << 8; 624*a6e3f4f3SSteve Lee 625*a6e3f4f3SSteve Lee return 0; 626*a6e3f4f3SSteve Lee } 627*a6e3f4f3SSteve Lee 628*a6e3f4f3SSteve Lee static int max98390_dsm_calib_get(struct snd_kcontrol *kcontrol, 629*a6e3f4f3SSteve Lee struct snd_ctl_elem_value *ucontrol) 630*a6e3f4f3SSteve Lee { 631*a6e3f4f3SSteve Lee /* Do nothing */ 632*a6e3f4f3SSteve Lee return 0; 633*a6e3f4f3SSteve Lee } 634*a6e3f4f3SSteve Lee 635*a6e3f4f3SSteve Lee static int max98390_dsm_calib_put(struct snd_kcontrol *kcontrol, 636*a6e3f4f3SSteve Lee struct snd_ctl_elem_value *ucontrol) 637*a6e3f4f3SSteve Lee { 638*a6e3f4f3SSteve Lee struct snd_soc_component *component = 639*a6e3f4f3SSteve Lee snd_soc_kcontrol_component(kcontrol); 640*a6e3f4f3SSteve Lee 641*a6e3f4f3SSteve Lee max98390_dsm_calibrate(component); 642*a6e3f4f3SSteve Lee 643*a6e3f4f3SSteve Lee return 0; 644*a6e3f4f3SSteve Lee } 645*a6e3f4f3SSteve Lee 646*a6e3f4f3SSteve Lee static const struct snd_kcontrol_new max98390_snd_controls[] = { 647*a6e3f4f3SSteve Lee SOC_SINGLE_TLV("Digital Volume", DSM_VOL_CTRL, 648*a6e3f4f3SSteve Lee 0, 184, 0, 649*a6e3f4f3SSteve Lee max98390_digital_tlv), 650*a6e3f4f3SSteve Lee SOC_SINGLE_TLV("Speaker Volume", MAX98390_R203D_SPK_GAIN, 651*a6e3f4f3SSteve Lee 0, 6, 0, 652*a6e3f4f3SSteve Lee max98390_spk_tlv), 653*a6e3f4f3SSteve Lee SOC_SINGLE("Ramp Up Bypass Switch", MAX98390_R2039_AMP_DSP_CFG, 654*a6e3f4f3SSteve Lee MAX98390_AMP_DSP_CFG_RMP_UP_SHIFT, 1, 0), 655*a6e3f4f3SSteve Lee SOC_SINGLE("Ramp Down Bypass Switch", MAX98390_R2039_AMP_DSP_CFG, 656*a6e3f4f3SSteve Lee MAX98390_AMP_DSP_CFG_RMP_DN_SHIFT, 1, 0), 657*a6e3f4f3SSteve Lee SOC_SINGLE("Boost Clock Phase", MAX98390_BOOST_CTRL3, 658*a6e3f4f3SSteve Lee MAX98390_BOOST_CLK_PHASE_CFG_SHIFT, 3, 0), 659*a6e3f4f3SSteve Lee SOC_ENUM("Boost Output Voltage", max98390_boost_voltage), 660*a6e3f4f3SSteve Lee SOC_ENUM("Current Limit", max98390_current_limit), 661*a6e3f4f3SSteve Lee SOC_SINGLE_EXT("DSM Rdc", SND_SOC_NOPM, 0, 0xffffff, 0, 662*a6e3f4f3SSteve Lee max98390_ref_rdc_get, max98390_ref_rdc_put), 663*a6e3f4f3SSteve Lee SOC_SINGLE_EXT("DSM Ambient Temp", SND_SOC_NOPM, 0, 0xffff, 0, 664*a6e3f4f3SSteve Lee max98390_ambient_temp_get, max98390_ambient_temp_put), 665*a6e3f4f3SSteve Lee SOC_SINGLE_EXT("DSM Adaptive Rdc", SND_SOC_NOPM, 0, 0xffff, 0, 666*a6e3f4f3SSteve Lee max98390_adaptive_rdc_get, max98390_adaptive_rdc_put), 667*a6e3f4f3SSteve Lee SOC_SINGLE_EXT("DSM Calibration", SND_SOC_NOPM, 0, 1, 0, 668*a6e3f4f3SSteve Lee max98390_dsm_calib_get, max98390_dsm_calib_put), 669*a6e3f4f3SSteve Lee }; 670*a6e3f4f3SSteve Lee 671*a6e3f4f3SSteve Lee static const struct soc_enum dai_sel_enum = 672*a6e3f4f3SSteve Lee SOC_ENUM_SINGLE(MAX98390_PCM_CH_SRC_1, 673*a6e3f4f3SSteve Lee MAX98390_PCM_RX_CH_SRC_SHIFT, 674*a6e3f4f3SSteve Lee 3, max98390_switch_text); 675*a6e3f4f3SSteve Lee 676*a6e3f4f3SSteve Lee static const struct snd_kcontrol_new max98390_dai_controls = 677*a6e3f4f3SSteve Lee SOC_DAPM_ENUM("DAI Sel", dai_sel_enum); 678*a6e3f4f3SSteve Lee 679*a6e3f4f3SSteve Lee static const struct snd_soc_dapm_widget max98390_dapm_widgets[] = { 680*a6e3f4f3SSteve Lee SND_SOC_DAPM_DAC_E("Amp Enable", "HiFi Playback", 681*a6e3f4f3SSteve Lee MAX98390_R203A_AMP_EN, 0, 0, max98390_dac_event, 682*a6e3f4f3SSteve Lee SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), 683*a6e3f4f3SSteve Lee SND_SOC_DAPM_MUX("DAI Sel Mux", SND_SOC_NOPM, 0, 0, 684*a6e3f4f3SSteve Lee &max98390_dai_controls), 685*a6e3f4f3SSteve Lee SND_SOC_DAPM_OUTPUT("BE_OUT"), 686*a6e3f4f3SSteve Lee }; 687*a6e3f4f3SSteve Lee 688*a6e3f4f3SSteve Lee static const struct snd_soc_dapm_route max98390_audio_map[] = { 689*a6e3f4f3SSteve Lee /* Plabyack */ 690*a6e3f4f3SSteve Lee {"DAI Sel Mux", "Left", "Amp Enable"}, 691*a6e3f4f3SSteve Lee {"DAI Sel Mux", "Right", "Amp Enable"}, 692*a6e3f4f3SSteve Lee {"DAI Sel Mux", "LeftRight", "Amp Enable"}, 693*a6e3f4f3SSteve Lee {"BE_OUT", NULL, "DAI Sel Mux"}, 694*a6e3f4f3SSteve Lee }; 695*a6e3f4f3SSteve Lee 696*a6e3f4f3SSteve Lee static bool max98390_readable_register(struct device *dev, unsigned int reg) 697*a6e3f4f3SSteve Lee { 698*a6e3f4f3SSteve Lee switch (reg) { 699*a6e3f4f3SSteve Lee case MAX98390_SOFTWARE_RESET ... MAX98390_INT_EN3: 700*a6e3f4f3SSteve Lee case MAX98390_IRQ_CTRL ... MAX98390_WDOG_CTRL: 701*a6e3f4f3SSteve Lee case MAX98390_MEAS_ADC_THERM_WARN_THRESH 702*a6e3f4f3SSteve Lee ... MAX98390_BROWNOUT_INFINITE_HOLD: 703*a6e3f4f3SSteve Lee case MAX98390_BROWNOUT_LVL_HOLD ... THERMAL_COILTEMP_RD_BACK_BYTE0: 704*a6e3f4f3SSteve Lee case DSMIG_DEBUZZER_THRESHOLD ... MAX98390_R24FF_REV_ID: 705*a6e3f4f3SSteve Lee return true; 706*a6e3f4f3SSteve Lee default: 707*a6e3f4f3SSteve Lee return false; 708*a6e3f4f3SSteve Lee } 709*a6e3f4f3SSteve Lee }; 710*a6e3f4f3SSteve Lee 711*a6e3f4f3SSteve Lee static bool max98390_volatile_reg(struct device *dev, unsigned int reg) 712*a6e3f4f3SSteve Lee { 713*a6e3f4f3SSteve Lee switch (reg) { 714*a6e3f4f3SSteve Lee case MAX98390_SOFTWARE_RESET ... MAX98390_INT_EN3: 715*a6e3f4f3SSteve Lee case MAX98390_MEAS_ADC_CH0_READ ... MAX98390_MEAS_ADC_CH2_READ: 716*a6e3f4f3SSteve Lee case MAX98390_PWR_GATE_STATUS ... MAX98390_BROWNOUT_STATUS: 717*a6e3f4f3SSteve Lee case MAX98390_BROWNOUT_LOWEST_STATUS: 718*a6e3f4f3SSteve Lee case MAX98390_ENV_TRACK_BOOST_VOUT_READ: 719*a6e3f4f3SSteve Lee case DSM_STBASS_HPF_B0_BYTE0 ... DSM_DEBUZZER_ATTACK_TIME_BYTE2: 720*a6e3f4f3SSteve Lee case THERMAL_RDC_RD_BACK_BYTE1 ... THERMAL_COILTEMP_RD_BACK_BYTE0: 721*a6e3f4f3SSteve Lee case DSM_THERMAL_GAIN ... DSM_WBDRC_GAIN: 722*a6e3f4f3SSteve Lee return true; 723*a6e3f4f3SSteve Lee default: 724*a6e3f4f3SSteve Lee return false; 725*a6e3f4f3SSteve Lee } 726*a6e3f4f3SSteve Lee } 727*a6e3f4f3SSteve Lee 728*a6e3f4f3SSteve Lee #define MAX98390_RATES SNDRV_PCM_RATE_8000_48000 729*a6e3f4f3SSteve Lee 730*a6e3f4f3SSteve Lee #define MAX98390_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ 731*a6e3f4f3SSteve Lee SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) 732*a6e3f4f3SSteve Lee 733*a6e3f4f3SSteve Lee static struct snd_soc_dai_driver max98390_dai[] = { 734*a6e3f4f3SSteve Lee { 735*a6e3f4f3SSteve Lee .name = "max98390-aif1", 736*a6e3f4f3SSteve Lee .playback = { 737*a6e3f4f3SSteve Lee .stream_name = "HiFi Playback", 738*a6e3f4f3SSteve Lee .channels_min = 1, 739*a6e3f4f3SSteve Lee .channels_max = 2, 740*a6e3f4f3SSteve Lee .rates = MAX98390_RATES, 741*a6e3f4f3SSteve Lee .formats = MAX98390_FORMATS, 742*a6e3f4f3SSteve Lee }, 743*a6e3f4f3SSteve Lee .capture = { 744*a6e3f4f3SSteve Lee .stream_name = "HiFi Capture", 745*a6e3f4f3SSteve Lee .channels_min = 1, 746*a6e3f4f3SSteve Lee .channels_max = 2, 747*a6e3f4f3SSteve Lee .rates = MAX98390_RATES, 748*a6e3f4f3SSteve Lee .formats = MAX98390_FORMATS, 749*a6e3f4f3SSteve Lee }, 750*a6e3f4f3SSteve Lee .ops = &max98390_dai_ops, 751*a6e3f4f3SSteve Lee } 752*a6e3f4f3SSteve Lee }; 753*a6e3f4f3SSteve Lee 754*a6e3f4f3SSteve Lee static int max98390_dsm_init(struct snd_soc_component *component) 755*a6e3f4f3SSteve Lee { 756*a6e3f4f3SSteve Lee int ret; 757*a6e3f4f3SSteve Lee char filename[128]; 758*a6e3f4f3SSteve Lee const char *vendor, *product; 759*a6e3f4f3SSteve Lee struct max98390_priv *max98390 = 760*a6e3f4f3SSteve Lee snd_soc_component_get_drvdata(component); 761*a6e3f4f3SSteve Lee const struct firmware *fw; 762*a6e3f4f3SSteve Lee char *dsm_param; 763*a6e3f4f3SSteve Lee 764*a6e3f4f3SSteve Lee vendor = dmi_get_system_info(DMI_SYS_VENDOR); 765*a6e3f4f3SSteve Lee product = dmi_get_system_info(DMI_PRODUCT_NAME); 766*a6e3f4f3SSteve Lee 767*a6e3f4f3SSteve Lee if (vendor && product) { 768*a6e3f4f3SSteve Lee snprintf(filename, sizeof(filename), "dsm_param_%s_%s.bin", 769*a6e3f4f3SSteve Lee vendor, product); 770*a6e3f4f3SSteve Lee } else { 771*a6e3f4f3SSteve Lee sprintf(filename, "dsm_param.bin"); 772*a6e3f4f3SSteve Lee } 773*a6e3f4f3SSteve Lee ret = request_firmware(&fw, filename, component->dev); 774*a6e3f4f3SSteve Lee if (ret) { 775*a6e3f4f3SSteve Lee ret = request_firmware(&fw, "dsm_param.bin", component->dev); 776*a6e3f4f3SSteve Lee if (ret) 777*a6e3f4f3SSteve Lee goto err; 778*a6e3f4f3SSteve Lee } 779*a6e3f4f3SSteve Lee 780*a6e3f4f3SSteve Lee dev_dbg(component->dev, 781*a6e3f4f3SSteve Lee "max98390: param fw size %ld\n", 782*a6e3f4f3SSteve Lee fw->size); 783*a6e3f4f3SSteve Lee dsm_param = (char *)fw->data; 784*a6e3f4f3SSteve Lee dsm_param += MAX98390_DSM_PAYLOAD_OFFSET; 785*a6e3f4f3SSteve Lee regmap_bulk_write(max98390->regmap, DSM_EQ_BQ1_B0_BYTE0, 786*a6e3f4f3SSteve Lee dsm_param, 787*a6e3f4f3SSteve Lee fw->size - MAX98390_DSM_PAYLOAD_OFFSET); 788*a6e3f4f3SSteve Lee release_firmware(fw); 789*a6e3f4f3SSteve Lee regmap_write(max98390->regmap, MAX98390_R23E1_DSP_GLOBAL_EN, 0x01); 790*a6e3f4f3SSteve Lee 791*a6e3f4f3SSteve Lee err: 792*a6e3f4f3SSteve Lee return ret; 793*a6e3f4f3SSteve Lee } 794*a6e3f4f3SSteve Lee 795*a6e3f4f3SSteve Lee static int max98390_dsm_calibrate(struct snd_soc_component *component) 796*a6e3f4f3SSteve Lee { 797*a6e3f4f3SSteve Lee unsigned int rdc, rdc_cal_result, temp; 798*a6e3f4f3SSteve Lee unsigned int rdc_integer, rdc_factor; 799*a6e3f4f3SSteve Lee struct max98390_priv *max98390 = 800*a6e3f4f3SSteve Lee snd_soc_component_get_drvdata(component); 801*a6e3f4f3SSteve Lee 802*a6e3f4f3SSteve Lee regmap_write(max98390->regmap, MAX98390_R203A_AMP_EN, 0x81); 803*a6e3f4f3SSteve Lee regmap_write(max98390->regmap, MAX98390_R23FF_GLOBAL_EN, 0x01); 804*a6e3f4f3SSteve Lee 805*a6e3f4f3SSteve Lee regmap_read(max98390->regmap, 806*a6e3f4f3SSteve Lee THERMAL_RDC_RD_BACK_BYTE1, &rdc); 807*a6e3f4f3SSteve Lee regmap_read(max98390->regmap, 808*a6e3f4f3SSteve Lee THERMAL_RDC_RD_BACK_BYTE0, &rdc_cal_result); 809*a6e3f4f3SSteve Lee rdc_cal_result |= (rdc << 8) & 0x0000FFFF; 810*a6e3f4f3SSteve Lee if (rdc_cal_result) 811*a6e3f4f3SSteve Lee max98390->ref_rdc_value = 268435456U / rdc_cal_result; 812*a6e3f4f3SSteve Lee 813*a6e3f4f3SSteve Lee regmap_read(max98390->regmap, MAX98390_MEAS_ADC_CH2_READ, &temp); 814*a6e3f4f3SSteve Lee max98390->ambient_temp_value = temp * 52 - 1188; 815*a6e3f4f3SSteve Lee 816*a6e3f4f3SSteve Lee rdc_integer = rdc_cal_result * 937 / 65536; 817*a6e3f4f3SSteve Lee rdc_factor = ((rdc_cal_result * 937 * 100) / 65536) 818*a6e3f4f3SSteve Lee - (rdc_integer * 100); 819*a6e3f4f3SSteve Lee 820*a6e3f4f3SSteve Lee dev_info(component->dev, "rdc resistance about %d.%02d ohm, reg=0x%X temp reg=0x%X\n", 821*a6e3f4f3SSteve Lee rdc_integer, rdc_factor, rdc_cal_result, temp); 822*a6e3f4f3SSteve Lee 823*a6e3f4f3SSteve Lee regmap_write(max98390->regmap, MAX98390_R23FF_GLOBAL_EN, 0x00); 824*a6e3f4f3SSteve Lee regmap_write(max98390->regmap, MAX98390_R203A_AMP_EN, 0x80); 825*a6e3f4f3SSteve Lee 826*a6e3f4f3SSteve Lee return 0; 827*a6e3f4f3SSteve Lee } 828*a6e3f4f3SSteve Lee 829*a6e3f4f3SSteve Lee static int max98390_probe(struct snd_soc_component *component) 830*a6e3f4f3SSteve Lee { 831*a6e3f4f3SSteve Lee struct max98390_priv *max98390 = 832*a6e3f4f3SSteve Lee snd_soc_component_get_drvdata(component); 833*a6e3f4f3SSteve Lee 834*a6e3f4f3SSteve Lee regmap_write(max98390->regmap, MAX98390_SOFTWARE_RESET, 0x01); 835*a6e3f4f3SSteve Lee /* Sleep reset settle time */ 836*a6e3f4f3SSteve Lee msleep(20); 837*a6e3f4f3SSteve Lee /* Update dsm bin param */ 838*a6e3f4f3SSteve Lee max98390_dsm_init(component); 839*a6e3f4f3SSteve Lee 840*a6e3f4f3SSteve Lee /* Amp Setting */ 841*a6e3f4f3SSteve Lee regmap_write(max98390->regmap, MAX98390_CLK_MON, 0x6f); 842*a6e3f4f3SSteve Lee regmap_write(max98390->regmap, MAX98390_PCM_RX_EN_A, 0x03); 843*a6e3f4f3SSteve Lee regmap_write(max98390->regmap, MAX98390_PWR_GATE_CTL, 0x2d); 844*a6e3f4f3SSteve Lee regmap_write(max98390->regmap, MAX98390_ENV_TRACK_VOUT_HEADROOM, 0x0e); 845*a6e3f4f3SSteve Lee regmap_write(max98390->regmap, MAX98390_BOOST_BYPASS1, 0x46); 846*a6e3f4f3SSteve Lee regmap_write(max98390->regmap, MAX98390_FET_SCALING3, 0x03); 847*a6e3f4f3SSteve Lee 848*a6e3f4f3SSteve Lee /* Dsm Setting */ 849*a6e3f4f3SSteve Lee regmap_write(max98390->regmap, DSM_VOL_CTRL, 0x94); 850*a6e3f4f3SSteve Lee regmap_write(max98390->regmap, DSMIG_EN, 0x19); 851*a6e3f4f3SSteve Lee regmap_write(max98390->regmap, MAX98390_R203A_AMP_EN, 0x80); 852*a6e3f4f3SSteve Lee if (max98390->ref_rdc_value) { 853*a6e3f4f3SSteve Lee regmap_write(max98390->regmap, DSM_TPROT_RECIP_RDC_ROOM_BYTE0, 854*a6e3f4f3SSteve Lee max98390->ref_rdc_value & 0x000000ff); 855*a6e3f4f3SSteve Lee regmap_write(max98390->regmap, DSM_TPROT_RECIP_RDC_ROOM_BYTE1, 856*a6e3f4f3SSteve Lee (max98390->ref_rdc_value >> 8) & 0x000000ff); 857*a6e3f4f3SSteve Lee regmap_write(max98390->regmap, DSM_TPROT_RECIP_RDC_ROOM_BYTE2, 858*a6e3f4f3SSteve Lee (max98390->ref_rdc_value >> 16) & 0x000000ff); 859*a6e3f4f3SSteve Lee } 860*a6e3f4f3SSteve Lee if (max98390->ambient_temp_value) { 861*a6e3f4f3SSteve Lee regmap_write(max98390->regmap, DSM_TPROT_ROOM_TEMPERATURE_BYTE1, 862*a6e3f4f3SSteve Lee (max98390->ambient_temp_value >> 8) & 0x000000ff); 863*a6e3f4f3SSteve Lee regmap_write(max98390->regmap, DSM_TPROT_ROOM_TEMPERATURE_BYTE0, 864*a6e3f4f3SSteve Lee (max98390->ambient_temp_value) & 0x000000ff); 865*a6e3f4f3SSteve Lee } 866*a6e3f4f3SSteve Lee 867*a6e3f4f3SSteve Lee return 0; 868*a6e3f4f3SSteve Lee } 869*a6e3f4f3SSteve Lee 870*a6e3f4f3SSteve Lee #ifdef CONFIG_PM_SLEEP 871*a6e3f4f3SSteve Lee static int max98390_suspend(struct device *dev) 872*a6e3f4f3SSteve Lee { 873*a6e3f4f3SSteve Lee struct max98390_priv *max98390 = dev_get_drvdata(dev); 874*a6e3f4f3SSteve Lee 875*a6e3f4f3SSteve Lee dev_dbg(dev, "%s:Enter\n", __func__); 876*a6e3f4f3SSteve Lee 877*a6e3f4f3SSteve Lee regcache_cache_only(max98390->regmap, true); 878*a6e3f4f3SSteve Lee regcache_mark_dirty(max98390->regmap); 879*a6e3f4f3SSteve Lee 880*a6e3f4f3SSteve Lee return 0; 881*a6e3f4f3SSteve Lee } 882*a6e3f4f3SSteve Lee 883*a6e3f4f3SSteve Lee static int max98390_resume(struct device *dev) 884*a6e3f4f3SSteve Lee { 885*a6e3f4f3SSteve Lee struct max98390_priv *max98390 = dev_get_drvdata(dev); 886*a6e3f4f3SSteve Lee 887*a6e3f4f3SSteve Lee dev_dbg(dev, "%s:Enter\n", __func__); 888*a6e3f4f3SSteve Lee 889*a6e3f4f3SSteve Lee regcache_cache_only(max98390->regmap, false); 890*a6e3f4f3SSteve Lee regcache_sync(max98390->regmap); 891*a6e3f4f3SSteve Lee 892*a6e3f4f3SSteve Lee return 0; 893*a6e3f4f3SSteve Lee } 894*a6e3f4f3SSteve Lee #endif 895*a6e3f4f3SSteve Lee 896*a6e3f4f3SSteve Lee static const struct dev_pm_ops max98390_pm = { 897*a6e3f4f3SSteve Lee SET_SYSTEM_SLEEP_PM_OPS(max98390_suspend, max98390_resume) 898*a6e3f4f3SSteve Lee }; 899*a6e3f4f3SSteve Lee 900*a6e3f4f3SSteve Lee static const struct snd_soc_component_driver soc_codec_dev_max98390 = { 901*a6e3f4f3SSteve Lee .probe = max98390_probe, 902*a6e3f4f3SSteve Lee .controls = max98390_snd_controls, 903*a6e3f4f3SSteve Lee .num_controls = ARRAY_SIZE(max98390_snd_controls), 904*a6e3f4f3SSteve Lee .dapm_widgets = max98390_dapm_widgets, 905*a6e3f4f3SSteve Lee .num_dapm_widgets = ARRAY_SIZE(max98390_dapm_widgets), 906*a6e3f4f3SSteve Lee .dapm_routes = max98390_audio_map, 907*a6e3f4f3SSteve Lee .num_dapm_routes = ARRAY_SIZE(max98390_audio_map), 908*a6e3f4f3SSteve Lee .idle_bias_on = 1, 909*a6e3f4f3SSteve Lee .use_pmdown_time = 1, 910*a6e3f4f3SSteve Lee .endianness = 1, 911*a6e3f4f3SSteve Lee .non_legacy_dai_naming = 1, 912*a6e3f4f3SSteve Lee }; 913*a6e3f4f3SSteve Lee 914*a6e3f4f3SSteve Lee static const struct regmap_config max98390_regmap = { 915*a6e3f4f3SSteve Lee .reg_bits = 16, 916*a6e3f4f3SSteve Lee .val_bits = 8, 917*a6e3f4f3SSteve Lee .max_register = MAX98390_R24FF_REV_ID, 918*a6e3f4f3SSteve Lee .reg_defaults = max98390_reg_defaults, 919*a6e3f4f3SSteve Lee .num_reg_defaults = ARRAY_SIZE(max98390_reg_defaults), 920*a6e3f4f3SSteve Lee .readable_reg = max98390_readable_register, 921*a6e3f4f3SSteve Lee .volatile_reg = max98390_volatile_reg, 922*a6e3f4f3SSteve Lee .cache_type = REGCACHE_RBTREE, 923*a6e3f4f3SSteve Lee }; 924*a6e3f4f3SSteve Lee 925*a6e3f4f3SSteve Lee #ifdef CONFIG_OF 926*a6e3f4f3SSteve Lee static const struct of_device_id max98390_dt_ids[] = { 927*a6e3f4f3SSteve Lee { .compatible = "maxim,max98390", }, 928*a6e3f4f3SSteve Lee { } 929*a6e3f4f3SSteve Lee }; 930*a6e3f4f3SSteve Lee MODULE_DEVICE_TABLE(of, max98390_dt_ids); 931*a6e3f4f3SSteve Lee #endif 932*a6e3f4f3SSteve Lee 933*a6e3f4f3SSteve Lee static int max98390_i2c_probe(struct i2c_client *i2c, 934*a6e3f4f3SSteve Lee const struct i2c_device_id *id) 935*a6e3f4f3SSteve Lee { 936*a6e3f4f3SSteve Lee int ret = 0; 937*a6e3f4f3SSteve Lee int reg = 0; 938*a6e3f4f3SSteve Lee 939*a6e3f4f3SSteve Lee struct max98390_priv *max98390 = NULL; 940*a6e3f4f3SSteve Lee struct i2c_adapter *adapter = to_i2c_adapter(i2c->dev.parent); 941*a6e3f4f3SSteve Lee 942*a6e3f4f3SSteve Lee ret = i2c_check_functionality(adapter, 943*a6e3f4f3SSteve Lee I2C_FUNC_SMBUS_BYTE 944*a6e3f4f3SSteve Lee | I2C_FUNC_SMBUS_BYTE_DATA); 945*a6e3f4f3SSteve Lee if (!ret) { 946*a6e3f4f3SSteve Lee dev_err(&i2c->dev, "I2C check functionality failed\n"); 947*a6e3f4f3SSteve Lee return -ENXIO; 948*a6e3f4f3SSteve Lee } 949*a6e3f4f3SSteve Lee 950*a6e3f4f3SSteve Lee max98390 = devm_kzalloc(&i2c->dev, sizeof(*max98390), GFP_KERNEL); 951*a6e3f4f3SSteve Lee if (!max98390) { 952*a6e3f4f3SSteve Lee ret = -ENOMEM; 953*a6e3f4f3SSteve Lee return ret; 954*a6e3f4f3SSteve Lee } 955*a6e3f4f3SSteve Lee i2c_set_clientdata(i2c, max98390); 956*a6e3f4f3SSteve Lee 957*a6e3f4f3SSteve Lee ret = device_property_read_u32(&i2c->dev, "maxim,temperature_calib", 958*a6e3f4f3SSteve Lee &max98390->ambient_temp_value); 959*a6e3f4f3SSteve Lee if (ret) { 960*a6e3f4f3SSteve Lee dev_info(&i2c->dev, 961*a6e3f4f3SSteve Lee "no optional property 'temperature_calib' found, default:\n"); 962*a6e3f4f3SSteve Lee } 963*a6e3f4f3SSteve Lee ret = device_property_read_u32(&i2c->dev, "maxim,r0_calib", 964*a6e3f4f3SSteve Lee &max98390->ref_rdc_value); 965*a6e3f4f3SSteve Lee if (ret) { 966*a6e3f4f3SSteve Lee dev_info(&i2c->dev, 967*a6e3f4f3SSteve Lee "no optional property 'r0_calib' found, default:\n"); 968*a6e3f4f3SSteve Lee } 969*a6e3f4f3SSteve Lee 970*a6e3f4f3SSteve Lee dev_info(&i2c->dev, 971*a6e3f4f3SSteve Lee "%s: r0_calib: 0x%x,temperature_calib: 0x%x", 972*a6e3f4f3SSteve Lee __func__, max98390->ref_rdc_value, 973*a6e3f4f3SSteve Lee max98390->ambient_temp_value); 974*a6e3f4f3SSteve Lee 975*a6e3f4f3SSteve Lee /* regmap initialization */ 976*a6e3f4f3SSteve Lee max98390->regmap = devm_regmap_init_i2c(i2c, &max98390_regmap); 977*a6e3f4f3SSteve Lee if (IS_ERR(max98390->regmap)) { 978*a6e3f4f3SSteve Lee ret = PTR_ERR(max98390->regmap); 979*a6e3f4f3SSteve Lee dev_err(&i2c->dev, 980*a6e3f4f3SSteve Lee "Failed to allocate regmap: %d\n", ret); 981*a6e3f4f3SSteve Lee return ret; 982*a6e3f4f3SSteve Lee } 983*a6e3f4f3SSteve Lee 984*a6e3f4f3SSteve Lee /* Check Revision ID */ 985*a6e3f4f3SSteve Lee ret = regmap_read(max98390->regmap, 986*a6e3f4f3SSteve Lee MAX98390_R24FF_REV_ID, ®); 987*a6e3f4f3SSteve Lee if (ret) { 988*a6e3f4f3SSteve Lee dev_err(&i2c->dev, 989*a6e3f4f3SSteve Lee "ret=%d, Failed to read: 0x%02X\n", 990*a6e3f4f3SSteve Lee ret, MAX98390_R24FF_REV_ID); 991*a6e3f4f3SSteve Lee return ret; 992*a6e3f4f3SSteve Lee } 993*a6e3f4f3SSteve Lee dev_info(&i2c->dev, "MAX98390 revisionID: 0x%02X\n", reg); 994*a6e3f4f3SSteve Lee 995*a6e3f4f3SSteve Lee ret = devm_snd_soc_register_component(&i2c->dev, 996*a6e3f4f3SSteve Lee &soc_codec_dev_max98390, 997*a6e3f4f3SSteve Lee max98390_dai, ARRAY_SIZE(max98390_dai)); 998*a6e3f4f3SSteve Lee 999*a6e3f4f3SSteve Lee return ret; 1000*a6e3f4f3SSteve Lee } 1001*a6e3f4f3SSteve Lee 1002*a6e3f4f3SSteve Lee static const struct i2c_device_id max98390_i2c_id[] = { 1003*a6e3f4f3SSteve Lee { "max98390", 0}, 1004*a6e3f4f3SSteve Lee {}, 1005*a6e3f4f3SSteve Lee }; 1006*a6e3f4f3SSteve Lee 1007*a6e3f4f3SSteve Lee MODULE_DEVICE_TABLE(i2c, max98390_i2c_id); 1008*a6e3f4f3SSteve Lee 1009*a6e3f4f3SSteve Lee #if defined(CONFIG_OF) 1010*a6e3f4f3SSteve Lee static const struct of_device_id max98390_of_match[] = { 1011*a6e3f4f3SSteve Lee { .compatible = "maxim,max98390", }, 1012*a6e3f4f3SSteve Lee {} 1013*a6e3f4f3SSteve Lee }; 1014*a6e3f4f3SSteve Lee MODULE_DEVICE_TABLE(of, max98390_of_match); 1015*a6e3f4f3SSteve Lee #endif 1016*a6e3f4f3SSteve Lee 1017*a6e3f4f3SSteve Lee #ifdef CONFIG_ACPI 1018*a6e3f4f3SSteve Lee static const struct acpi_device_id max98390_acpi_match[] = { 1019*a6e3f4f3SSteve Lee { "MX98390", 0 }, 1020*a6e3f4f3SSteve Lee {}, 1021*a6e3f4f3SSteve Lee }; 1022*a6e3f4f3SSteve Lee MODULE_DEVICE_TABLE(acpi, max98390_acpi_match); 1023*a6e3f4f3SSteve Lee #endif 1024*a6e3f4f3SSteve Lee 1025*a6e3f4f3SSteve Lee static struct i2c_driver max98390_i2c_driver = { 1026*a6e3f4f3SSteve Lee .driver = { 1027*a6e3f4f3SSteve Lee .name = "max98390", 1028*a6e3f4f3SSteve Lee .of_match_table = of_match_ptr(max98390_of_match), 1029*a6e3f4f3SSteve Lee .acpi_match_table = ACPI_PTR(max98390_acpi_match), 1030*a6e3f4f3SSteve Lee .pm = &max98390_pm, 1031*a6e3f4f3SSteve Lee }, 1032*a6e3f4f3SSteve Lee .probe = max98390_i2c_probe, 1033*a6e3f4f3SSteve Lee .id_table = max98390_i2c_id, 1034*a6e3f4f3SSteve Lee }; 1035*a6e3f4f3SSteve Lee 1036*a6e3f4f3SSteve Lee module_i2c_driver(max98390_i2c_driver) 1037*a6e3f4f3SSteve Lee 1038*a6e3f4f3SSteve Lee MODULE_DESCRIPTION("ALSA SoC MAX98390 driver"); 1039*a6e3f4f3SSteve Lee MODULE_AUTHOR("Steve Lee <steves.lee@maximintegrated.com>"); 1040*a6e3f4f3SSteve Lee MODULE_LICENSE("GPL"); 1041