[alsa-devel] [PATCH 00/10] ALSA SoC MAX98927 driver - revision
The initial driver had many textual and structural problems. I have added next patches to modify existing problems. There was concern about the design of keeping separate regmaps for each instance of the amplifier explicitly instead of instantiating two instances of a single, simpler driver. This was major change of this release. Coding style problem like indentation also have been fixed.
Ryan Lee (10): ALSA SoC MAX98927 driver - Initial release Updated max98927_reg table with physical defaults. Replaced max98927.h for better legibility Removed the secondary device initialization from the primary device initialization. Removed manual register configuration from devicetree Modified indentation Replaced pr_err by dev_err. Modified debug message Added mask variable to apply it in one round after the switch Modified initialization code of VI sensing Added DAI Sel Mux and minor updates Added ACPI support. Changed snd_kcontrol_chip to snd_soc_kcontrol_codec Added vendor prefix. Added range information
.../devicetree/bindings/sound/max98927.txt | 39 + sound/soc/codecs/Kconfig | 5 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/max98927.c | 1039 ++++++++++++++++++++ sound/soc/codecs/max98927.h | 267 +++++ 5 files changed, 1352 insertions(+) create mode 100755 Documentation/devicetree/bindings/sound/max98927.txt mode change 100644 => 100755 sound/soc/codecs/Kconfig mode change 100644 => 100755 sound/soc/codecs/Makefile create mode 100755 sound/soc/codecs/max98927.c create mode 100755 sound/soc/codecs/max98927.h
Signed-off-by: Ryan Lee ryans.lee@maximintegrated.com --- Keeping seperate regmaps for each instance of the amplifier was not good idea. So this part has been removed. Manual register configuration from devicetree was also removed.
sound/soc/codecs/max98927.c | 223 +++++++------------------------------------- sound/soc/codecs/max98927.h | 14 +-- 2 files changed, 33 insertions(+), 204 deletions(-)
diff --git a/sound/soc/codecs/max98927.c b/sound/soc/codecs/max98927.c index ae082ec..5627279c 100755 --- a/sound/soc/codecs/max98927.c +++ b/sound/soc/codecs/max98927.c @@ -140,24 +140,6 @@ static struct reg_default max98927_reg[] = { {MAX98927_R01FF_REV_ID, 0x40}, };
-void max98927_wrapper_write(struct max98927_priv *max98927, - unsigned int reg, unsigned int val) -{ - if (max98927->regmap) - regmap_write(max98927->regmap, reg, val); - if (max98927->sub_regmap) - regmap_write(max98927->sub_regmap, reg, val); -} - -void max98927_wrap_update_bits(struct max98927_priv *max98927, - unsigned int reg, unsigned int mask, unsigned int val) -{ - if (max98927->regmap) - regmap_update_bits(max98927->regmap, reg, mask, val); - if (max98927->sub_regmap) - regmap_update_bits(max98927->sub_regmap, reg, mask, val); -} - static int max98927_reg_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol, unsigned int reg, unsigned int mask, unsigned int shift) @@ -180,7 +162,7 @@ static int max98927_reg_put(struct snd_kcontrol *kcontrol, struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); unsigned int sel = ucontrol->value.integer.value[0];
- max98927_wrap_update_bits(max98927, reg, mask, sel << shift); + regmap_update_bits(max98927->regmap, reg, mask, sel << shift); dev_dbg(codec->dev, "%s: register 0x%02X, value 0x%02X\n", __func__, reg, sel); return 0; @@ -196,20 +178,20 @@ static int max98927_dai_set_fmt(struct snd_soc_dai *codec_dai, dev_dbg(codec->dev, "%s: fmt 0x%08X\n", __func__, fmt); switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBS_CFS: - max98927_wrap_update_bits(max98927, + regmap_update_bits(max98927->regmap, MAX98927_R0021_PCM_MASTER_MODE, MAX98927_PCM_MASTER_MODE_MASK, MAX98927_PCM_MASTER_MODE_SLAVE); break; case SND_SOC_DAIFMT_CBM_CFM: max98927->master = true; - max98927_wrap_update_bits(max98927, + regmap_update_bits(max98927->regmap, MAX98927_R0021_PCM_MASTER_MODE, MAX98927_PCM_MASTER_MODE_MASK, MAX98927_PCM_MASTER_MODE_MASTER); break; case SND_SOC_DAIFMT_CBS_CFM: - max98927_wrap_update_bits(max98927, + regmap_update_bits(max98927->regmap, MAX98927_R0021_PCM_MASTER_MODE, MAX98927_PCM_MASTER_MODE_MASK, MAX98927_PCM_MASTER_MODE_HYBRID); @@ -233,13 +215,13 @@ static int max98927_dai_set_fmt(struct snd_soc_dai *codec_dai, switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: max98927->iface |= SND_SOC_DAIFMT_I2S; - max98927_wrap_update_bits(max98927, + regmap_update_bits(max98927->regmap, MAX98927_R0020_PCM_MODE_CFG, max98927->iface, max98927->iface); break; case SND_SOC_DAIFMT_LEFT_J: max98927->iface |= SND_SOC_DAIFMT_LEFT_J; - max98927_wrap_update_bits(max98927, + regmap_update_bits(max98927->regmap, MAX98927_R0020_PCM_MODE_CFG, max98927->iface, max98927->iface); break; @@ -249,16 +231,16 @@ static int max98927_dai_set_fmt(struct snd_soc_dai *codec_dai,
/* pcm channel configuration */ if (max98927->iface & (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_LEFT_J)) { - max98927_wrapper_write(max98927, + regmap_write(max98927->regmap, MAX98927_R0018_PCM_RX_EN_A, MAX98927_PCM_RX_CH0_EN| MAX98927_PCM_RX_CH1_EN); - max98927_wrapper_write(max98927, + regmap_write(max98927->regmap, MAX98927_R0021_PCM_MASTER_MODE, MAX98927_PCM_TX_CH0_EN| MAX98927_PCM_TX_CH1_EN); } - max98927_wrap_update_bits(max98927, MAX98927_R0020_PCM_MODE_CFG, + regmap_update_bits(max98927->regmap, MAX98927_R0020_PCM_MODE_CFG, MAX98927_PCM_MODE_CFG_PCM_BCLKEDGE, invert); return 0; } @@ -291,7 +273,7 @@ static int max98927_set_clock(struct max98927_priv *max98927, __func__); return -EINVAL; } - max98927_wrap_update_bits(max98927, + regmap_update_bits(max98927->regmap, MAX98927_R0021_PCM_MASTER_MODE, MAX98927_PCM_MASTER_MODE_MCLK_MASK, i << MAX98927_PCM_MASTER_MODE_MCLK_RATE_SHIFT); @@ -310,7 +292,7 @@ static int max98927_set_clock(struct max98927_priv *max98927, default: return -EINVAL; } - max98927_wrap_update_bits(max98927, + regmap_update_bits(max98927->regmap, reg, mask, value); return 0; } @@ -326,21 +308,21 @@ static int max98927_dai_hw_params(struct snd_pcm_substream *substream, /* pcm mode configuration */ switch (snd_pcm_format_width(params_format(params))) { case 16: - max98927_wrap_update_bits(max98927, + regmap_update_bits(max98927->regmap, MAX98927_R0020_PCM_MODE_CFG, MAX98927_PCM_MODE_CFG_CHANSZ_16, MAX98927_PCM_MODE_CFG_CHANSZ_16); max98927->ch_size = 16; break; case 24: - max98927_wrap_update_bits(max98927, + regmap_update_bits(max98927->regmap, MAX98927_R0020_PCM_MODE_CFG, MAX98927_PCM_MODE_CFG_CHANSZ_24, MAX98927_PCM_MODE_CFG_CHANSZ_24); max98927->ch_size = 24; break; case 32: - max98927_wrap_update_bits(max98927, + regmap_update_bits(max98927->regmap, MAX98927_R0020_PCM_MODE_CFG, MAX98927_PCM_MODE_CFG_CHANSZ_32, MAX98927_PCM_MODE_CFG_CHANSZ_32); @@ -389,11 +371,11 @@ static int max98927_dai_hw_params(struct snd_pcm_substream *substream, goto err; } /* set DAI_SR to correct LRCLK frequency */ - max98927_wrap_update_bits(max98927, MAX98927_R0023_PCM_SR_SETUP1, + regmap_update_bits(max98927->regmap, MAX98927_R0023_PCM_SR_SETUP1, MAX98927_PCM_SR_SET1_SR_MASK, sampling_rate); - max98927_wrap_update_bits(max98927, MAX98927_R0024_PCM_SR_SETUP2, + regmap_update_bits(max98927->regmap, MAX98927_R0024_PCM_SR_SETUP2, MAX98927_PCM_SR_SET2_SR_MASK, sampling_rate<<4); - max98927_wrap_update_bits(max98927, MAX98927_R0024_PCM_SR_SETUP2, + regmap_update_bits(max98927->regmap, MAX98927_R0024_PCM_SR_SETUP2, MAX98927_PCM_SR_SET2_IVADC_SR_MASK, sampling_rate); return max98927_set_clock(max98927, params); err: @@ -421,42 +403,6 @@ static const struct snd_soc_dai_ops max98927_dai_ops = { .hw_params = max98927_dai_hw_params, };
-static void max98927_handle_pdata(struct snd_soc_codec *codec) -{ - struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); - struct max98927_reg_default *regInfo; - int cfg_size = 0; - int x; - - if (max98927->regcfg != NULL) - cfg_size = max98927->regcfg_sz / sizeof(uint32_t); - - if (cfg_size <= 0) { - dev_dbg(codec->dev, - "Register configuration is not required.\n"); - return; - } - - /* direct configuration from device tree */ - for (x = 0; x < cfg_size; x += 3) { - regInfo = (struct max98927_reg_default *)&max98927->regcfg[x]; - dev_info(codec->dev, "CH:%d, reg:0x%02x, value:0x%02x\n", - be32_to_cpu(regInfo->ch), - be32_to_cpu(regInfo->reg), - be32_to_cpu(regInfo->def)); - if (be32_to_cpu(regInfo->ch) == 0 /* Primary amp */ - && max98927->regmap) - regmap_write(max98927->regmap, - be32_to_cpu(regInfo->reg), - be32_to_cpu(regInfo->def)); - else if (be32_to_cpu(regInfo->ch) == 1 /* Secondary amp */ - && max98927->sub_regmap) - regmap_write(max98927->sub_regmap, - be32_to_cpu(regInfo->reg), - be32_to_cpu(regInfo->def)); - } -} - static int max98927_dac_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { @@ -465,31 +411,31 @@ static int max98927_dac_event(struct snd_soc_dapm_widget *w,
switch (event) { case SND_SOC_DAPM_POST_PMU: - max98927_wrap_update_bits(max98927, + regmap_update_bits(max98927->regmap, MAX98927_R003A_AMP_EN, 1, 1); /* enable the v and i for vi feedback */ - max98927_wrap_update_bits(max98927, + regmap_update_bits(max98927->regmap, MAX98927_R003E_MEAS_EN, MAX98927_MEAS_V_EN, MAX98927_MEAS_V_EN); - max98927_wrap_update_bits(max98927, + regmap_update_bits(max98927->regmap, MAX98927_R003E_MEAS_EN, MAX98927_MEAS_I_EN, MAX98927_MEAS_I_EN); - max98927_wrap_update_bits(max98927, + regmap_update_bits(max98927->regmap, MAX98927_GLOBAL_EN_MASK, 1, 1); break; case SND_SOC_DAPM_POST_PMD: - max98927_wrap_update_bits(max98927, + regmap_update_bits(max98927->regmap, MAX98927_R00FF_GLOBAL_SHDN, 1, 0); - max98927_wrap_update_bits(max98927, + regmap_update_bits(max98927->regmap, MAX98927_R003A_AMP_EN, 1, 0); /* disable the v and i for vi feedback */ - max98927_wrap_update_bits(max98927, + regmap_update_bits(max98927->regmap, MAX98927_R003E_MEAS_EN, MAX98927_MEAS_V_EN, 0); - max98927_wrap_update_bits(max98927, + regmap_update_bits(max98927->regmap, MAX98927_R003E_MEAS_EN, MAX98927_MEAS_I_EN, 0); @@ -531,7 +477,7 @@ static int max98927_spk_gain_put(struct snd_kcontrol *kcontrol, unsigned int sel = ucontrol->value.integer.value[0];
if (sel < ((1 << MAX98927_Speaker_Gain_Width) - 1)) { - max98927_wrap_update_bits(max98927, + regmap_update_bits(max98927->regmap, MAX98927_R003C_SPK_GAIN, MAX98927_SPK_PCM_GAIN_MASK, sel); max98927->spk_gain = sel; @@ -559,7 +505,7 @@ static int max98927_digital_gain_put(struct snd_kcontrol *kcontrol, unsigned int sel = ucontrol->value.integer.value[0];
if (sel < ((1 << MAX98927_AMP_VOL_WIDTH) - 1)) { - max98927_wrap_update_bits(max98927, + regmap_update_bits(max98927->regmap, MAX98927_R0036_AMP_VOL_CTRL, MAX98927_AMP_VOL_MASK, sel); max98927->digital_gain = sel; @@ -792,17 +738,17 @@ static struct snd_soc_dai_driver max98927_dai[] = { static int max98927_probe(struct snd_soc_codec *codec) { struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); - int ret = 0, reg = 0, i; + int ret = 0, reg = 0;
max98927->codec = codec; codec->control_data = max98927->regmap; codec->cache_bypass = 1;
/* Software Reset */ - max98927_wrapper_write(max98927, + regmap_write(max98927->regmap, MAX98927_R0100_SOFT_RESET, MAX98927_SOFT_RESET);
- /* Check Revision ID for the primary MAX98927*/ + /* Check Revision ID */ ret = regmap_read(max98927->regmap, MAX98927_R01FF_REV_ID, ®); if (ret < 0) @@ -812,25 +758,6 @@ static int max98927_probe(struct snd_soc_codec *codec) dev_info(codec->dev, "MAX98927 revisionID: 0x%02X\n", reg);
- /* Check Revision ID for the secondary MAX98927*/ - if (max98927->sub_regmap) { - ret = regmap_read(max98927->sub_regmap, - MAX98927_R01FF_REV_ID, ®); - if (ret < 0) - dev_err(codec->dev, - "Failed to read: 0x%02X from secodnary device\n" - , MAX98927_R01FF_REV_ID); - else - dev_info(codec->dev, - "Secondary device revisionID: 0x%02X\n", reg); - } - - /* Register initialization */ - for (i = 0; i < sizeof(max98927_reg)/ - sizeof(max98927_reg[0]); i++) - max98927_wrapper_write(max98927, - max98927_reg[i].reg, - max98927_reg[i].def);
if (max98927->regmap) regmap_write(max98927->regmap, @@ -838,22 +765,13 @@ static int max98927_probe(struct snd_soc_codec *codec) (max98927->i_l_slot <<MAX98927_PCM_TX_CH_SRC_A_I_SHIFT| max98927->v_l_slot)&0xFF); - if (max98927->sub_regmap) - regmap_write(max98927->sub_regmap, - MAX98927_R001E_PCM_TX_CH_SRC_A, - (max98927->i_r_slot - <<MAX98927_PCM_TX_CH_SRC_A_I_SHIFT| - max98927->v_r_slot)&0xFF);
/* Set interleave mode */ if (max98927->interleave_mode) - max98927_wrap_update_bits(max98927, + regmap_update_bits(max98927->regmap, MAX98927_R001F_PCM_TX_CH_SRC_B, MAX98927_PCM_TX_CH_INTERLEAVE_MASK, MAX98927_PCM_TX_CH_INTERLEAVE_MASK); - - max98927_handle_pdata(codec); - return ret; }
@@ -879,36 +797,6 @@ static const struct regmap_config max98927_regmap = { .cache_type = REGCACHE_RBTREE, };
-static struct i2c_board_info max98927_i2c_sub_board[] = { - { - I2C_BOARD_INFO("max98927_sub", 0x39), - } -}; - -static struct i2c_driver max98927_i2c_sub_driver = { - .driver = { - .name = "max98927_sub", - .owner = THIS_MODULE, - }, -}; - -struct i2c_client *max98927_add_sub_device(int bus_id, int slave_addr) -{ - struct i2c_client *i2c = NULL; - struct i2c_adapter *adapter; - - max98927_i2c_sub_board[0].addr = slave_addr; - - adapter = i2c_get_adapter(bus_id); - if (adapter) { - i2c = i2c_new_device(adapter, max98927_i2c_sub_board); - if (i2c) - i2c->dev.driver = &max98927_i2c_sub_driver.driver; - } - - return i2c; -} - int probe_common(struct i2c_client *i2c, struct max98927_priv *max98927) { int ret = 0, value; @@ -921,14 +809,6 @@ int probe_common(struct i2c_client *i2c, struct max98927_priv *max98927) max98927->i_l_slot = value & 0xF; else max98927->i_l_slot = 1; - if (!of_property_read_u32(i2c->dev.of_node, "vmon-r-slot", &value)) - max98927->v_r_slot = value & 0xF; - else - max98927->v_r_slot = 2; - if (!of_property_read_u32(i2c->dev.of_node, "imon-r-slot", &value)) - max98927->i_r_slot = value & 0xF; - else - max98927->i_r_slot = 3;
ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_max98927, max98927_dai, ARRAY_SIZE(max98927_dai)); @@ -964,25 +844,7 @@ static int max98927_i2c_probe(struct i2c_client *i2c, } else max98927->interleave_mode = 0;
- /* update direct configuration info */ - max98927->regcfg = of_get_property(i2c->dev.of_node, - "maxim,regcfg", &max98927->regcfg_sz); - - /* check for secondary MAX98927 */ - ret = of_property_read_u32(i2c->dev.of_node, - "maxim,sub_reg", &max98927->sub_reg); - if (ret) { - dev_err(&i2c->dev, "Sub-device slave address was not found.\n"); - max98927->sub_reg = -1; - } - ret = of_property_read_u32(i2c->dev.of_node, - "maxim,sub_bus", &max98927->sub_bus); - if (ret) { - dev_err(&i2c->dev, "Sub-device bus information was not found.\n"); - max98927->sub_bus = i2c->adapter->nr; - } - - /* regmap initialization for primary device */ + /* regmap initialization */ max98927->regmap = devm_regmap_init_i2c(i2c, &max98927_regmap); if (IS_ERR(max98927->regmap)) { @@ -992,27 +854,6 @@ static int max98927_i2c_probe(struct i2c_client *i2c, goto err; }
- /* regmap initialization for secondary device */ - if (max98927->sub_reg > 0) { - max98927->sub_i2c = max98927_add_sub_device(max98927->sub_bus, - max98927->sub_reg); - if (IS_ERR(max98927->sub_i2c)) { - dev_err(&max98927->sub_i2c->dev, - "Second MAX98927 was not found\n"); - ret = PTR_ERR(max98927->regmap); - goto err; - } else { - max98927->sub_regmap = regmap_init_i2c( - max98927->sub_i2c, &max98927_regmap); - if (IS_ERR(max98927->sub_regmap)) { - ret = PTR_ERR(max98927->sub_regmap); - dev_err(&max98927->sub_i2c->dev, - "Failed to allocate sub_regmap: %d\n", - ret); - goto err; - } - } - }
/* codec registeration */ ret = probe_common(i2c, max98927); diff --git a/sound/soc/codecs/max98927.h b/sound/soc/codecs/max98927.h index 0d8daa5..2de8504 100755 --- a/sound/soc/codecs/max98927.h +++ b/sound/soc/codecs/max98927.h @@ -249,33 +249,21 @@ /* MAX98927_R00FF_GLOBAL_SHDN */ #define MAX98927_GLOBAL_EN_MASK (0x1 << 0)
-struct max98927_reg_default { - unsigned int ch; - unsigned int reg; - unsigned int def; -}; struct max98927_priv { struct regmap *regmap; - struct regmap *sub_regmap; struct snd_soc_codec *codec; struct max98927_pdata *pdata; - const uint32_t *regcfg; - uint32_t regcfg_sz; unsigned int spk_gain; unsigned int sysclk; unsigned int v_l_slot; unsigned int i_l_slot; - unsigned int v_r_slot; - unsigned int i_r_slot; bool interleave_mode; unsigned int ch_size; unsigned int rate; unsigned int iface; unsigned int master; unsigned int digital_gain; - struct i2c_client *sub_i2c; - int sub_reg; - int sub_bus; }; #define MAX98927_Speaker_Gain_Width 3 +#define MAX98927_AMP_VOL_LOCATION_SHIFT 7 #endif
Signed-off-by: Ryan Lee ryans.lee@maximintegrated.com --- Modified indentation problem.
sound/soc/codecs/max98927.c | 80 ++++++++++++++++++++++----------------------- 1 file changed, 39 insertions(+), 41 deletions(-)
diff --git a/sound/soc/codecs/max98927.c b/sound/soc/codecs/max98927.c index 5627279c..efc761b 100755 --- a/sound/soc/codecs/max98927.c +++ b/sound/soc/codecs/max98927.c @@ -141,22 +141,21 @@ static struct reg_default max98927_reg[] = { };
static int max98927_reg_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol, unsigned int reg, - unsigned int mask, unsigned int shift) + struct snd_ctl_elem_value *ucontrol, unsigned int reg, + unsigned int mask, unsigned int shift) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); int data;
regmap_read(max98927->regmap, reg, &data); - ucontrol->value.integer.value[0] = - (data & mask) >> shift; + ucontrol->value.integer.value[0] = (data & mask) >> shift; return 0; }
static int max98927_reg_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol, unsigned int reg, - unsigned int mask, unsigned int shift) + struct snd_ctl_elem_value *ucontrol, unsigned int reg, + unsigned int mask, unsigned int shift) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); @@ -164,18 +163,18 @@ static int max98927_reg_put(struct snd_kcontrol *kcontrol,
regmap_update_bits(max98927->regmap, reg, mask, sel << shift); dev_dbg(codec->dev, "%s: register 0x%02X, value 0x%02X\n", - __func__, reg, sel); + __func__, reg, sel); return 0; }
-static int max98927_dai_set_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) +static int max98927_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct snd_soc_codec *codec = codec_dai->codec; struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); unsigned int invert = 0;
dev_dbg(codec->dev, "%s: fmt 0x%08X\n", __func__, fmt); + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBS_CFS: regmap_update_bits(max98927->regmap, @@ -218,13 +217,13 @@ static int max98927_dai_set_fmt(struct snd_soc_dai *codec_dai, regmap_update_bits(max98927->regmap, MAX98927_R0020_PCM_MODE_CFG, max98927->iface, max98927->iface); - break; + break; case SND_SOC_DAIFMT_LEFT_J: max98927->iface |= SND_SOC_DAIFMT_LEFT_J; regmap_update_bits(max98927->regmap, MAX98927_R0020_PCM_MODE_CFG, max98927->iface, max98927->iface); - break; + break; default: return -EINVAL; } @@ -292,8 +291,7 @@ static int max98927_set_clock(struct max98927_priv *max98927, default: return -EINVAL; } - regmap_update_bits(max98927->regmap, - reg, mask, value); + regmap_update_bits(max98927->regmap, reg, mask, value); return 0; }
@@ -388,7 +386,7 @@ static int max98927_dai_hw_params(struct snd_pcm_substream *substream, SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
static int max98927_dai_set_sysclk(struct snd_soc_dai *dai, - int clk_id, unsigned int freq, int dir) + int clk_id, unsigned int freq, int dir) { struct snd_soc_codec *codec = dai->codec; struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); @@ -458,7 +456,7 @@ static DECLARE_TLV_DB_SCALE(max98927_spk_tlv, 300, 300, 0); static DECLARE_TLV_DB_SCALE(max98927_digital_tlv, -1600, 25, 0);
static int max98927_spk_gain_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) + struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); @@ -470,7 +468,7 @@ static int max98927_spk_gain_get(struct snd_kcontrol *kcontrol, }
static int max98927_spk_gain_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) + struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); @@ -486,7 +484,7 @@ static int max98927_spk_gain_put(struct snd_kcontrol *kcontrol, }
static int max98927_digital_gain_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) + struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); @@ -498,7 +496,7 @@ static int max98927_digital_gain_get(struct snd_kcontrol *kcontrol, }
static int max98927_digital_gain_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) + struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); @@ -514,7 +512,7 @@ static int max98927_digital_gain_put(struct snd_kcontrol *kcontrol, }
static int max98927_boost_voltage_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) + struct snd_ctl_elem_value *ucontrol) { return max98927_reg_get(kcontrol, ucontrol, MAX98927_R0040_BOOST_CTRL0, @@ -522,7 +520,7 @@ static int max98927_boost_voltage_get(struct snd_kcontrol *kcontrol, }
static int max98927_boost_voltage_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) + struct snd_ctl_elem_value *ucontrol) { return max98927_reg_put(kcontrol, ucontrol, MAX98927_R0040_BOOST_CTRL0, @@ -530,7 +528,7 @@ static int max98927_boost_voltage_put(struct snd_kcontrol *kcontrol, }
static int max98927_amp_vol_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) + struct snd_ctl_elem_value *ucontrol) { return max98927_reg_get(kcontrol, ucontrol, MAX98927_R0036_AMP_VOL_CTRL, @@ -539,7 +537,7 @@ static int max98927_amp_vol_get(struct snd_kcontrol *kcontrol, }
static int max98927_amp_dsp_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) + struct snd_ctl_elem_value *ucontrol) { return max98927_reg_put(kcontrol, ucontrol, MAX98927_R0052_BROWNOUT_EN, @@ -548,7 +546,7 @@ static int max98927_amp_dsp_put(struct snd_kcontrol *kcontrol, }
static int max98927_amp_dsp_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) + struct snd_ctl_elem_value *ucontrol) { return max98927_reg_get(kcontrol, ucontrol, MAX98927_R0052_BROWNOUT_EN, @@ -557,7 +555,7 @@ static int max98927_amp_dsp_get(struct snd_kcontrol *kcontrol, }
static int max98927_ramp_switch_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) + struct snd_ctl_elem_value *ucontrol) { return max98927_reg_put(kcontrol, ucontrol, MAX98927_R0037_AMP_DSP_CFG, @@ -565,7 +563,7 @@ static int max98927_ramp_switch_put(struct snd_kcontrol *kcontrol, MAX98927_AMP_DSP_CFG_RMP_SHIFT); } static int max98927_ramp_switch_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) + struct snd_ctl_elem_value *ucontrol) { return max98927_reg_get(kcontrol, ucontrol, MAX98927_R0037_AMP_DSP_CFG, @@ -574,21 +572,21 @@ static int max98927_ramp_switch_get(struct snd_kcontrol *kcontrol, }
static int max98927_dre_en_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) + struct snd_ctl_elem_value *ucontrol) { return max98927_reg_put(kcontrol, ucontrol, MAX98927_R0039_DRE_CTRL, MAX98927_DRE_CTRL_DRE_EN, 0); } static int max98927_dre_en_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) + struct snd_ctl_elem_value *ucontrol) { return max98927_reg_get(kcontrol, ucontrol, MAX98927_R0039_DRE_CTRL, MAX98927_DRE_CTRL_DRE_EN, 0); } static int max98927_amp_vol_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) + struct snd_ctl_elem_value *ucontrol) { return max98927_reg_put(kcontrol, ucontrol, MAX98927_R0036_AMP_VOL_CTRL, @@ -596,7 +594,7 @@ static int max98927_amp_vol_put(struct snd_kcontrol *kcontrol, 7); } static int max98927_spk_src_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) + struct snd_ctl_elem_value *ucontrol) { return max98927_reg_get(kcontrol, ucontrol, MAX98927_R003B_SPK_SRC_SEL, @@ -604,7 +602,7 @@ static int max98927_spk_src_get(struct snd_kcontrol *kcontrol, }
static int max98927_spk_src_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) + struct snd_ctl_elem_value *ucontrol) { return max98927_reg_put(kcontrol, ucontrol, MAX98927_R003B_SPK_SRC_SEL, @@ -612,7 +610,7 @@ static int max98927_spk_src_put(struct snd_kcontrol *kcontrol, }
static int max98927_mono_out_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) + struct snd_ctl_elem_value *ucontrol) { return max98927_reg_get(kcontrol, ucontrol, MAX98927_R0025_PCM_TO_SPK_MONOMIX_A, @@ -621,7 +619,7 @@ static int max98927_mono_out_get(struct snd_kcontrol *kcontrol, }
static int max98927_mono_out_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) + struct snd_ctl_elem_value *ucontrol) { return max98927_reg_put(kcontrol, ucontrol, MAX98927_R0025_PCM_TO_SPK_MONOMIX_A, @@ -646,9 +644,10 @@ static bool max98927_readable_register(struct device *dev, unsigned int reg) case MAX98927_R0100_SOFT_RESET: case MAX98927_R01FF_REV_ID: return true; + default: + return false; } - return false; -}; +}
static const char * const max98927_boost_voltage_text[] = { "6.5V", "6.625V", "6.75V", "6.875V", "7V", "7.125V", "7.25V", "7.375V", @@ -701,13 +700,12 @@ static const struct snd_kcontrol_new max98927_snd_controls[] = { MAX98927_R0036_AMP_VOL_CTRL, MAX98927_AMP_VOL_SEL_SHIFT, 1, 0, max98927_amp_vol_get, max98927_amp_vol_put), - SOC_ENUM_EXT("Boost Output Voltage", max98927_enum[2], - max98927_boost_voltage_get, max98927_boost_voltage_put), + max98927_boost_voltage_get, max98927_boost_voltage_put), SOC_ENUM_EXT("Speaker Source", max98927_enum[1], - max98927_spk_src_get, max98927_spk_src_put), + max98927_spk_src_get, max98927_spk_src_put), SOC_ENUM_EXT("Monomix Output", max98927_enum[0], - max98927_mono_out_get, max98927_mono_out_put), + max98927_mono_out_get, max98927_mono_out_put), };
static const struct snd_soc_dapm_route max98927_audio_map[] = { @@ -762,9 +760,9 @@ static int max98927_probe(struct snd_soc_codec *codec) if (max98927->regmap) regmap_write(max98927->regmap, MAX98927_R001E_PCM_TX_CH_SRC_A, - (max98927->i_l_slot - <<MAX98927_PCM_TX_CH_SRC_A_I_SHIFT| - max98927->v_l_slot)&0xFF); + ((max98927->i_l_slot << + MAX98927_PCM_TX_CH_SRC_A_I_SHIFT) + | max98927->v_l_slot) & 0xFF);
/* Set interleave mode */ if (max98927->interleave_mode)
Signed-off-by: Ryan Lee ryans.lee@maximintegrated.com --- Replaced 'pr_err' by 'dev_err'. Modified error message.
sound/soc/codecs/max98927.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/sound/soc/codecs/max98927.c b/sound/soc/codecs/max98927.c index efc761b..0abf6d3 100755 --- a/sound/soc/codecs/max98927.c +++ b/sound/soc/codecs/max98927.c @@ -254,6 +254,7 @@ static const int rate_table[] = { static int max98927_set_clock(struct max98927_priv *max98927, struct snd_pcm_hw_params *params) { + struct snd_soc_codec *codec = max98927->codec; /* BCLK/LRCLK ratio calculation */ int blr_clk_ratio = params_channels(params) * max98927->ch_size; int reg = MAX98927_R0022_PCM_CLK_SETUP; @@ -268,8 +269,7 @@ static int max98927_set_clock(struct max98927_priv *max98927, break; } if (i == ARRAY_SIZE(rate_table)) { - pr_err("%s couldn't get the MCLK to match codec\n", - __func__); + dev_err(codec->dev, "failed to find proper clock rate.\n"); return -EINVAL; } regmap_update_bits(max98927->regmap, @@ -327,12 +327,12 @@ static int max98927_dai_hw_params(struct snd_pcm_substream *substream, max98927->ch_size = 32; break; default: - pr_err("%s: format unsupported %d", - __func__, params_format(params)); + dev_err(codec->dev, "format unsupported %d", + params_format(params)); goto err; } - dev_dbg(codec->dev, "%s: format supported %d", - __func__, params_format(params)); + dev_dbg(codec->dev, "format supported %d", + params_format(params));
/* sampling rate configuration */ switch (params_rate(params)) { @@ -364,8 +364,8 @@ static int max98927_dai_hw_params(struct snd_pcm_substream *substream, sampling_rate |= MAX98927_PCM_SR_SET1_SR_48000; break; default: - pr_err("%s rate %d not supported\n", - __func__, params_rate(params)); + dev_err(codec->dev, "rate %d not supported\n", + params_rate(params)); goto err; } /* set DAI_SR to correct LRCLK frequency */ @@ -490,7 +490,7 @@ static int max98927_digital_gain_get(struct snd_kcontrol *kcontrol, struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec);
ucontrol->value.integer.value[0] = max98927->digital_gain; - dev_dbg(codec->dev, "%s: spk_gain setting returned %d\n", __func__, + dev_dbg(codec->dev, "%s: digital_gain setting returned %d\n", __func__, (int) ucontrol->value.integer.value[0]); return 0; }
Signed-off-by: Ryan Lee ryans.lee@maximintegrated.com --- Added the mask variable to apply in one round after the switch.
sound/soc/codecs/max98927.c | 64 ++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 33 deletions(-)
diff --git a/sound/soc/codecs/max98927.c b/sound/soc/codecs/max98927.c index 0abf6d3..9e70883 100755 --- a/sound/soc/codecs/max98927.c +++ b/sound/soc/codecs/max98927.c @@ -171,34 +171,31 @@ static int max98927_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct snd_soc_codec *codec = codec_dai->codec; struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); + unsigned int mode = 0; unsigned int invert = 0;
dev_dbg(codec->dev, "%s: fmt 0x%08X\n", __func__, fmt);
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBS_CFS: - regmap_update_bits(max98927->regmap, - MAX98927_R0021_PCM_MASTER_MODE, - MAX98927_PCM_MASTER_MODE_MASK, - MAX98927_PCM_MASTER_MODE_SLAVE); + mode = MAX98927_PCM_MASTER_MODE_SLAVE; break; case SND_SOC_DAIFMT_CBM_CFM: max98927->master = true; - regmap_update_bits(max98927->regmap, - MAX98927_R0021_PCM_MASTER_MODE, - MAX98927_PCM_MASTER_MODE_MASK, - MAX98927_PCM_MASTER_MODE_MASTER); + mode = MAX98927_PCM_MASTER_MODE_MASTER; break; case SND_SOC_DAIFMT_CBS_CFM: - regmap_update_bits(max98927->regmap, - MAX98927_R0021_PCM_MASTER_MODE, - MAX98927_PCM_MASTER_MODE_MASK, - MAX98927_PCM_MASTER_MODE_HYBRID); + mode = MAX98927_PCM_MASTER_MODE_HYBRID; default: dev_err(codec->dev, "DAI clock mode unsupported"); return -EINVAL; }
+ regmap_update_bits(max98927->regmap, + MAX98927_R0021_PCM_MASTER_MODE, + MAX98927_PCM_MASTER_MODE_MASK, + mode); + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { case SND_SOC_DAIFMT_NB_NF: break; @@ -210,24 +207,28 @@ static int max98927_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) return -EINVAL; }
+ regmap_update_bits(max98927->regmap, + MAX98927_R0020_PCM_MODE_CFG, + MAX98927_PCM_MODE_CFG_PCM_BCLKEDGE, + invert); + /* interface format */ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: max98927->iface |= SND_SOC_DAIFMT_I2S; - regmap_update_bits(max98927->regmap, - MAX98927_R0020_PCM_MODE_CFG, - max98927->iface, max98927->iface); - break; + + break; case SND_SOC_DAIFMT_LEFT_J: max98927->iface |= SND_SOC_DAIFMT_LEFT_J; - regmap_update_bits(max98927->regmap, - MAX98927_R0020_PCM_MODE_CFG, - max98927->iface, max98927->iface); - break; + break; default: return -EINVAL; }
+ regmap_update_bits(max98927->regmap, + MAX98927_R0020_PCM_MODE_CFG, + max98927->iface, max98927->iface); + /* pcm channel configuration */ if (max98927->iface & (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_LEFT_J)) { regmap_write(max98927->regmap, @@ -301,29 +302,21 @@ static int max98927_dai_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_codec *codec = dai->codec; struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); - int sampling_rate = 0; + unsigned int sampling_rate = 0; + unsigned int chan_sz = 0;
/* pcm mode configuration */ switch (snd_pcm_format_width(params_format(params))) { case 16: - regmap_update_bits(max98927->regmap, - MAX98927_R0020_PCM_MODE_CFG, - MAX98927_PCM_MODE_CFG_CHANSZ_16, - MAX98927_PCM_MODE_CFG_CHANSZ_16); + chan_sz = MAX98927_PCM_MODE_CFG_CHANSZ_16; max98927->ch_size = 16; break; case 24: - regmap_update_bits(max98927->regmap, - MAX98927_R0020_PCM_MODE_CFG, - MAX98927_PCM_MODE_CFG_CHANSZ_24, - MAX98927_PCM_MODE_CFG_CHANSZ_24); + chan_sz = MAX98927_PCM_MODE_CFG_CHANSZ_24; max98927->ch_size = 24; break; case 32: - regmap_update_bits(max98927->regmap, - MAX98927_R0020_PCM_MODE_CFG, - MAX98927_PCM_MODE_CFG_CHANSZ_32, - MAX98927_PCM_MODE_CFG_CHANSZ_32); + chan_sz = MAX98927_PCM_MODE_CFG_CHANSZ_32; max98927->ch_size = 32; break; default: @@ -331,6 +324,11 @@ static int max98927_dai_hw_params(struct snd_pcm_substream *substream, params_format(params)); goto err; } + + regmap_update_bits(max98927->regmap, + MAX98927_R0020_PCM_MODE_CFG, + MAX98927_PCM_MODE_CFG_CHANSZ_MASK, chan_sz); + dev_dbg(codec->dev, "format supported %d", params_format(params));
Signed-off-by: Ryan Lee ryans.lee@maximintegrated.com --- Initialization code of TX(VI sensing) had a problem for interleave mode configuration. Additional configuration for volume, DC blocker, Voltage/Current limit and ADC have been added.
sound/soc/codecs/max98927.c | 195 +++++++++++++++++++++++++++++++++----------- 1 file changed, 146 insertions(+), 49 deletions(-)
diff --git a/sound/soc/codecs/max98927.c b/sound/soc/codecs/max98927.c index 9e70883..df2f4ff 100755 --- a/sound/soc/codecs/max98927.c +++ b/sound/soc/codecs/max98927.c @@ -1,7 +1,7 @@ /* * max98927.c -- MAX98927 ALSA Soc Audio driver * - * Copyright 2013-15 Maxim Integrated Products + * Copyright (C) 2016 Maxim Integrated Products * Author: Ryan Lee ryans.lee@maximintegrated.com * * This program is free software; you can redistribute it and/or modify it @@ -230,18 +230,12 @@ static int max98927_dai_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) max98927->iface, max98927->iface);
/* pcm channel configuration */ - if (max98927->iface & (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_LEFT_J)) { + if (max98927->iface & (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_LEFT_J)) regmap_write(max98927->regmap, MAX98927_R0018_PCM_RX_EN_A, MAX98927_PCM_RX_CH0_EN| MAX98927_PCM_RX_CH1_EN); - regmap_write(max98927->regmap, - MAX98927_R0021_PCM_MASTER_MODE, - MAX98927_PCM_TX_CH0_EN| - MAX98927_PCM_TX_CH1_EN); - } - regmap_update_bits(max98927->regmap, MAX98927_R0020_PCM_MODE_CFG, - MAX98927_PCM_MODE_CFG_PCM_BCLKEDGE, invert); + return 0; }
@@ -367,12 +361,27 @@ static int max98927_dai_hw_params(struct snd_pcm_substream *substream, goto err; } /* set DAI_SR to correct LRCLK frequency */ - regmap_update_bits(max98927->regmap, MAX98927_R0023_PCM_SR_SETUP1, - MAX98927_PCM_SR_SET1_SR_MASK, sampling_rate); - regmap_update_bits(max98927->regmap, MAX98927_R0024_PCM_SR_SETUP2, - MAX98927_PCM_SR_SET2_SR_MASK, sampling_rate<<4); - regmap_update_bits(max98927->regmap, MAX98927_R0024_PCM_SR_SETUP2, - MAX98927_PCM_SR_SET2_IVADC_SR_MASK, sampling_rate); + regmap_update_bits(max98927->regmap, + MAX98927_R0023_PCM_SR_SETUP1, + MAX98927_PCM_SR_SET1_SR_MASK, + sampling_rate); + regmap_update_bits(max98927->regmap, + MAX98927_R0024_PCM_SR_SETUP2, + MAX98927_PCM_SR_SET2_SR_MASK, + sampling_rate << MAX98927_PCM_SR_SET2_SR_SHIFT); + + /* set sampling rate of IV */ + if (max98927->interleave_mode && + sampling_rate > MAX98927_PCM_SR_SET1_SR_16000) + regmap_update_bits(max98927->regmap, + MAX98927_R0024_PCM_SR_SETUP2, + MAX98927_PCM_SR_SET2_IVADC_SR_MASK, + sampling_rate - 3); + else + regmap_update_bits(max98927->regmap, + MAX98927_R0024_PCM_SR_SETUP2, + MAX98927_PCM_SR_SET2_IVADC_SR_MASK, + sampling_rate); return max98927_set_clock(max98927, params); err: return -EINVAL; @@ -408,33 +417,28 @@ static int max98927_dac_event(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_POST_PMU: regmap_update_bits(max98927->regmap, - MAX98927_R003A_AMP_EN, 1, 1); - /* enable the v and i for vi feedback */ - regmap_update_bits(max98927->regmap, - MAX98927_R003E_MEAS_EN, - MAX98927_MEAS_V_EN, - MAX98927_MEAS_V_EN); + MAX98927_R003A_AMP_EN, + MAX98927_AMP_EN_MASK, 1); + /* enable VMON and IMON */ regmap_update_bits(max98927->regmap, MAX98927_R003E_MEAS_EN, - MAX98927_MEAS_I_EN, - MAX98927_MEAS_I_EN); + MAX98927_MEAS_V_EN | MAX98927_MEAS_I_EN, + MAX98927_MEAS_V_EN | MAX98927_MEAS_I_EN); regmap_update_bits(max98927->regmap, - MAX98927_GLOBAL_EN_MASK, 1, 1); + MAX98927_R00FF_GLOBAL_SHDN, + MAX98927_GLOBAL_EN_MASK, 1); break; case SND_SOC_DAPM_POST_PMD: regmap_update_bits(max98927->regmap, - MAX98927_R00FF_GLOBAL_SHDN, 1, 0); + MAX98927_R00FF_GLOBAL_SHDN, + MAX98927_GLOBAL_EN_MASK, 0); regmap_update_bits(max98927->regmap, - MAX98927_R003A_AMP_EN, 1, 0); - /* disable the v and i for vi feedback */ + MAX98927_R003A_AMP_EN, + MAX98927_AMP_EN_MASK, 0); + /* disable VMON and IMON */ regmap_update_bits(max98927->regmap, MAX98927_R003E_MEAS_EN, - MAX98927_MEAS_V_EN, - 0); - regmap_update_bits(max98927->regmap, - MAX98927_R003E_MEAS_EN, - MAX98927_MEAS_I_EN, - 0); + MAX98927_MEAS_V_EN | MAX98927_MEAS_I_EN, 0); break; default: return 0; @@ -754,13 +758,107 @@ static int max98927_probe(struct snd_soc_codec *codec) dev_info(codec->dev, "MAX98927 revisionID: 0x%02X\n", reg);
+ /* IV default slot configuration */ + regmap_write(max98927->regmap, + MAX98927_R001C_PCM_TX_HIZ_CTRL_A, + 0xFF); + regmap_write(max98927->regmap, + MAX98927_R001D_PCM_TX_HIZ_CTRL_B, + 0xFF); + regmap_write(max98927->regmap, + MAX98927_R0025_PCM_TO_SPK_MONOMIX_A, + 0x80); + regmap_write(max98927->regmap, + MAX98927_R0026_PCM_TO_SPK_MONOMIX_B, + 0x1); + /* Set inital volume (+13dB) */ + regmap_write(max98927->regmap, + MAX98927_R0036_AMP_VOL_CTRL, + 0x38); + regmap_write(max98927->regmap, + MAX98927_R003C_SPK_GAIN, + 0x05); + /* Enable DC blocker */ + regmap_write(max98927->regmap, + MAX98927_R0037_AMP_DSP_CFG, + 0x03); + /* Enable IMON VMON DC blocker */ + regmap_write(max98927->regmap, + MAX98927_R003F_MEAS_DSP_CFG, + 0xF7); + /* Boost Output Voltage & Current limit */ + regmap_write(max98927->regmap, + MAX98927_R0040_BOOST_CTRL0, + 0x1C); + regmap_write(max98927->regmap, + MAX98927_R0042_BOOST_CTRL1, + 0x3E); + /* Measurement ADC config */ + regmap_write(max98927->regmap, + MAX98927_R0043_MEAS_ADC_CFG, + 0x04); + regmap_write(max98927->regmap, + MAX98927_R0044_MEAS_ADC_BASE_MSB, + 0x00); + regmap_write(max98927->regmap, + MAX98927_R0045_MEAS_ADC_BASE_LSB, + 0x24); + /* Brownout Level */ + regmap_write(max98927->regmap, + MAX98927_R007F_BROWNOUT_LVL4_AMP1_CTRL1, + 0x06); + /* Envelope Tracking configuration */ + regmap_write(max98927->regmap, + MAX98927_R0082_ENV_TRACK_VOUT_HEADROOM, + 0x08); + regmap_write(max98927->regmap, + MAX98927_R0086_ENV_TRACK_CTRL, + 0x01); + regmap_write(max98927->regmap, + MAX98927_R0087_ENV_TRACK_BOOST_VOUT_READ, + 0x10);
- if (max98927->regmap) - regmap_write(max98927->regmap, - MAX98927_R001E_PCM_TX_CH_SRC_A, - ((max98927->i_l_slot << - MAX98927_PCM_TX_CH_SRC_A_I_SHIFT) - | max98927->v_l_slot) & 0xFF); + /* voltage, current slot configuration */ + regmap_write(max98927->regmap, + MAX98927_R001E_PCM_TX_CH_SRC_A, + (max98927->i_l_slot<<MAX98927_PCM_TX_CH_SRC_A_I_SHIFT| + max98927->v_l_slot)&0xFF); + + if (max98927->v_l_slot < 8) { + regmap_update_bits(max98927->regmap, + MAX98927_R001C_PCM_TX_HIZ_CTRL_A, + 1 << max98927->v_l_slot, 0); + regmap_update_bits(max98927->regmap, + MAX98927_R001A_PCM_TX_EN_A, + 1 << max98927->v_l_slot, + 1 << max98927->v_l_slot); + } else { + regmap_update_bits(max98927->regmap, + MAX98927_R001D_PCM_TX_HIZ_CTRL_B, + 1 << (max98927->v_l_slot - 8), 0); + regmap_update_bits(max98927->regmap, + MAX98927_R001B_PCM_TX_EN_B, + 1 << (max98927->v_l_slot - 8), + 1 << (max98927->v_l_slot - 8)); + } + + if (max98927->i_l_slot < 8) { + regmap_update_bits(max98927->regmap, + MAX98927_R001C_PCM_TX_HIZ_CTRL_A, + 1 << max98927->i_l_slot, 0); + regmap_update_bits(max98927->regmap, + MAX98927_R001A_PCM_TX_EN_A, + 1 << max98927->i_l_slot, + 1 << max98927->i_l_slot); + } else { + regmap_update_bits(max98927->regmap, + MAX98927_R001D_PCM_TX_HIZ_CTRL_B, + 1 << (max98927->i_l_slot - 8), 0); + regmap_update_bits(max98927->regmap, + MAX98927_R001B_PCM_TX_EN_B, + 1 << (max98927->i_l_slot - 8), + 1 << (max98927->i_l_slot - 8)); + }
/* Set interleave mode */ if (max98927->interleave_mode) @@ -793,9 +891,10 @@ static const struct regmap_config max98927_regmap = { .cache_type = REGCACHE_RBTREE, };
-int probe_common(struct i2c_client *i2c, struct max98927_priv *max98927) +static void max98927_slot_config(struct i2c_client *i2c, + struct max98927_priv *max98927) { - int ret = 0, value; + int value;
if (!of_property_read_u32(i2c->dev.of_node, "vmon-l-slot", &value)) max98927->v_l_slot = value & 0xF; @@ -805,13 +904,6 @@ int probe_common(struct i2c_client *i2c, struct max98927_priv *max98927) max98927->i_l_slot = value & 0xF; else max98927->i_l_slot = 1; - - ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_max98927, - max98927_dai, ARRAY_SIZE(max98927_dai)); - if (ret < 0) - dev_err(&i2c->dev, - "Failed to register codec: %d\n", ret); - return ret; }
static int max98927_i2c_probe(struct i2c_client *i2c, @@ -850,9 +942,14 @@ static int max98927_i2c_probe(struct i2c_client *i2c, goto err; }
+ /* voltage/current slot configuration */ + max98927_slot_config(i2c, max98927);
/* codec registeration */ - ret = probe_common(i2c, max98927); + ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_max98927, + max98927_dai, ARRAY_SIZE(max98927_dai)); + if (ret < 0) + dev_err(&i2c->dev, "Failed to register codec: %d\n", ret);
return ret;
Signed-off-by: Ryan Lee ryans.lee@maximintegrated.com --- 'DAI Sel Mux' was added. 'max98927_volatile_reg' was added to identify volatile register.
sound/soc/codecs/max98927.c | 60 +++++++++++++++++++++++++++++++++------------ sound/soc/codecs/max98927.h | 2 -- 2 files changed, 45 insertions(+), 17 deletions(-)
diff --git a/sound/soc/codecs/max98927.c b/sound/soc/codecs/max98927.c index df2f4ff..6eb745bd 100755 --- a/sound/soc/codecs/max98927.c +++ b/sound/soc/codecs/max98927.c @@ -446,11 +446,24 @@ static int max98927_dac_event(struct snd_soc_dapm_widget *w, return 0; }
+static const char * const max98927_switch_text[] = { + "Left", "Right", "LeftRight"}; + +static const struct soc_enum dai_sel_enum = + SOC_ENUM_SINGLE(MAX98927_R0025_PCM_TO_SPK_MONOMIX_A, + MAX98927_PCM_TO_SPK_MONOMIX_CFG_SHIFT, + 3, max98927_switch_text); + +static const struct snd_kcontrol_new max98927_dai_controls = + SOC_DAPM_ENUM("DAI Sel", dai_sel_enum); + static const struct snd_soc_dapm_widget max98927_dapm_widgets[] = { SND_SOC_DAPM_AIF_IN("DAI_OUT", "HiFi Playback", 0, SND_SOC_NOPM, 0, 0), SND_SOC_DAPM_DAC_E("Amp Enable", "HiFi Playback", MAX98927_R003A_AMP_EN, 0, 0, max98927_dac_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_MUX("DAI Sel Mux", SND_SOC_NOPM, 0, 0, + &max98927_dai_controls), SND_SOC_DAPM_OUTPUT("BE_OUT"), };
@@ -476,12 +489,14 @@ static int max98927_spk_gain_put(struct snd_kcontrol *kcontrol, struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); unsigned int sel = ucontrol->value.integer.value[0];
- if (sel < ((1 << MAX98927_Speaker_Gain_Width) - 1)) { - regmap_update_bits(max98927->regmap, - MAX98927_R003C_SPK_GAIN, - MAX98927_SPK_PCM_GAIN_MASK, sel); - max98927->spk_gain = sel; - } + /* 0x7 is reserved */ + if (sel > 6) + return -EINVAL; + + regmap_update_bits(max98927->regmap, + MAX98927_R003C_SPK_GAIN, + MAX98927_SPK_PCM_GAIN_MASK, sel); + max98927->spk_gain = sel; return 0; }
@@ -538,6 +553,15 @@ static int max98927_amp_vol_get(struct snd_kcontrol *kcontrol, MAX98927_AMP_VOL_SHIFT); }
+static int max98927_amp_vol_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return max98927_reg_put(kcontrol, ucontrol, + MAX98927_R0036_AMP_VOL_CTRL, + MAX98927_AMP_VOL_SEL, + MAX98927_AMP_VOL_SHIFT); +} + static int max98927_amp_dsp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -587,14 +611,6 @@ static int max98927_dre_en_get(struct snd_kcontrol *kcontrol, MAX98927_R0039_DRE_CTRL, MAX98927_DRE_CTRL_DRE_EN, 0); } -static int max98927_amp_vol_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - return max98927_reg_put(kcontrol, ucontrol, - MAX98927_R0036_AMP_VOL_CTRL, - MAX98927_AMP_VOL_SEL, - 7); -} static int max98927_spk_src_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -646,6 +662,15 @@ static bool max98927_readable_register(struct device *dev, unsigned int reg) case MAX98927_R0100_SOFT_RESET: case MAX98927_R01FF_REV_ID: return true; + } + return false; +}; + +static bool max98927_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case MAX98927_R0001_INT_RAW1 ... MAX98927_R0009_INT_FLAG3: + return true; default: return false; } @@ -711,7 +736,11 @@ static const struct snd_kcontrol_new max98927_snd_controls[] = { };
static const struct snd_soc_dapm_route max98927_audio_map[] = { - {"BE_OUT", NULL, "Amp Enable"}, + {"Amp Enable", NULL, "DAI_OUT"}, + {"DAI Sel Mux", "Left", "Amp Enable"}, + {"DAI Sel Mux", "Right", "Amp Enable"}, + {"DAI Sel Mux", "LeftRight", "Amp Enable"}, + {"BE_OUT", NULL, "DAI Sel Mux"}, };
static struct snd_soc_dai_driver max98927_dai[] = { @@ -888,6 +917,7 @@ static const struct regmap_config max98927_regmap = { .reg_defaults = max98927_reg, .num_reg_defaults = ARRAY_SIZE(max98927_reg), .readable_reg = max98927_readable_register, + .volatile_reg = max98927_volatile_reg, .cache_type = REGCACHE_RBTREE, };
diff --git a/sound/soc/codecs/max98927.h b/sound/soc/codecs/max98927.h index 2de8504..e13e18a 100755 --- a/sound/soc/codecs/max98927.h +++ b/sound/soc/codecs/max98927.h @@ -264,6 +264,4 @@ struct max98927_priv { unsigned int master; unsigned int digital_gain; }; -#define MAX98927_Speaker_Gain_Width 3 -#define MAX98927_AMP_VOL_LOCATION_SHIFT 7 #endif
Signed-off-by: Ryan Lee ryans.lee@maximintegrated.com --- snd_kcontrol_chip was changed to snd_soc_kcontrol_codec. acpi_match_table was added.
sound/soc/codecs/max98927.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-)
diff --git a/sound/soc/codecs/max98927.c b/sound/soc/codecs/max98927.c index 6eb745bd..0614936 100755 --- a/sound/soc/codecs/max98927.c +++ b/sound/soc/codecs/max98927.c @@ -10,7 +10,7 @@ * option) any later version. */
-#include <linux/delay.h> +#include <linux/acpi.h> #include <linux/i2c.h> #include <linux/module.h> #include <linux/regmap.h> @@ -144,7 +144,7 @@ static int max98927_reg_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol, unsigned int reg, unsigned int mask, unsigned int shift) { - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); int data;
@@ -157,7 +157,7 @@ static int max98927_reg_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol, unsigned int reg, unsigned int mask, unsigned int shift) { - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); unsigned int sel = ucontrol->value.integer.value[0];
@@ -473,7 +473,7 @@ static DECLARE_TLV_DB_SCALE(max98927_digital_tlv, -1600, 25, 0); static int max98927_spk_gain_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec);
ucontrol->value.integer.value[0] = max98927->spk_gain; @@ -485,7 +485,7 @@ static int max98927_spk_gain_get(struct snd_kcontrol *kcontrol, static int max98927_spk_gain_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); unsigned int sel = ucontrol->value.integer.value[0];
@@ -503,7 +503,7 @@ static int max98927_spk_gain_put(struct snd_kcontrol *kcontrol, static int max98927_digital_gain_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec);
ucontrol->value.integer.value[0] = max98927->digital_gain; @@ -515,7 +515,7 @@ static int max98927_digital_gain_get(struct snd_kcontrol *kcontrol, static int max98927_digital_gain_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); struct max98927_priv *max98927 = snd_soc_codec_get_drvdata(codec); unsigned int sel = ucontrol->value.integer.value[0];
@@ -1002,17 +1002,27 @@ static const struct i2c_device_id max98927_i2c_id[] = {
MODULE_DEVICE_TABLE(i2c, max98927_i2c_id);
+#if defined(CONFIG_OF) static const struct of_device_id max98927_of_match[] = { { .compatible = "maxim,max98927", }, { } }; MODULE_DEVICE_TABLE(of, max98927_of_match); +#endif + +#ifdef CONFIG_ACPI +static const struct acpi_device_id max98927_acpi_match[] = { + { "MX98927", 0 }, + {}, +}; +MODULE_DEVICE_TABLE(acpi, max98927_acpi_match); +#endif
static struct i2c_driver max98927_i2c_driver = { .driver = { .name = "max98927", - .owner = THIS_MODULE, .of_match_table = of_match_ptr(max98927_of_match), + .acpi_match_table = ACPI_PTR(max98927_acpi_match), .pm = NULL, }, .probe = max98927_i2c_probe,
Signed-off-by: Ryan Lee ryans.lee@maximintegrated.com --- Vendor prefix was added. Range information of each propery was added.
.../devicetree/bindings/sound/max98927.txt | 33 +++++++++++++--------- sound/soc/codecs/max98927.c | 8 ++++-- 2 files changed, 25 insertions(+), 16 deletions(-)
diff --git a/Documentation/devicetree/bindings/sound/max98927.txt b/Documentation/devicetree/bindings/sound/max98927.txt index ddcd332..d610879 100755 --- a/Documentation/devicetree/bindings/sound/max98927.txt +++ b/Documentation/devicetree/bindings/sound/max98927.txt @@ -6,19 +6,25 @@ Required properties:
- compatible : "maxim,max98927"
- - vmon-slot-no : slot number used to send voltage information + - maxim,vmon-slot-no : slot number used to send voltage information or in inteleave mode this will be used as interleave slot. - - - imon-slot-no : slot number used to send current information - - - interleave-mode : When using two MAX98927 in a system it is - possible to create ADC data that that will - overflow the frame size. Digital Audio Interleave - mode provides a means to output VMON and IMON data - from two devices on a single DOUT line when running - smaller frames sizes such as 32 BCLKS per LRCLK or - 48 BCLKS per LRCLK. + This property can be set to values from 0 to 15 for slot 0 to 15. + Default value is 0. + + - maxim,imon-slot-no : slot number used to send current information + This property can be set to values from 0 to 15 for slot 0 to 15. + Default value is 0. + + - maxim,interleave-mode : When using two MAX98927 in a system it is + possible to create ADC data that that will + overflow the frame size. Digital Audio Interleave + mode provides a means to output VMON and IMON data + from two devices on a single DOUT line when running + smaller frames sizes such as 32 BCLKS per LRCLK or + 48 BCLKS per LRCLK. + This property can be set to values from 0 to 1 for off and on. + Default value is 0.
- reg : the I2C address of the device for I2C
@@ -26,7 +32,8 @@ Example:
codec: max98927@3a { compatible = "maxim,max98927"; - vmon-slot-no = <1>; - imon-slot-no = <0>; + maxim,vmon-slot-no = <0>; + maxim,imon-slot-no = <1>; + maxim,interleave-mode = <0>; reg = <0x3a>; }; diff --git a/sound/soc/codecs/max98927.c b/sound/soc/codecs/max98927.c index 0614936..b9b7621 100755 --- a/sound/soc/codecs/max98927.c +++ b/sound/soc/codecs/max98927.c @@ -926,11 +926,13 @@ static void max98927_slot_config(struct i2c_client *i2c, { int value;
- if (!of_property_read_u32(i2c->dev.of_node, "vmon-l-slot", &value)) + if (!of_property_read_u32(i2c->dev.of_node, + "maxim,vmon-slot-no", &value)) max98927->v_l_slot = value & 0xF; else max98927->v_l_slot = 0; - if (!of_property_read_u32(i2c->dev.of_node, "imon-l-slot", &value)) + if (!of_property_read_u32(i2c->dev.of_node, + "maxim,imon-slot-no", &value)) max98927->i_l_slot = value & 0xF; else max98927->i_l_slot = 1; @@ -954,7 +956,7 @@ static int max98927_i2c_probe(struct i2c_client *i2c,
/* update interleave mode info */ if (!of_property_read_u32(i2c->dev.of_node, - "interleave_mode", &value)) { + "maxim,interleave_mode", &value)) { if (value > 0) max98927->interleave_mode = 1; else
participants (1)
-
Ryan Lee