diff options
author | Sumit Bhattacharya <sumitb@nvidia.com> | 2011-10-03 05:10:51 +0530 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2011-11-30 21:52:33 -0800 |
commit | c333609b01af3de744bb909e0e4e57ba0ced0778 (patch) | |
tree | 00ed8b5adb3d683ce239319c40b7c764a0ded43e /sound | |
parent | d6b7aebfafda31f58cb7854bda525840c8ae1fa0 (diff) |
ASoC: Tegra: WM8903: Support switch class
Add support to convey HP and mic jack status to switch class.
Bug 872652
Change-Id: I2d64c97ef8bf0ab3dfeec3c711ef0e8048bff133
Signed-off-by: Sumit Bhattacharya <sumitb@nvidia.com>
Reviewed-on: http://git-master/r/55670
Reviewed-by: Varun Colbert <vcolbert@nvidia.com>
Tested-by: Varun Colbert <vcolbert@nvidia.com>
Rebase-Id: Re41027a605ed344cd0dd90c1bc41656a04afb1c1
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/tegra/tegra_wm8903.c | 99 |
1 files changed, 90 insertions, 9 deletions
diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c index 1f27e7066794..f9b434194e82 100644 --- a/sound/soc/tegra/tegra_wm8903.c +++ b/sound/soc/tegra/tegra_wm8903.c @@ -35,6 +35,9 @@ #include <linux/slab.h> #include <linux/gpio.h> #include <linux/regulator/consumer.h> +#ifdef CONFIG_SWITCH +#include <linux/switch.h> +#endif #include <mach/tegra_wm8903_pdata.h> @@ -67,6 +70,9 @@ struct tegra_wm8903 { struct regulator *spk_reg; struct regulator *dmic_reg; int gpio_requested; +#ifdef CONFIG_SWITCH + int jack_status; +#endif }; static int tegra_wm8903_hw_params(struct snd_pcm_substream *substream, @@ -297,13 +303,7 @@ static struct snd_soc_ops tegra_spdif_ops = { }; static struct snd_soc_jack tegra_wm8903_hp_jack; - -static struct snd_soc_jack_pin tegra_wm8903_hp_jack_pins[] = { - { - .pin = "Headphone Jack", - .mask = SND_JACK_HEADPHONE, - }, -}; +static struct snd_soc_jack tegra_wm8903_mic_jack; static struct snd_soc_jack_gpio tegra_wm8903_hp_jack_gpio = { .name = "headphone detect", @@ -312,7 +312,63 @@ static struct snd_soc_jack_gpio tegra_wm8903_hp_jack_gpio = { .invert = 1, }; -static struct snd_soc_jack tegra_wm8903_mic_jack; +#ifdef CONFIG_SWITCH +/* These values are copied from Android WiredAccessoryObserver */ +enum headset_state { + BIT_NO_HEADSET = 0, + BIT_HEADSET = (1 << 0), + BIT_HEADSET_NO_MIC = (1 << 1), +}; + +static struct switch_dev tegra_wm8903_headset_switch = { + .name = "h2w", +}; + +static int tegra_wm8903_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_wm8903 *machine = snd_soc_card_get_drvdata(card); + enum headset_state state = BIT_NO_HEADSET; + + if (jack == &tegra_wm8903_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_wm8903_headset_switch, state); + + return NOTIFY_OK; +} + +static struct notifier_block tegra_wm8903_jack_detect_nb = { + .notifier_call = tegra_wm8903_jack_notifier, +}; +#else +static struct snd_soc_jack_pin tegra_wm8903_hp_jack_pins[] = { + { + .pin = "Headphone Jack", + .mask = SND_JACK_HEADPHONE, + }, +}; static struct snd_soc_jack_pin tegra_wm8903_mic_jack_pins[] = { { @@ -320,6 +376,7 @@ static struct snd_soc_jack_pin tegra_wm8903_mic_jack_pins[] = { .mask = SND_JACK_MICROPHONE, }, }; +#endif static int tegra_wm8903_event_int_spk(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event) @@ -550,9 +607,14 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd) tegra_wm8903_hp_jack_gpio.gpio = pdata->gpio_hp_det; snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE, &tegra_wm8903_hp_jack); +#ifndef CONFIG_SWITCH snd_soc_jack_add_pins(&tegra_wm8903_hp_jack, ARRAY_SIZE(tegra_wm8903_hp_jack_pins), tegra_wm8903_hp_jack_pins); +#else + snd_soc_jack_notifier_register(&tegra_wm8903_hp_jack, + &tegra_wm8903_jack_detect_nb); +#endif snd_soc_jack_add_gpios(&tegra_wm8903_hp_jack, 1, &tegra_wm8903_hp_jack_gpio); @@ -561,9 +623,14 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd) snd_soc_jack_new(codec, "Mic Jack", SND_JACK_MICROPHONE, &tegra_wm8903_mic_jack); +#ifndef CONFIG_SWITCH snd_soc_jack_add_pins(&tegra_wm8903_mic_jack, ARRAY_SIZE(tegra_wm8903_mic_jack_pins), tegra_wm8903_mic_jack_pins); +#else + snd_soc_jack_notifier_register(&tegra_wm8903_mic_jack, + &tegra_wm8903_jack_detect_nb); +#endif wm8903_mic_detect(codec, &tegra_wm8903_mic_jack, SND_JACK_MICROPHONE, 0); @@ -680,6 +747,13 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev) tegra_wm8903_dai[2].cpu_dai_name = "tegra30-i2s.3"; } +#ifdef CONFIG_SWITCH + /* Addd h2w swith class support */ + ret = switch_dev_register(&tegra_wm8903_headset_switch); + if (ret < 0) + goto err_fini_utils; +#endif + card->dev = &pdev->dev; platform_set_drvdata(pdev, card); snd_soc_card_set_drvdata(card, machine); @@ -719,11 +793,15 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev) if (ret) { dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); - goto err_fini_utils; + goto err_unregister_switch; } return 0; +err_unregister_switch: +#ifdef CONFIG_SWITCH + switch_dev_unregister(&tegra_wm8903_headset_switch); +#endif err_fini_utils: tegra_asoc_utils_fini(&machine->util_data); err_free_machine: @@ -760,6 +838,9 @@ static int __devexit tegra_wm8903_driver_remove(struct platform_device *pdev) tegra_asoc_utils_fini(&machine->util_data); +#ifdef CONFIG_SWITCH + switch_dev_unregister(&tegra_wm8903_headset_switch); +#endif kfree(machine); return 0; |