162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * max98371.c -- ALSA SoC Stereo MAX98371 driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright 2015-16 Maxim Integrated Products 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/i2c.h> 962306a36Sopenharmony_ci#include <linux/module.h> 1062306a36Sopenharmony_ci#include <linux/regmap.h> 1162306a36Sopenharmony_ci#include <linux/slab.h> 1262306a36Sopenharmony_ci#include <sound/pcm.h> 1362306a36Sopenharmony_ci#include <sound/pcm_params.h> 1462306a36Sopenharmony_ci#include <sound/soc.h> 1562306a36Sopenharmony_ci#include <sound/tlv.h> 1662306a36Sopenharmony_ci#include "max98371.h" 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_cistatic const char *const monomix_text[] = { 1962306a36Sopenharmony_ci "Left", "Right", "LeftRightDiv2", 2062306a36Sopenharmony_ci}; 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_cistatic const char *const hpf_cutoff_txt[] = { 2362306a36Sopenharmony_ci "Disable", "DC Block", "50Hz", 2462306a36Sopenharmony_ci "100Hz", "200Hz", "400Hz", "800Hz", 2562306a36Sopenharmony_ci}; 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(max98371_monomix, MAX98371_MONOMIX_CFG, 0, 2862306a36Sopenharmony_ci monomix_text); 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(max98371_hpf_cutoff, MAX98371_HPF, 0, 3162306a36Sopenharmony_ci hpf_cutoff_txt); 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_cistatic const DECLARE_TLV_DB_RANGE(max98371_dht_min_gain, 3462306a36Sopenharmony_ci 0, 1, TLV_DB_SCALE_ITEM(537, 66, 0), 3562306a36Sopenharmony_ci 2, 3, TLV_DB_SCALE_ITEM(677, 82, 0), 3662306a36Sopenharmony_ci 4, 5, TLV_DB_SCALE_ITEM(852, 104, 0), 3762306a36Sopenharmony_ci 6, 7, TLV_DB_SCALE_ITEM(1072, 131, 0), 3862306a36Sopenharmony_ci 8, 9, TLV_DB_SCALE_ITEM(1350, 165, 0), 3962306a36Sopenharmony_ci 10, 11, TLV_DB_SCALE_ITEM(1699, 101, 0), 4062306a36Sopenharmony_ci); 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_cistatic const DECLARE_TLV_DB_RANGE(max98371_dht_max_gain, 4362306a36Sopenharmony_ci 0, 1, TLV_DB_SCALE_ITEM(537, 66, 0), 4462306a36Sopenharmony_ci 2, 3, TLV_DB_SCALE_ITEM(677, 82, 0), 4562306a36Sopenharmony_ci 4, 5, TLV_DB_SCALE_ITEM(852, 104, 0), 4662306a36Sopenharmony_ci 6, 7, TLV_DB_SCALE_ITEM(1072, 131, 0), 4762306a36Sopenharmony_ci 8, 9, TLV_DB_SCALE_ITEM(1350, 165, 0), 4862306a36Sopenharmony_ci 10, 11, TLV_DB_SCALE_ITEM(1699, 208, 0), 4962306a36Sopenharmony_ci); 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_cistatic const DECLARE_TLV_DB_RANGE(max98371_dht_rot_gain, 5262306a36Sopenharmony_ci 0, 1, TLV_DB_SCALE_ITEM(-50, -50, 0), 5362306a36Sopenharmony_ci 2, 6, TLV_DB_SCALE_ITEM(-100, -100, 0), 5462306a36Sopenharmony_ci 7, 8, TLV_DB_SCALE_ITEM(-800, -200, 0), 5562306a36Sopenharmony_ci 9, 11, TLV_DB_SCALE_ITEM(-1200, -300, 0), 5662306a36Sopenharmony_ci 12, 13, TLV_DB_SCALE_ITEM(-2000, -200, 0), 5762306a36Sopenharmony_ci 14, 15, TLV_DB_SCALE_ITEM(-2500, -500, 0), 5862306a36Sopenharmony_ci); 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_cistatic const struct reg_default max98371_reg[] = { 6162306a36Sopenharmony_ci { 0x01, 0x00 }, 6262306a36Sopenharmony_ci { 0x02, 0x00 }, 6362306a36Sopenharmony_ci { 0x03, 0x00 }, 6462306a36Sopenharmony_ci { 0x04, 0x00 }, 6562306a36Sopenharmony_ci { 0x05, 0x00 }, 6662306a36Sopenharmony_ci { 0x06, 0x00 }, 6762306a36Sopenharmony_ci { 0x07, 0x00 }, 6862306a36Sopenharmony_ci { 0x08, 0x00 }, 6962306a36Sopenharmony_ci { 0x09, 0x00 }, 7062306a36Sopenharmony_ci { 0x0A, 0x00 }, 7162306a36Sopenharmony_ci { 0x10, 0x06 }, 7262306a36Sopenharmony_ci { 0x11, 0x08 }, 7362306a36Sopenharmony_ci { 0x14, 0x80 }, 7462306a36Sopenharmony_ci { 0x15, 0x00 }, 7562306a36Sopenharmony_ci { 0x16, 0x00 }, 7662306a36Sopenharmony_ci { 0x18, 0x00 }, 7762306a36Sopenharmony_ci { 0x19, 0x00 }, 7862306a36Sopenharmony_ci { 0x1C, 0x00 }, 7962306a36Sopenharmony_ci { 0x1D, 0x00 }, 8062306a36Sopenharmony_ci { 0x1E, 0x00 }, 8162306a36Sopenharmony_ci { 0x1F, 0x00 }, 8262306a36Sopenharmony_ci { 0x20, 0x00 }, 8362306a36Sopenharmony_ci { 0x21, 0x00 }, 8462306a36Sopenharmony_ci { 0x22, 0x00 }, 8562306a36Sopenharmony_ci { 0x23, 0x00 }, 8662306a36Sopenharmony_ci { 0x24, 0x00 }, 8762306a36Sopenharmony_ci { 0x25, 0x00 }, 8862306a36Sopenharmony_ci { 0x26, 0x00 }, 8962306a36Sopenharmony_ci { 0x27, 0x00 }, 9062306a36Sopenharmony_ci { 0x28, 0x00 }, 9162306a36Sopenharmony_ci { 0x29, 0x00 }, 9262306a36Sopenharmony_ci { 0x2A, 0x00 }, 9362306a36Sopenharmony_ci { 0x2B, 0x00 }, 9462306a36Sopenharmony_ci { 0x2C, 0x00 }, 9562306a36Sopenharmony_ci { 0x2D, 0x00 }, 9662306a36Sopenharmony_ci { 0x2E, 0x0B }, 9762306a36Sopenharmony_ci { 0x31, 0x00 }, 9862306a36Sopenharmony_ci { 0x32, 0x18 }, 9962306a36Sopenharmony_ci { 0x33, 0x00 }, 10062306a36Sopenharmony_ci { 0x34, 0x00 }, 10162306a36Sopenharmony_ci { 0x36, 0x00 }, 10262306a36Sopenharmony_ci { 0x37, 0x00 }, 10362306a36Sopenharmony_ci { 0x38, 0x00 }, 10462306a36Sopenharmony_ci { 0x39, 0x00 }, 10562306a36Sopenharmony_ci { 0x3A, 0x00 }, 10662306a36Sopenharmony_ci { 0x3B, 0x00 }, 10762306a36Sopenharmony_ci { 0x3C, 0x00 }, 10862306a36Sopenharmony_ci { 0x3D, 0x00 }, 10962306a36Sopenharmony_ci { 0x3E, 0x00 }, 11062306a36Sopenharmony_ci { 0x3F, 0x00 }, 11162306a36Sopenharmony_ci { 0x40, 0x00 }, 11262306a36Sopenharmony_ci { 0x41, 0x00 }, 11362306a36Sopenharmony_ci { 0x42, 0x00 }, 11462306a36Sopenharmony_ci { 0x43, 0x00 }, 11562306a36Sopenharmony_ci { 0x4A, 0x00 }, 11662306a36Sopenharmony_ci { 0x4B, 0x00 }, 11762306a36Sopenharmony_ci { 0x4C, 0x00 }, 11862306a36Sopenharmony_ci { 0x4D, 0x00 }, 11962306a36Sopenharmony_ci { 0x4E, 0x00 }, 12062306a36Sopenharmony_ci { 0x50, 0x00 }, 12162306a36Sopenharmony_ci { 0x51, 0x00 }, 12262306a36Sopenharmony_ci { 0x55, 0x00 }, 12362306a36Sopenharmony_ci { 0x58, 0x00 }, 12462306a36Sopenharmony_ci { 0x59, 0x00 }, 12562306a36Sopenharmony_ci { 0x5C, 0x00 }, 12662306a36Sopenharmony_ci { 0xFF, 0x43 }, 12762306a36Sopenharmony_ci}; 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_cistatic bool max98371_volatile_register(struct device *dev, unsigned int reg) 13062306a36Sopenharmony_ci{ 13162306a36Sopenharmony_ci switch (reg) { 13262306a36Sopenharmony_ci case MAX98371_IRQ_CLEAR1: 13362306a36Sopenharmony_ci case MAX98371_IRQ_CLEAR2: 13462306a36Sopenharmony_ci case MAX98371_IRQ_CLEAR3: 13562306a36Sopenharmony_ci case MAX98371_VERSION: 13662306a36Sopenharmony_ci return true; 13762306a36Sopenharmony_ci default: 13862306a36Sopenharmony_ci return false; 13962306a36Sopenharmony_ci } 14062306a36Sopenharmony_ci} 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_cistatic bool max98371_readable_register(struct device *dev, unsigned int reg) 14362306a36Sopenharmony_ci{ 14462306a36Sopenharmony_ci switch (reg) { 14562306a36Sopenharmony_ci case MAX98371_SOFT_RESET: 14662306a36Sopenharmony_ci return false; 14762306a36Sopenharmony_ci default: 14862306a36Sopenharmony_ci return true; 14962306a36Sopenharmony_ci } 15062306a36Sopenharmony_ci}; 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_cistatic const DECLARE_TLV_DB_RANGE(max98371_gain_tlv, 15362306a36Sopenharmony_ci 0, 7, TLV_DB_SCALE_ITEM(0, 50, 0), 15462306a36Sopenharmony_ci 8, 10, TLV_DB_SCALE_ITEM(400, 100, 0) 15562306a36Sopenharmony_ci); 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_cistatic const DECLARE_TLV_DB_SCALE(digital_tlv, -6300, 50, 1); 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_cistatic const struct snd_kcontrol_new max98371_snd_controls[] = { 16062306a36Sopenharmony_ci SOC_SINGLE_TLV("Speaker Volume", MAX98371_GAIN, 16162306a36Sopenharmony_ci MAX98371_GAIN_SHIFT, (1<<MAX98371_GAIN_WIDTH)-1, 0, 16262306a36Sopenharmony_ci max98371_gain_tlv), 16362306a36Sopenharmony_ci SOC_SINGLE_TLV("Digital Volume", MAX98371_DIGITAL_GAIN, 0, 16462306a36Sopenharmony_ci (1<<MAX98371_DIGITAL_GAIN_WIDTH)-1, 1, digital_tlv), 16562306a36Sopenharmony_ci SOC_SINGLE_TLV("Speaker DHT Max Volume", MAX98371_GAIN, 16662306a36Sopenharmony_ci 0, (1<<MAX98371_DHT_MAX_WIDTH)-1, 0, 16762306a36Sopenharmony_ci max98371_dht_max_gain), 16862306a36Sopenharmony_ci SOC_SINGLE_TLV("Speaker DHT Min Volume", MAX98371_DHT_GAIN, 16962306a36Sopenharmony_ci 0, (1<<MAX98371_DHT_GAIN_WIDTH)-1, 0, 17062306a36Sopenharmony_ci max98371_dht_min_gain), 17162306a36Sopenharmony_ci SOC_SINGLE_TLV("Speaker DHT Rotation Volume", MAX98371_DHT_GAIN, 17262306a36Sopenharmony_ci 0, (1<<MAX98371_DHT_ROT_WIDTH)-1, 0, 17362306a36Sopenharmony_ci max98371_dht_rot_gain), 17462306a36Sopenharmony_ci SOC_SINGLE("DHT Attack Step", MAX98371_DHT, MAX98371_DHT_STEP, 3, 0), 17562306a36Sopenharmony_ci SOC_SINGLE("DHT Attack Rate", MAX98371_DHT, 0, 7, 0), 17662306a36Sopenharmony_ci SOC_ENUM("Monomix Select", max98371_monomix), 17762306a36Sopenharmony_ci SOC_ENUM("HPF Cutoff", max98371_hpf_cutoff), 17862306a36Sopenharmony_ci}; 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_cistatic int max98371_dai_set_fmt(struct snd_soc_dai *codec_dai, 18162306a36Sopenharmony_ci unsigned int fmt) 18262306a36Sopenharmony_ci{ 18362306a36Sopenharmony_ci struct snd_soc_component *component = codec_dai->component; 18462306a36Sopenharmony_ci struct max98371_priv *max98371 = snd_soc_component_get_drvdata(component); 18562306a36Sopenharmony_ci unsigned int val = 0; 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { 18862306a36Sopenharmony_ci case SND_SOC_DAIFMT_CBC_CFC: 18962306a36Sopenharmony_ci break; 19062306a36Sopenharmony_ci default: 19162306a36Sopenharmony_ci dev_err(component->dev, "DAI clock mode unsupported"); 19262306a36Sopenharmony_ci return -EINVAL; 19362306a36Sopenharmony_ci } 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 19662306a36Sopenharmony_ci case SND_SOC_DAIFMT_I2S: 19762306a36Sopenharmony_ci val |= 0; 19862306a36Sopenharmony_ci break; 19962306a36Sopenharmony_ci case SND_SOC_DAIFMT_RIGHT_J: 20062306a36Sopenharmony_ci val |= MAX98371_DAI_RIGHT; 20162306a36Sopenharmony_ci break; 20262306a36Sopenharmony_ci case SND_SOC_DAIFMT_LEFT_J: 20362306a36Sopenharmony_ci val |= MAX98371_DAI_LEFT; 20462306a36Sopenharmony_ci break; 20562306a36Sopenharmony_ci default: 20662306a36Sopenharmony_ci dev_err(component->dev, "DAI wrong mode unsupported"); 20762306a36Sopenharmony_ci return -EINVAL; 20862306a36Sopenharmony_ci } 20962306a36Sopenharmony_ci regmap_update_bits(max98371->regmap, MAX98371_FMT, 21062306a36Sopenharmony_ci MAX98371_FMT_MODE_MASK, val); 21162306a36Sopenharmony_ci return 0; 21262306a36Sopenharmony_ci} 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_cistatic int max98371_dai_hw_params(struct snd_pcm_substream *substream, 21562306a36Sopenharmony_ci struct snd_pcm_hw_params *params, 21662306a36Sopenharmony_ci struct snd_soc_dai *dai) 21762306a36Sopenharmony_ci{ 21862306a36Sopenharmony_ci struct snd_soc_component *component = dai->component; 21962306a36Sopenharmony_ci struct max98371_priv *max98371 = snd_soc_component_get_drvdata(component); 22062306a36Sopenharmony_ci int blr_clk_ratio, ch_size, channels = params_channels(params); 22162306a36Sopenharmony_ci int rate = params_rate(params); 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci switch (params_format(params)) { 22462306a36Sopenharmony_ci case SNDRV_PCM_FORMAT_S8: 22562306a36Sopenharmony_ci regmap_update_bits(max98371->regmap, MAX98371_FMT, 22662306a36Sopenharmony_ci MAX98371_FMT_MASK, MAX98371_DAI_CHANSZ_16); 22762306a36Sopenharmony_ci ch_size = 8; 22862306a36Sopenharmony_ci break; 22962306a36Sopenharmony_ci case SNDRV_PCM_FORMAT_S16_LE: 23062306a36Sopenharmony_ci regmap_update_bits(max98371->regmap, MAX98371_FMT, 23162306a36Sopenharmony_ci MAX98371_FMT_MASK, MAX98371_DAI_CHANSZ_16); 23262306a36Sopenharmony_ci ch_size = 16; 23362306a36Sopenharmony_ci break; 23462306a36Sopenharmony_ci case SNDRV_PCM_FORMAT_S24_LE: 23562306a36Sopenharmony_ci regmap_update_bits(max98371->regmap, MAX98371_FMT, 23662306a36Sopenharmony_ci MAX98371_FMT_MASK, MAX98371_DAI_CHANSZ_32); 23762306a36Sopenharmony_ci ch_size = 24; 23862306a36Sopenharmony_ci break; 23962306a36Sopenharmony_ci case SNDRV_PCM_FORMAT_S32_LE: 24062306a36Sopenharmony_ci regmap_update_bits(max98371->regmap, MAX98371_FMT, 24162306a36Sopenharmony_ci MAX98371_FMT_MASK, MAX98371_DAI_CHANSZ_32); 24262306a36Sopenharmony_ci ch_size = 32; 24362306a36Sopenharmony_ci break; 24462306a36Sopenharmony_ci default: 24562306a36Sopenharmony_ci return -EINVAL; 24662306a36Sopenharmony_ci } 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci /* BCLK/LRCLK ratio calculation */ 24962306a36Sopenharmony_ci blr_clk_ratio = channels * ch_size; 25062306a36Sopenharmony_ci switch (blr_clk_ratio) { 25162306a36Sopenharmony_ci case 32: 25262306a36Sopenharmony_ci regmap_update_bits(max98371->regmap, 25362306a36Sopenharmony_ci MAX98371_DAI_CLK, 25462306a36Sopenharmony_ci MAX98371_DAI_BSEL_MASK, MAX98371_DAI_BSEL_32); 25562306a36Sopenharmony_ci break; 25662306a36Sopenharmony_ci case 48: 25762306a36Sopenharmony_ci regmap_update_bits(max98371->regmap, 25862306a36Sopenharmony_ci MAX98371_DAI_CLK, 25962306a36Sopenharmony_ci MAX98371_DAI_BSEL_MASK, MAX98371_DAI_BSEL_48); 26062306a36Sopenharmony_ci break; 26162306a36Sopenharmony_ci case 64: 26262306a36Sopenharmony_ci regmap_update_bits(max98371->regmap, 26362306a36Sopenharmony_ci MAX98371_DAI_CLK, 26462306a36Sopenharmony_ci MAX98371_DAI_BSEL_MASK, MAX98371_DAI_BSEL_64); 26562306a36Sopenharmony_ci break; 26662306a36Sopenharmony_ci default: 26762306a36Sopenharmony_ci return -EINVAL; 26862306a36Sopenharmony_ci } 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci switch (rate) { 27162306a36Sopenharmony_ci case 32000: 27262306a36Sopenharmony_ci regmap_update_bits(max98371->regmap, 27362306a36Sopenharmony_ci MAX98371_SPK_SR, 27462306a36Sopenharmony_ci MAX98371_SPK_SR_MASK, MAX98371_SPK_SR_32); 27562306a36Sopenharmony_ci break; 27662306a36Sopenharmony_ci case 44100: 27762306a36Sopenharmony_ci regmap_update_bits(max98371->regmap, 27862306a36Sopenharmony_ci MAX98371_SPK_SR, 27962306a36Sopenharmony_ci MAX98371_SPK_SR_MASK, MAX98371_SPK_SR_44); 28062306a36Sopenharmony_ci break; 28162306a36Sopenharmony_ci case 48000: 28262306a36Sopenharmony_ci regmap_update_bits(max98371->regmap, 28362306a36Sopenharmony_ci MAX98371_SPK_SR, 28462306a36Sopenharmony_ci MAX98371_SPK_SR_MASK, MAX98371_SPK_SR_48); 28562306a36Sopenharmony_ci break; 28662306a36Sopenharmony_ci case 88200: 28762306a36Sopenharmony_ci regmap_update_bits(max98371->regmap, 28862306a36Sopenharmony_ci MAX98371_SPK_SR, 28962306a36Sopenharmony_ci MAX98371_SPK_SR_MASK, MAX98371_SPK_SR_88); 29062306a36Sopenharmony_ci break; 29162306a36Sopenharmony_ci case 96000: 29262306a36Sopenharmony_ci regmap_update_bits(max98371->regmap, 29362306a36Sopenharmony_ci MAX98371_SPK_SR, 29462306a36Sopenharmony_ci MAX98371_SPK_SR_MASK, MAX98371_SPK_SR_96); 29562306a36Sopenharmony_ci break; 29662306a36Sopenharmony_ci default: 29762306a36Sopenharmony_ci return -EINVAL; 29862306a36Sopenharmony_ci } 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci /* enabling both the RX channels*/ 30162306a36Sopenharmony_ci regmap_update_bits(max98371->regmap, MAX98371_MONOMIX_SRC, 30262306a36Sopenharmony_ci MAX98371_MONOMIX_SRC_MASK, MONOMIX_RX_0_1); 30362306a36Sopenharmony_ci regmap_update_bits(max98371->regmap, MAX98371_DAI_CHANNEL, 30462306a36Sopenharmony_ci MAX98371_CHANNEL_MASK, MAX98371_CHANNEL_MASK); 30562306a36Sopenharmony_ci return 0; 30662306a36Sopenharmony_ci} 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_cistatic const struct snd_soc_dapm_widget max98371_dapm_widgets[] = { 30962306a36Sopenharmony_ci SND_SOC_DAPM_DAC("DAC", NULL, MAX98371_SPK_ENABLE, 0, 0), 31062306a36Sopenharmony_ci SND_SOC_DAPM_SUPPLY("Global Enable", MAX98371_GLOBAL_ENABLE, 31162306a36Sopenharmony_ci 0, 0, NULL, 0), 31262306a36Sopenharmony_ci SND_SOC_DAPM_OUTPUT("SPK_OUT"), 31362306a36Sopenharmony_ci}; 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_cistatic const struct snd_soc_dapm_route max98371_audio_map[] = { 31662306a36Sopenharmony_ci {"DAC", NULL, "HiFi Playback"}, 31762306a36Sopenharmony_ci {"SPK_OUT", NULL, "DAC"}, 31862306a36Sopenharmony_ci {"SPK_OUT", NULL, "Global Enable"}, 31962306a36Sopenharmony_ci}; 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci#define MAX98371_RATES SNDRV_PCM_RATE_8000_48000 32262306a36Sopenharmony_ci#define MAX98371_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_BE | \ 32362306a36Sopenharmony_ci SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S32_BE) 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_cistatic const struct snd_soc_dai_ops max98371_dai_ops = { 32662306a36Sopenharmony_ci .set_fmt = max98371_dai_set_fmt, 32762306a36Sopenharmony_ci .hw_params = max98371_dai_hw_params, 32862306a36Sopenharmony_ci}; 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_cistatic struct snd_soc_dai_driver max98371_dai[] = { 33162306a36Sopenharmony_ci { 33262306a36Sopenharmony_ci .name = "max98371-aif1", 33362306a36Sopenharmony_ci .playback = { 33462306a36Sopenharmony_ci .stream_name = "HiFi Playback", 33562306a36Sopenharmony_ci .channels_min = 1, 33662306a36Sopenharmony_ci .channels_max = 2, 33762306a36Sopenharmony_ci .rates = SNDRV_PCM_RATE_8000_48000, 33862306a36Sopenharmony_ci .formats = MAX98371_FORMATS, 33962306a36Sopenharmony_ci }, 34062306a36Sopenharmony_ci .ops = &max98371_dai_ops, 34162306a36Sopenharmony_ci } 34262306a36Sopenharmony_ci}; 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_cistatic const struct snd_soc_component_driver max98371_component = { 34562306a36Sopenharmony_ci .controls = max98371_snd_controls, 34662306a36Sopenharmony_ci .num_controls = ARRAY_SIZE(max98371_snd_controls), 34762306a36Sopenharmony_ci .dapm_routes = max98371_audio_map, 34862306a36Sopenharmony_ci .num_dapm_routes = ARRAY_SIZE(max98371_audio_map), 34962306a36Sopenharmony_ci .dapm_widgets = max98371_dapm_widgets, 35062306a36Sopenharmony_ci .num_dapm_widgets = ARRAY_SIZE(max98371_dapm_widgets), 35162306a36Sopenharmony_ci .idle_bias_on = 1, 35262306a36Sopenharmony_ci .use_pmdown_time = 1, 35362306a36Sopenharmony_ci .endianness = 1, 35462306a36Sopenharmony_ci}; 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_cistatic const struct regmap_config max98371_regmap = { 35762306a36Sopenharmony_ci .reg_bits = 8, 35862306a36Sopenharmony_ci .val_bits = 8, 35962306a36Sopenharmony_ci .max_register = MAX98371_VERSION, 36062306a36Sopenharmony_ci .reg_defaults = max98371_reg, 36162306a36Sopenharmony_ci .num_reg_defaults = ARRAY_SIZE(max98371_reg), 36262306a36Sopenharmony_ci .volatile_reg = max98371_volatile_register, 36362306a36Sopenharmony_ci .readable_reg = max98371_readable_register, 36462306a36Sopenharmony_ci .cache_type = REGCACHE_RBTREE, 36562306a36Sopenharmony_ci}; 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_cistatic int max98371_i2c_probe(struct i2c_client *i2c) 36862306a36Sopenharmony_ci{ 36962306a36Sopenharmony_ci struct max98371_priv *max98371; 37062306a36Sopenharmony_ci int ret, reg; 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci max98371 = devm_kzalloc(&i2c->dev, 37362306a36Sopenharmony_ci sizeof(*max98371), GFP_KERNEL); 37462306a36Sopenharmony_ci if (!max98371) 37562306a36Sopenharmony_ci return -ENOMEM; 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci i2c_set_clientdata(i2c, max98371); 37862306a36Sopenharmony_ci max98371->regmap = devm_regmap_init_i2c(i2c, &max98371_regmap); 37962306a36Sopenharmony_ci if (IS_ERR(max98371->regmap)) { 38062306a36Sopenharmony_ci ret = PTR_ERR(max98371->regmap); 38162306a36Sopenharmony_ci dev_err(&i2c->dev, 38262306a36Sopenharmony_ci "Failed to allocate regmap: %d\n", ret); 38362306a36Sopenharmony_ci return ret; 38462306a36Sopenharmony_ci } 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci ret = regmap_read(max98371->regmap, MAX98371_VERSION, ®); 38762306a36Sopenharmony_ci if (ret < 0) { 38862306a36Sopenharmony_ci dev_info(&i2c->dev, "device error %d\n", ret); 38962306a36Sopenharmony_ci return ret; 39062306a36Sopenharmony_ci } 39162306a36Sopenharmony_ci dev_info(&i2c->dev, "device version %x\n", reg); 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci ret = devm_snd_soc_register_component(&i2c->dev, &max98371_component, 39462306a36Sopenharmony_ci max98371_dai, ARRAY_SIZE(max98371_dai)); 39562306a36Sopenharmony_ci if (ret < 0) { 39662306a36Sopenharmony_ci dev_err(&i2c->dev, "Failed to register component: %d\n", ret); 39762306a36Sopenharmony_ci return ret; 39862306a36Sopenharmony_ci } 39962306a36Sopenharmony_ci return ret; 40062306a36Sopenharmony_ci} 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_cistatic const struct i2c_device_id max98371_i2c_id[] = { 40362306a36Sopenharmony_ci { "max98371", 0 }, 40462306a36Sopenharmony_ci { } 40562306a36Sopenharmony_ci}; 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, max98371_i2c_id); 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci#ifdef CONFIG_OF 41062306a36Sopenharmony_cistatic const struct of_device_id max98371_of_match[] = { 41162306a36Sopenharmony_ci { .compatible = "maxim,max98371", }, 41262306a36Sopenharmony_ci { } 41362306a36Sopenharmony_ci}; 41462306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, max98371_of_match); 41562306a36Sopenharmony_ci#endif 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_cistatic struct i2c_driver max98371_i2c_driver = { 41862306a36Sopenharmony_ci .driver = { 41962306a36Sopenharmony_ci .name = "max98371", 42062306a36Sopenharmony_ci .of_match_table = of_match_ptr(max98371_of_match), 42162306a36Sopenharmony_ci }, 42262306a36Sopenharmony_ci .probe = max98371_i2c_probe, 42362306a36Sopenharmony_ci .id_table = max98371_i2c_id, 42462306a36Sopenharmony_ci}; 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_cimodule_i2c_driver(max98371_i2c_driver); 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ciMODULE_AUTHOR("anish kumar <yesanishhere@gmail.com>"); 42962306a36Sopenharmony_ciMODULE_DESCRIPTION("ALSA SoC MAX98371 driver"); 43062306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 431