asoc: tegra: ALC5640 machine: Add support for HP detect
Manoj Gangwal [Mon, 13 Feb 2012 09:41:09 +0000 (14:41 +0530)]
Add support for Headphone detect on Kai.

Bug 928046

Change-Id: Ieffb3aed32e57ca3e43f6a1c8d049ac1b433867f
Signed-off-by: Manoj Gangwal <mgangwal@nvidia.com>
Reviewed-on: http://git-master/r/83408
Reviewed-by: Simone Willett <swillett@nvidia.com>
Tested-by: Simone Willett <swillett@nvidia.com>

Rebase-Id: R60dad39051b136e21d143de0812cf2f13b6c0d4a

sound/soc/tegra/tegra_rt5640.c

index 8735c14..2f1cee2 100644 (file)
@@ -268,6 +268,45 @@ enum headset_state {
 static struct switch_dev tegra_rt5640_headset_switch = {
        .name = "h2w1",
 };
+
+static int tegra_rt5640_jack_notifier(struct notifier_block *self,
+                             unsigned long action, void *dev)
+{
+       struct snd_soc_jack *jack = dev;
+       struct snd_soc_codec *codec = jack->codec;
+       struct snd_soc_card *card = codec->card;
+       struct tegra_rt5640 *machine = snd_soc_card_get_drvdata(card);
+       enum headset_state state = BIT_NO_HEADSET;
+
+       if (jack == &tegra_rt5640_hp_jack) {
+               machine->jack_status &= ~SND_JACK_HEADPHONE;
+               machine->jack_status |= (action & SND_JACK_HEADPHONE);
+       } else {
+               machine->jack_status &= ~SND_JACK_MICROPHONE;
+               machine->jack_status |= (action & SND_JACK_MICROPHONE);
+       }
+
+       switch (machine->jack_status) {
+       case SND_JACK_HEADPHONE:
+               state = BIT_HEADSET_NO_MIC;
+               break;
+       case SND_JACK_HEADSET:
+               state = BIT_HEADSET;
+               break;
+       case SND_JACK_MICROPHONE:
+               /* mic: would not report */
+       default:
+               state = BIT_NO_HEADSET;
+       }
+
+       switch_set_state(&tegra_rt5640_headset_switch, state);
+
+       return NOTIFY_OK;
+}
+
+static struct notifier_block tegra_rt5640_jack_detect_nb = {
+       .notifier_call = tegra_rt5640_jack_notifier,
+};
 #else
 static struct snd_soc_jack_pin tegra_rt5640_hp_jack_pins[] = {
        {
@@ -449,6 +488,24 @@ static int tegra_rt5640_init(struct snd_soc_pcm_runtime *rtd)
                gpio_direction_output(pdata->gpio_ext_mic_en, 0);
        }
 
+       if (gpio_is_valid(pdata->gpio_hp_det)) {
+               tegra_rt5640_hp_jack_gpio.gpio = pdata->gpio_hp_det;
+               snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE,
+                               &tegra_rt5640_hp_jack);
+#ifndef CONFIG_SWITCH
+               snd_soc_jack_add_pins(&tegra_rt5640_hp_jack,
+                                       ARRAY_SIZE(tegra_rt5640_hp_jack_pins),
+                                       tegra_rt5640_hp_jack_pins);
+#else
+               snd_soc_jack_notifier_register(&tegra_rt5640_hp_jack,
+                                       &tegra_rt5640_jack_detect_nb);
+#endif
+               snd_soc_jack_add_gpios(&tegra_rt5640_hp_jack,
+                                       1,
+                                       &tegra_rt5640_hp_jack_gpio);
+               machine->gpio_requested |= GPIO_HP_DET;
+       }
+
        ret = snd_soc_add_controls(codec, cardhu_controls,
                        ARRAY_SIZE(cardhu_controls));
        if (ret < 0)