summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/sound/soc.h6
-rw-r--r--sound/soc/soc-jack.c38
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)