| Index: sound/soc/soc-jack.c
|
| diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c
|
| index 8a0a9205b1e785bf92d6ddd773b0a70cc7cf568d..4579ee090bbfdb061393ff2ef2bb497c722c7eb0 100644
|
| --- a/sound/soc/soc-jack.c
|
| +++ b/sound/soc/soc-jack.c
|
| @@ -13,11 +13,11 @@
|
|
|
| #include <sound/jack.h>
|
| #include <sound/soc.h>
|
| -#include <sound/soc-dapm.h>
|
| #include <linux/gpio.h>
|
| #include <linux/interrupt.h>
|
| #include <linux/workqueue.h>
|
| #include <linux/delay.h>
|
| +#include <trace/events/asoc.h>
|
|
|
| /**
|
| * snd_soc_jack_new - Create a new jack
|
| @@ -37,6 +37,7 @@ int snd_soc_jack_new(struct snd_soc_codec *codec, const char *id, int type,
|
| {
|
| jack->codec = codec;
|
| INIT_LIST_HEAD(&jack->pins);
|
| + INIT_LIST_HEAD(&jack->jack_zones);
|
| BLOCKING_INIT_NOTIFIER_HEAD(&jack->notifier);
|
|
|
| return snd_jack_new(codec->card->snd_card, id, type, &jack->jack);
|
| @@ -60,14 +61,18 @@ EXPORT_SYMBOL_GPL(snd_soc_jack_new);
|
| void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask)
|
| {
|
| struct snd_soc_codec *codec;
|
| + struct snd_soc_dapm_context *dapm;
|
| struct snd_soc_jack_pin *pin;
|
| int enable;
|
| int oldstatus;
|
|
|
| + trace_snd_soc_jack_report(jack, mask, status);
|
| +
|
| if (!jack)
|
| return;
|
|
|
| codec = jack->codec;
|
| + dapm = &codec->dapm;
|
|
|
| mutex_lock(&codec->mutex);
|
|
|
| @@ -81,6 +86,8 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask)
|
| if (mask && (jack->status == oldstatus))
|
| goto out;
|
|
|
| + trace_snd_soc_jack_notify(jack, status);
|
| +
|
| list_for_each_entry(pin, &jack->pins, list) {
|
| enable = pin->mask & jack->status;
|
|
|
| @@ -88,15 +95,15 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask)
|
| enable = !enable;
|
|
|
| if (enable)
|
| - snd_soc_dapm_enable_pin(codec, pin->pin);
|
| + snd_soc_dapm_enable_pin(dapm, pin->pin);
|
| else
|
| - snd_soc_dapm_disable_pin(codec, pin->pin);
|
| + snd_soc_dapm_disable_pin(dapm, 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_soc_dapm_sync(dapm);
|
|
|
| snd_jack_report(jack->jack, status);
|
|
|
| @@ -106,6 +113,51 @@ out:
|
| EXPORT_SYMBOL_GPL(snd_soc_jack_report);
|
|
|
| /**
|
| + * snd_soc_jack_add_zones - Associate voltage zones with jack
|
| + *
|
| + * @jack: ASoC jack
|
| + * @count: Number of zones
|
| + * @zone: Array of zones
|
| + *
|
| + * After this function has been called the zones specified in the
|
| + * array will be associated with the jack.
|
| + */
|
| +int snd_soc_jack_add_zones(struct snd_soc_jack *jack, int count,
|
| + struct snd_soc_jack_zone *zones)
|
| +{
|
| + int i;
|
| +
|
| + for (i = 0; i < count; i++) {
|
| + INIT_LIST_HEAD(&zones[i].list);
|
| + list_add(&(zones[i].list), &jack->jack_zones);
|
| + }
|
| + return 0;
|
| +}
|
| +EXPORT_SYMBOL_GPL(snd_soc_jack_add_zones);
|
| +
|
| +/**
|
| + * snd_soc_jack_get_type - Based on the mic bias value, this function returns
|
| + * the type of jack from the zones delcared in the jack type
|
| + *
|
| + * @micbias_voltage: mic bias voltage at adc channel when jack is plugged in
|
| + *
|
| + * Based on the mic bias value passed, this function helps identify
|
| + * the type of jack from the already delcared jack zones
|
| + */
|
| +int snd_soc_jack_get_type(struct snd_soc_jack *jack, int micbias_voltage)
|
| +{
|
| + struct snd_soc_jack_zone *zone;
|
| +
|
| + list_for_each_entry(zone, &jack->jack_zones, list) {
|
| + if (micbias_voltage >= zone->min_mv &&
|
| + micbias_voltage < zone->max_mv)
|
| + return zone->jack_type;
|
| + }
|
| + return 0;
|
| +}
|
| +EXPORT_SYMBOL_GPL(snd_soc_jack_get_type);
|
| +
|
| +/**
|
| * snd_soc_jack_add_pins - Associate DAPM pins with an ASoC jack
|
| *
|
| * @jack: ASoC jack
|
| @@ -188,7 +240,7 @@ static void snd_soc_jack_gpio_detect(struct snd_soc_jack_gpio *gpio)
|
| int enable;
|
| int report;
|
|
|
| - enable = gpio_get_value(gpio->gpio);
|
| + enable = gpio_get_value_cansleep(gpio->gpio);
|
| if (gpio->invert)
|
| enable = !enable;
|
|
|
| @@ -207,6 +259,12 @@ static void snd_soc_jack_gpio_detect(struct snd_soc_jack_gpio *gpio)
|
| static irqreturn_t gpio_handler(int irq, void *data)
|
| {
|
| struct snd_soc_jack_gpio *gpio = data;
|
| + struct device *dev = gpio->jack->codec->card->dev;
|
| +
|
| + trace_snd_soc_jack_irq(gpio->name);
|
| +
|
| + if (device_may_wakeup(dev))
|
| + pm_wakeup_event(dev, gpio->debounce_time + 50);
|
|
|
| schedule_delayed_work(&gpio->work,
|
| msecs_to_jiffies(gpio->debounce_time));
|
| @@ -263,11 +321,12 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
|
| INIT_DELAYED_WORK(&gpios[i].work, gpio_work);
|
| gpios[i].jack = jack;
|
|
|
| - ret = request_irq(gpio_to_irq(gpios[i].gpio),
|
| - gpio_handler,
|
| - IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
|
| - jack->codec->dev->driver->name,
|
| - &gpios[i]);
|
| + ret = request_any_context_irq(gpio_to_irq(gpios[i].gpio),
|
| + gpio_handler,
|
| + IRQF_TRIGGER_RISING |
|
| + IRQF_TRIGGER_FALLING,
|
| + jack->codec->dev->driver->name,
|
| + &gpios[i]);
|
| if (ret)
|
| goto err;
|
|
|
|
|