diff options
Diffstat (limited to 'sound/soc/codecs/arizona.c')
-rw-r--r-- | sound/soc/codecs/arizona.c | 78 |
1 files changed, 69 insertions, 9 deletions
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 9550d7433ad0..29202610dd0d 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c @@ -84,7 +84,7 @@ static int arizona_spk_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { - struct snd_soc_codec *codec = w->codec; + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); struct arizona *arizona = dev_get_drvdata(codec->dev->parent); struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); bool manual_ena = false; @@ -692,7 +692,8 @@ static void arizona_in_set_vu(struct snd_soc_codec *codec, int ena) int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { - struct arizona_priv *priv = snd_soc_codec_get_drvdata(w->codec); + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); unsigned int reg; if (w->shift % 2) @@ -705,25 +706,25 @@ int arizona_in_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, priv->in_pending++; break; case SND_SOC_DAPM_POST_PMU: - snd_soc_update_bits(w->codec, reg, ARIZONA_IN1L_MUTE, 0); + snd_soc_update_bits(codec, reg, ARIZONA_IN1L_MUTE, 0); /* If this is the last input pending then allow VU */ priv->in_pending--; if (priv->in_pending == 0) { msleep(1); - arizona_in_set_vu(w->codec, 1); + arizona_in_set_vu(codec, 1); } break; case SND_SOC_DAPM_PRE_PMD: - snd_soc_update_bits(w->codec, reg, + snd_soc_update_bits(codec, reg, ARIZONA_IN1L_MUTE | ARIZONA_IN_VU, ARIZONA_IN1L_MUTE | ARIZONA_IN_VU); break; case SND_SOC_DAPM_POST_PMD: /* Disable volume updates if no inputs are enabled */ - reg = snd_soc_read(w->codec, ARIZONA_INPUT_ENABLES); + reg = snd_soc_read(codec, ARIZONA_INPUT_ENABLES); if (reg == 0) - arizona_in_set_vu(w->codec, 0); + arizona_in_set_vu(codec, 0); } return 0; @@ -734,7 +735,25 @@ int arizona_out_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + switch (w->shift) { + case ARIZONA_OUT1L_ENA_SHIFT: + case ARIZONA_OUT1R_ENA_SHIFT: + case ARIZONA_OUT2L_ENA_SHIFT: + case ARIZONA_OUT2R_ENA_SHIFT: + case ARIZONA_OUT3L_ENA_SHIFT: + case ARIZONA_OUT3R_ENA_SHIFT: + priv->out_up_pending++; + priv->out_up_delay += 17; + break; + default: + break; + } + break; case SND_SOC_DAPM_POST_PMU: switch (w->shift) { case ARIZONA_OUT1L_ENA_SHIFT: @@ -743,13 +762,50 @@ int arizona_out_ev(struct snd_soc_dapm_widget *w, case ARIZONA_OUT2R_ENA_SHIFT: case ARIZONA_OUT3L_ENA_SHIFT: case ARIZONA_OUT3R_ENA_SHIFT: - msleep(17); + priv->out_up_pending--; + if (!priv->out_up_pending) { + msleep(priv->out_up_delay); + priv->out_up_delay = 0; + } break; default: break; } break; + case SND_SOC_DAPM_PRE_PMD: + switch (w->shift) { + case ARIZONA_OUT1L_ENA_SHIFT: + case ARIZONA_OUT1R_ENA_SHIFT: + case ARIZONA_OUT2L_ENA_SHIFT: + case ARIZONA_OUT2R_ENA_SHIFT: + case ARIZONA_OUT3L_ENA_SHIFT: + case ARIZONA_OUT3R_ENA_SHIFT: + priv->out_down_pending++; + priv->out_down_delay++; + break; + default: + break; + } + break; + case SND_SOC_DAPM_POST_PMD: + switch (w->shift) { + case ARIZONA_OUT1L_ENA_SHIFT: + case ARIZONA_OUT1R_ENA_SHIFT: + case ARIZONA_OUT2L_ENA_SHIFT: + case ARIZONA_OUT2R_ENA_SHIFT: + case ARIZONA_OUT3L_ENA_SHIFT: + case ARIZONA_OUT3R_ENA_SHIFT: + priv->out_down_pending--; + if (!priv->out_down_pending) { + msleep(priv->out_down_delay); + priv->out_down_delay = 0; + } + break; + default: + break; + } + break; } return 0; @@ -760,7 +816,8 @@ int arizona_hp_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { - struct arizona_priv *priv = snd_soc_codec_get_drvdata(w->codec); + struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); + struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); struct arizona *arizona = priv->arizona; unsigned int mask = 1 << w->shift; unsigned int val; @@ -772,6 +829,9 @@ int arizona_hp_ev(struct snd_soc_dapm_widget *w, case SND_SOC_DAPM_PRE_PMD: val = 0; break; + case SND_SOC_DAPM_PRE_PMU: + case SND_SOC_DAPM_POST_PMD: + return arizona_out_ev(w, kcontrol, event); default: return -EINVAL; } |