Skip to content

Commit

Permalink
ASoC: mediatek: mt6358: save output volume for mixer controls
Browse files Browse the repository at this point in the history
Output volume settings from mixer controls would be lost.

Imagine that "Headphone Volume" has set to -10dB via amixer:
- in mtk_hp_enable()
  - hp_store_gain() saves the volume setting -10dB from regmap_read()
    to ana_gain[AUDIO_ANALOG_VOLUME_HPOUTL]
  - headset_volume_ramp() ramps up from -10dB to -10dB
- in mtk_hp_disable()
  - headset_volume_ramp() ramps down from -10dB to -40dB

Next time in mtk_hp_enable(), hp_store_gain() would save -40dB but
not -10dB.  As a result, headset_volume_ramp() would ramp from -10dB to
-40dB (which is mute).

Signed-off-by: Tzung-Bi Shih <[email protected]>
Signed-off-by: Mark Brown <[email protected]>
  • Loading branch information
Tzung-Bi Shih authored and broonie committed May 8, 2019
1 parent bdb8fa6 commit bbb5653
Showing 1 changed file with 51 additions and 40 deletions.
91 changes: 51 additions & 40 deletions sound/soc/codecs/mt6358.c
Original file line number Diff line number Diff line change
Expand Up @@ -320,32 +320,6 @@ enum {
#define DL_GAIN_N_40DB_REG (DL_GAIN_N_40DB << 7 | DL_GAIN_N_40DB)
#define DL_GAIN_REG_MASK 0x0f9f

static void lo_store_gain(struct mt6358_priv *priv)
{
unsigned int reg;
unsigned int gain_l, gain_r;

regmap_read(priv->regmap, MT6358_ZCD_CON1, &reg);
gain_l = (reg >> RG_AUDLOLGAIN_SFT) & RG_AUDLOLGAIN_MASK;
gain_r = (reg >> RG_AUDLORGAIN_SFT) & RG_AUDLORGAIN_MASK;

priv->ana_gain[AUDIO_ANALOG_VOLUME_LINEOUTL] = gain_l;
priv->ana_gain[AUDIO_ANALOG_VOLUME_LINEOUTR] = gain_r;
}

static void hp_store_gain(struct mt6358_priv *priv)
{
unsigned int reg;
unsigned int gain_l, gain_r;

regmap_read(priv->regmap, MT6358_ZCD_CON2, &reg);
gain_l = (reg >> RG_AUDHPLGAIN_SFT) & RG_AUDHPLGAIN_MASK;
gain_r = (reg >> RG_AUDHPRGAIN_SFT) & RG_AUDHPRGAIN_MASK;

priv->ana_gain[AUDIO_ANALOG_VOLUME_HPOUTL] = gain_l;
priv->ana_gain[AUDIO_ANALOG_VOLUME_HPOUTR] = gain_r;
}

static void hp_zcd_disable(struct mt6358_priv *priv)
{
regmap_write(priv->regmap, MT6358_ZCD_CON0, 0x0000);
Expand Down Expand Up @@ -439,20 +413,62 @@ static void headset_volume_ramp(struct mt6358_priv *priv, int from, int to)
}
}

static int mt6358_put_volsw(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component =
snd_soc_kcontrol_component(kcontrol);
struct mt6358_priv *priv = snd_soc_component_get_drvdata(component);
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
unsigned int reg;
int ret;

ret = snd_soc_put_volsw(kcontrol, ucontrol);
if (ret < 0)
return ret;

switch (mc->reg) {
case MT6358_ZCD_CON2:
regmap_read(priv->regmap, MT6358_ZCD_CON2, &reg);
priv->ana_gain[AUDIO_ANALOG_VOLUME_HPOUTL] =
(reg >> RG_AUDHPLGAIN_SFT) & RG_AUDHPLGAIN_MASK;
priv->ana_gain[AUDIO_ANALOG_VOLUME_HPOUTR] =
(reg >> RG_AUDHPRGAIN_SFT) & RG_AUDHPRGAIN_MASK;
break;
case MT6358_ZCD_CON1:
regmap_read(priv->regmap, MT6358_ZCD_CON1, &reg);
priv->ana_gain[AUDIO_ANALOG_VOLUME_LINEOUTL] =
(reg >> RG_AUDLOLGAIN_SFT) & RG_AUDLOLGAIN_MASK;
priv->ana_gain[AUDIO_ANALOG_VOLUME_LINEOUTR] =
(reg >> RG_AUDLORGAIN_SFT) & RG_AUDLORGAIN_MASK;
break;
case MT6358_ZCD_CON3:
regmap_read(priv->regmap, MT6358_ZCD_CON3, &reg);
priv->ana_gain[AUDIO_ANALOG_VOLUME_HSOUTL] =
(reg >> RG_AUDHSGAIN_SFT) & RG_AUDHSGAIN_MASK;
priv->ana_gain[AUDIO_ANALOG_VOLUME_HSOUTR] =
(reg >> RG_AUDHSGAIN_SFT) & RG_AUDHSGAIN_MASK;
break;
}

return ret;
}

