forked from Minki/linux
ASoC: mediatek: mt6358: save output volume for mixer controls
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 <tzungbi@google.com> Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
bdb8fa6b09
commit
bbb56537a3
@ -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, ®);
|
||||
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, ®);
|
||||
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);
|
||||
@ -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, ®);
|
||||
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, ®);
|
||||
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, ®);
|
||||
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,
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user