aboutsummaryrefslogtreecommitdiff
path: root/sound/soc/soc-jack.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/soc-jack.c')
-rw-r--r--sound/soc/soc-jack.c76
1 files changed, 64 insertions, 12 deletions
diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c
index 7daf21fee355..99902ae1a2d9 100644
--- a/sound/soc/soc-jack.c
+++ b/sound/soc/soc-jack.c
@@ -22,6 +22,12 @@
#include <linux/suspend.h>
#include <trace/events/asoc.h>
+struct jack_gpio_tbl {
+ int count;
+ struct snd_soc_jack *jack;
+ struct snd_soc_jack_gpio *gpios;
+};
+
/**
* snd_soc_codec_set_jack - configure codec jack.
* @codec: CODEC
@@ -36,11 +42,33 @@ int snd_soc_codec_set_jack(struct snd_soc_codec *codec,
if (codec->driver->set_jack)
return codec->driver->set_jack(codec, jack, data);
else
- return -EINVAL;
+ return -ENOTSUPP;
}
EXPORT_SYMBOL_GPL(snd_soc_codec_set_jack);
/**
+ * snd_soc_component_set_jack - configure component jack.
+ * @component: COMPONENTs
+ * @jack: structure to use for the jack
+ * @data: can be used if codec driver need extra data for configuring jack
+ *
+ * Configures and enables jack detection function.
+ */
+int snd_soc_component_set_jack(struct snd_soc_component *component,
+ struct snd_soc_jack *jack, void *data)
+{
+ /* will be removed */
+ if (component->set_jack)
+ return component->set_jack(component, jack, data);
+
+ if (component->driver->set_jack)
+ return component->driver->set_jack(component, jack, data);
+
+ return -ENOTSUPP;
+}
+EXPORT_SYMBOL_GPL(snd_soc_component_set_jack);
+
+/**
* snd_soc_card_jack_new - Create a new jack
* @card: ASoC card
* @id: an identifying string for this jack
@@ -333,6 +361,28 @@ static int snd_soc_jack_pm_notifier(struct notifier_block *nb,
return NOTIFY_DONE;
}
+static void jack_free_gpios(struct snd_soc_jack *jack, int count,
+ struct snd_soc_jack_gpio *gpios)
+{
+ int i;
+
+ for (i = 0; i < count; i++) {
+ gpiod_unexport(gpios[i].desc);
+ unregister_pm_notifier(&gpios[i].pm_notifier);
+ free_irq(gpiod_to_irq(gpios[i].desc), &gpios[i]);
+ cancel_delayed_work_sync(&gpios[i].work);
+ gpiod_put(gpios[i].desc);
+ gpios[i].jack = NULL;
+ }
+}
+
+static void jack_devres_free_gpios(struct device *dev, void *res)
+{
+ struct jack_gpio_tbl *tbl = res;
+
+ jack_free_gpios(tbl->jack, tbl->count, tbl->gpios);
+}
+
/**
* snd_soc_jack_add_gpios - Associate GPIO pins with an ASoC jack
*
@@ -347,6 +397,14 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
struct snd_soc_jack_gpio *gpios)
{
int i, ret;
+ struct jack_gpio_tbl *tbl;
+
+ tbl = devres_alloc(jack_devres_free_gpios, sizeof(*tbl), GFP_KERNEL);
+ if (!tbl)
+ return -ENOMEM;
+ tbl->jack = jack;
+ tbl->count = count;
+ tbl->gpios = gpios;
for (i = 0; i < count; i++) {
if (!gpios[i].name) {
@@ -424,12 +482,14 @@ got_gpio:
msecs_to_jiffies(gpios[i].debounce_time));
}
+ devres_add(jack->card->dev, tbl);
return 0;
err:
gpio_free(gpios[i].gpio);
undo:
- snd_soc_jack_free_gpios(jack, i, gpios);
+ jack_free_gpios(jack, i, gpios);
+ devres_free(tbl);
return ret;
}
@@ -471,16 +531,8 @@ EXPORT_SYMBOL_GPL(snd_soc_jack_add_gpiods);
void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count,
struct snd_soc_jack_gpio *gpios)
{
- int i;
-
- for (i = 0; i < count; i++) {
- gpiod_unexport(gpios[i].desc);
- unregister_pm_notifier(&gpios[i].pm_notifier);
- free_irq(gpiod_to_irq(gpios[i].desc), &gpios[i]);
- cancel_delayed_work_sync(&gpios[i].work);
- gpiod_put(gpios[i].desc);
- gpios[i].jack = NULL;
- }
+ jack_free_gpios(jack, count, gpios);
+ devres_destroy(jack->card->dev, jack_devres_free_gpios, NULL, NULL);
}
EXPORT_SYMBOL_GPL(snd_soc_jack_free_gpios);
#endif /* CONFIG_GPIOLIB */