static const DECLARE_TLV_DB_SCALE(playback_tlv, -1000, 100, 0);
static const DECLARE_TLV_DB_SCALE(pga_tlv, 0, 600, 0);

static const struct snd_kcontrol_new mt6358_snd_controls[] = {
/* dl pga gain */
SOC_DOUBLE_TLV("Headphone Volume",
MT6358_ZCD_CON2, 0, 7, 0x12, 1,
playback_tlv),
SOC_DOUBLE_TLV("Lineout Volume",
MT6358_ZCD_CON1, 0, 7, 0x12, 1,
playback_tlv),
SOC_SINGLE_TLV("Handset Volume",
MT6358_ZCD_CON3, 0, 0x12, 1,
playback_tlv),
SOC_DOUBLE_EXT_TLV("Headphone Volume",
MT6358_ZCD_CON2, 0, 7, 0x12, 1,
snd_soc_get_volsw, mt6358_put_volsw, playback_tlv),
SOC_DOUBLE_EXT_TLV("Lineout Volume",
MT6358_ZCD_CON1, 0, 7, 0x12, 1,
snd_soc_get_volsw, mt6358_put_volsw, playback_tlv),
SOC_SINGLE_EXT_TLV("Handset Volume",
MT6358_ZCD_CON3, 0, 0x12, 1,
snd_soc_get_volsw, mt6358_put_volsw, playback_tlv),
/* ul pga gain */
SOC_DOUBLE_R_TLV("PGA Volume",
MT6358_AUDENC_ANA_CON0, MT6358_AUDENC_ANA_CON1,
Expand Down Expand Up @@ -831,8 +847,6 @@ static int mtk_hp_enable(struct mt6358_priv *priv)
/* Reduce ESD resistance of AU_REFN */
regmap_write(priv->regmap, MT6358_AUDDEC_ANA_CON2, 0x4000);

/* save target gain to restore after hardware open complete */
hp_store_gain(priv);
/* Set HPR/HPL gain as minimum (~ -40dB) */
regmap_write(priv->regmap, MT6358_ZCD_CON2, DL_GAIN_N_40DB_REG);

Expand Down Expand Up @@ -1042,8 +1056,6 @@ static int mtk_hp_spk_enable(struct mt6358_priv *priv)
/* Reduce ESD resistance of AU_REFN */
regmap_write(priv->regmap, MT6358_AUDDEC_ANA_CON2, 0x4000);

/* save target gain to restore after hardware open complete */
hp_store_gain(priv);
/* Set HPR/HPL gain to -10dB */
regmap_write(priv->regmap, MT6358_ZCD_CON2, DL_GAIN_N_10DB_REG);

Expand Down Expand Up @@ -1103,7 +1115,6 @@ static int mtk_hp_spk_enable(struct mt6358_priv *priv)
hp_main_output_ramp(priv, true);

/* Set LO gain as minimum (~ -40dB) */
lo_store_gain(priv);
regmap_write(priv->regmap, MT6358_ZCD_CON1, DL_GAIN_N_40DB_REG);
/* apply volume setting */
headset_volume_ramp(priv,
Expand Down

0 comments on commit bbb5653

Please sign in to comment.