diff options
-rw-r--r-- | include/sound/soc.h | 6 | ||||
-rw-r--r-- | sound/soc/soc-jack.c | 38 |
2 files changed, 44 insertions, 0 deletions
diff --git a/include/sound/soc.h b/include/sound/soc.h index b8bac6ae6244..80dfac162723 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -15,6 +15,7 @@ #include <linux/platform_device.h> #include <linux/types.h> +#include <linux/notifier.h> #include <linux/workqueue.h> #include <linux/interrupt.h> #include <linux/kernel.h> @@ -261,6 +262,10 @@ int snd_soc_jack_new(struct snd_soc_card *card, const char *id, int type, void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask); int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count, struct snd_soc_jack_pin *pins); +void snd_soc_jack_notifier_register(struct snd_soc_jack *jack, + struct notifier_block *nb); +void snd_soc_jack_notifier_unregister(struct snd_soc_jack *jack, + struct notifier_block *nb); #ifdef CONFIG_GPIOLIB int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count, struct snd_soc_jack_gpio *gpios); @@ -364,6 +369,7 @@ struct snd_soc_jack { struct snd_soc_card *card; struct list_head pins; int status; + struct blocking_notifier_head notifier; }; /* SoC PCM stream information */ diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c index 3c07a94c2e30..f8fd22cc70bc 100644 --- a/sound/soc/soc-jack.c +++ b/sound/soc/soc-jack.c @@ -37,6 +37,7 @@ int snd_soc_jack_new(struct snd_soc_card *card, const char *id, int type, { jack->card = card; INIT_LIST_HEAD(&jack->pins); + BLOCKING_INIT_NOTIFIER_HEAD(&jack->notifier); return snd_jack_new(card->codec->card, id, type, &jack->jack); } @@ -93,6 +94,9 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask) snd_soc_dapm_disable_pin(codec, pin->pin); } + /* Report before the DAPM sync to help users updating micbias status */ + blocking_notifier_call_chain(&jack->notifier, status, NULL); + snd_soc_dapm_sync(codec); snd_jack_report(jack->jack, status); @@ -143,6 +147,40 @@ int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count, } EXPORT_SYMBOL_GPL(snd_soc_jack_add_pins); +/** + * snd_soc_jack_notifier_register - Register a notifier for jack status + * + * @jack: ASoC jack + * @nb: Notifier block to register + * + * Register for notification of the current status of the jack. Note + * that it is not possible to report additional jack events in the + * callback from the notifier, this is intended to support + * applications such as enabling electrical detection only when a + * mechanical detection event has occurred. + */ +void snd_soc_jack_notifier_register(struct snd_soc_jack *jack, + struct notifier_block *nb) +{ + blocking_notifier_chain_register(&jack->notifier, nb); +} +EXPORT_SYMBOL_GPL(snd_soc_jack_notifier_register); + +/** + * snd_soc_jack_notifier_unregister - Unregister a notifier for jack status + * + * @jack: ASoC jack + * @nb: Notifier block to unregister + * + * Stop notifying for status changes. + */ +void snd_soc_jack_notifier_unregister(struct snd_soc_jack *jack, + struct notifier_block *nb) +{ + blocking_notifier_chain_unregister(&jack->notifier, nb); +} +EXPORT_SYMBOL_GPL(snd_soc_jack_notifier_unregister); + #ifdef CONFIG_GPIOLIB /* gpio detect */ static void snd_soc_jack_gpio_detect(struct snd_soc_jack_gpio *gpio) |