From: Mark Brown Date: Mon, 21 Aug 2017 20:48:37 +0000 (+0100) Subject: Merge branch 'topic/msm8916' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie... X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=f13db334bf7b68b0086d04ab6a51517ba41123b4;p=GitHub%2Fmoto-9609%2Fandroid_kernel_motorola_exynos9610.git Merge branch 'topic/msm8916' of git://git./linux/kernel/git/broonie/sound into asoc-const --- f13db334bf7b68b0086d04ab6a51517ba41123b4 diff --cc sound/soc/codecs/msm8916-wcd-analog.c index f07674eddc52,f834a639b350..4aa878d29098 --- a/sound/soc/codecs/msm8916-wcd-analog.c +++ b/sound/soc/codecs/msm8916-wcd-analog.c @@@ -736,27 -940,113 +940,112 @@@ static struct regmap *pm8916_get_regmap return dev_get_regmap(dev->parent, NULL); } - static int pm8916_wcd_analog_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) + static irqreturn_t mbhc_btn_release_irq_handler(int irq, void *arg) { - snd_soc_update_bits(dai->codec, CDC_D_CDC_RST_CTL, - RST_CTL_DIG_SW_RST_N_MASK, - RST_CTL_DIG_SW_RST_N_REMOVE_RESET); + struct pm8916_wcd_analog_priv *priv = arg; - return 0; + if (priv->detect_accessory_type) { + struct snd_soc_codec *codec = priv->codec; + u32 val = snd_soc_read(codec, CDC_A_MBHC_RESULT_1); + + /* check if its BTN0 thats released */ + if ((val >= 0) && !(val & CDC_A_MBHC_RESULT_1_BTN_RESULT_MASK)) + priv->mbhc_btn0_pressed = false; + + } else { + snd_soc_jack_report(priv->jack, 0, btn_mask); + } + + return IRQ_HANDLED; } - static void pm8916_wcd_analog_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) + static irqreturn_t mbhc_btn_press_irq_handler(int irq, void *arg) { - snd_soc_update_bits(dai->codec, CDC_D_CDC_RST_CTL, - RST_CTL_DIG_SW_RST_N_MASK, 0); + struct pm8916_wcd_analog_priv *priv = arg; + struct snd_soc_codec *codec = priv->codec; + u32 btn_result; + + btn_result = snd_soc_read(codec, CDC_A_MBHC_RESULT_1) & + CDC_A_MBHC_RESULT_1_BTN_RESULT_MASK; + + switch (btn_result) { + case 0xf: + snd_soc_jack_report(priv->jack, SND_JACK_BTN_4, btn_mask); + break; + case 0x7: + snd_soc_jack_report(priv->jack, SND_JACK_BTN_3, btn_mask); + break; + case 0x3: + snd_soc_jack_report(priv->jack, SND_JACK_BTN_2, btn_mask); + break; + case 0x1: + snd_soc_jack_report(priv->jack, SND_JACK_BTN_1, btn_mask); + break; + case 0x0: + /* handle BTN_0 specially for type detection */ + if (priv->detect_accessory_type) + priv->mbhc_btn0_pressed = true; + else + snd_soc_jack_report(priv->jack, + SND_JACK_BTN_0, btn_mask); + break; + default: + dev_err(codec->dev, + "Unexpected button press result (%x)", btn_result); + break; + } + + return IRQ_HANDLED; } - static const struct snd_soc_dai_ops pm8916_wcd_analog_dai_ops = { - .startup = pm8916_wcd_analog_startup, - .shutdown = pm8916_wcd_analog_shutdown, - }; - + static irqreturn_t pm8916_mbhc_switch_irq_handler(int irq, void *arg) + { + struct pm8916_wcd_analog_priv *priv = arg; + struct snd_soc_codec *codec = priv->codec; + bool ins = false; + + if (snd_soc_read(codec, CDC_A_MBHC_DET_CTL_1) & + CDC_A_MBHC_DET_CTL_MECH_DET_TYPE_MASK) + ins = true; + + /* Set the detection type appropriately */ + snd_soc_update_bits(codec, CDC_A_MBHC_DET_CTL_1, + CDC_A_MBHC_DET_CTL_MECH_DET_TYPE_MASK, + (!ins << CDC_A_MBHC_DET_CTL_MECH_DET_TYPE_SHIFT)); + + + if (ins) { /* hs insertion */ + bool micbias_enabled = false; + + if (snd_soc_read(codec, CDC_A_MICB_2_EN) & + CDC_A_MICB_2_EN_ENABLE) + micbias_enabled = true; + + pm8916_mbhc_configure_bias(priv, micbias_enabled); + + /* + * if only a btn0 press event is receive just before + * insert event then its a 3 pole headphone else if + * both press and release event received then its + * a headset. + */ + if (priv->mbhc_btn0_pressed) + snd_soc_jack_report(priv->jack, + SND_JACK_HEADPHONE, hs_jack_mask); + else + snd_soc_jack_report(priv->jack, + SND_JACK_HEADSET, hs_jack_mask); + + priv->detect_accessory_type = false; + + } else { /* removal */ + snd_soc_jack_report(priv->jack, 0, hs_jack_mask); + priv->detect_accessory_type = true; + priv->mbhc_btn0_pressed = false; + } + + return IRQ_HANDLED; + } static struct snd_soc_dai_driver pm8916_wcd_analog_dai[] = { [0] = {