Signed-off-by: Ryan Lee <ryans....@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....@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;
 
-- 
2.7.4

Reply via email to