Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b8d4f7a3 authored by Mark Brown's avatar Mark Brown
Browse files

Merge branch 'topic/jack' of...

Merge branch 'topic/jack' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into asoc-rt5665
parents 17febfa6 d7344010
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -434,6 +434,8 @@ int snd_soc_codec_set_sysclk(struct snd_soc_codec *codec, int clk_id,
			     int source, unsigned int freq, int dir);
int snd_soc_codec_set_pll(struct snd_soc_codec *codec, int pll_id, int source,
			  unsigned int freq_in, unsigned int freq_out);
int snd_soc_codec_set_jack(struct snd_soc_codec *codec,
			   struct snd_soc_jack *jack, void *data);

int snd_soc_register_card(struct snd_soc_card *card);
int snd_soc_unregister_card(struct snd_soc_card *card);
@@ -721,6 +723,7 @@ struct snd_soc_jack_gpio {
	/* private: */
	struct snd_soc_jack *jack;
	struct delayed_work work;
	struct notifier_block pm_notifier;
	struct gpio_desc *desc;

	void *data;
@@ -913,6 +916,8 @@ struct snd_soc_codec_driver {
			  int clk_id, int source, unsigned int freq, int dir);
	int (*set_pll)(struct snd_soc_codec *codec, int pll_id, int source,
		unsigned int freq_in, unsigned int freq_out);
	int (*set_jack)(struct snd_soc_codec *codec,
			struct snd_soc_jack *jack,  void *data);

	/* codec IO */
	struct regmap *(*get_regmap)(struct device *);
+48 −0
Original line number Diff line number Diff line
@@ -19,8 +19,27 @@
#include <linux/workqueue.h>
#include <linux/delay.h>
#include <linux/export.h>
#include <linux/suspend.h>
#include <trace/events/asoc.h>

/**
 * snd_soc_codec_set_jack - configure codec jack.
 * @codec: CODEC
 * @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_codec_set_jack(struct snd_soc_codec *codec,
	struct snd_soc_jack *jack, void *data)
{
	if (codec->driver->set_jack)
		return codec->driver->set_jack(codec, jack, data);
	else
		return -EINVAL;
}
EXPORT_SYMBOL_GPL(snd_soc_codec_set_jack);

/**
 * snd_soc_card_jack_new - Create a new jack
 * @card:  ASoC card
@@ -293,6 +312,27 @@ static void gpio_work(struct work_struct *work)
	snd_soc_jack_gpio_detect(gpio);
}

static int snd_soc_jack_pm_notifier(struct notifier_block *nb,
				    unsigned long action, void *data)
{
	struct snd_soc_jack_gpio *gpio =
			container_of(nb, struct snd_soc_jack_gpio, pm_notifier);

	switch (action) {
	case PM_POST_SUSPEND:
	case PM_POST_HIBERNATION:
	case PM_POST_RESTORE:
		/*
		 * Use workqueue so we do not have to care about running
		 * concurrently with work triggered by the interrupt handler.
		 */
		queue_delayed_work(system_power_efficient_wq, &gpio->work, 0);
		break;
	}

	return NOTIFY_DONE;
}

/**
 * snd_soc_jack_add_gpios - Associate GPIO pins with an ASoC jack
 *
@@ -369,6 +409,13 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
					i, ret);
		}

		/*
		 * Register PM notifier so we do not miss state transitions
		 * happening while system is asleep.
		 */
		gpios[i].pm_notifier.notifier_call = snd_soc_jack_pm_notifier;
		register_pm_notifier(&gpios[i].pm_notifier);

		/* Expose GPIO value over sysfs for diagnostic purposes */
		gpiod_export(gpios[i].desc, false);

@@ -428,6 +475,7 @@ void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count,

	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);