Commit f607e31c authored by Mark Brown's avatar Mark Brown

ASoC: arizona: Fix interaction between headphone outputs and identification

Running HPDET while the headphone outputs are enabled can disrupt the
operation of HPDET. In order to avoid this HPDET needs to disable the
headphone outputs and ASoC needs to not enable them while HPDET is
running.

Do the ASoC side of this by storing the enable state in the core driver
structure and only writing to the device if a flag indicating that the
accessory detection side is in a state where it can have the headphone
output stage enabled.
Signed-off-by: default avatarMark Brown <broonie@opensource.wolfsonmicro.com>
parent 03409071
......@@ -100,6 +100,9 @@ struct arizona {
struct regmap_irq_chip_data *aod_irq_chip;
struct regmap_irq_chip_data *irq_chip;
bool hpdet_magic;
unsigned int hp_ena;
struct mutex clk_lock;
int clk32k_ref;
......
......@@ -364,6 +364,39 @@ int arizona_out_ev(struct snd_soc_dapm_widget *w,
}
EXPORT_SYMBOL_GPL(arizona_out_ev);
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);
unsigned int mask = 1 << w->shift;
unsigned int val;
switch (event) {
case SND_SOC_DAPM_POST_PMU:
val = mask;
break;
case SND_SOC_DAPM_PRE_PMD:
val = 0;
break;
default:
return -EINVAL;
}
/* Store the desired state for the HP outputs */
priv->arizona->hp_ena &= ~mask;
priv->arizona->hp_ena |= val;
/* Force off if HPDET magic is active */
if (priv->arizona->hpdet_magic)
val = 0;
snd_soc_update_bits(w->codec, ARIZONA_OUTPUT_ENABLES_1, mask, val);
return arizona_out_ev(w, kcontrol, event);
}
EXPORT_SYMBOL_GPL(arizona_hp_ev);
static unsigned int arizona_sysclk_48k_rates[] = {
6144000,
12288000,
......
......@@ -184,6 +184,9 @@ extern int arizona_in_ev(struct snd_soc_dapm_widget *w,
extern int arizona_out_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event);
extern int arizona_hp_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event);
extern int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id,
int source, unsigned int freq, int dir);
......
......@@ -1131,11 +1131,11 @@ ARIZONA_DSP_WIDGETS(DSP1, "DSP1"),
SND_SOC_DAPM_VALUE_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1,
ARIZONA_AEC_LOOPBACK_ENA, 0, &wm5102_aec_loopback_mux),
SND_SOC_DAPM_PGA_E("OUT1L", ARIZONA_OUTPUT_ENABLES_1,
ARIZONA_OUT1L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
SND_SOC_DAPM_PGA_E("OUT1L", SND_SOC_NOPM,
ARIZONA_OUT1L_ENA_SHIFT, 0, NULL, 0, arizona_hp_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_E("OUT1R", ARIZONA_OUTPUT_ENABLES_1,
ARIZONA_OUT1R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
SND_SOC_DAPM_PGA_E("OUT1R", SND_SOC_NOPM,
ARIZONA_OUT1R_ENA_SHIFT, 0, NULL, 0, arizona_hp_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_E("OUT2L", ARIZONA_OUTPUT_ENABLES_1,
ARIZONA_OUT2L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
......
......@@ -551,11 +551,11 @@ SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0,
SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0,
ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX2_ENA_SHIFT, 0),
SND_SOC_DAPM_PGA_E("OUT1L", ARIZONA_OUTPUT_ENABLES_1,
ARIZONA_OUT1L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
SND_SOC_DAPM_PGA_E("OUT1L", SND_SOC_NOPM,
ARIZONA_OUT1L_ENA_SHIFT, 0, NULL, 0, arizona_hp_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_E("OUT1R", ARIZONA_OUTPUT_ENABLES_1,
ARIZONA_OUT1R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
SND_SOC_DAPM_PGA_E("OUT1R", SND_SOC_NOPM,
ARIZONA_OUT1R_ENA_SHIFT, 0, NULL, 0, arizona_hp_ev,
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_PGA_E("OUT2L", ARIZONA_OUTPUT_ENABLES_1,
ARIZONA_OUT2L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment