OSDN Git Service

Merge branch 'topic/msm8916' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie...
authorMark Brown <broonie@kernel.org>
Mon, 21 Aug 2017 20:48:37 +0000 (21:48 +0100)
committerMark Brown <broonie@kernel.org>
Mon, 21 Aug 2017 20:48:37 +0000 (21:48 +0100)
1  2 
sound/soc/codecs/msm8916-wcd-analog.c
sound/soc/codecs/rt5663.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] = {
Simple merge