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

Commit d19663ac authored by Mark Brown's avatar Mark Brown Committed by Samuel Ortiz
Browse files

mfd: Use completion interrupt for WM835x AUXADC



Use the completion interrupt generated by the device rather than
polling for conversions to complete. As a backup we still check
the state of the AUXADC if we don't get a completion, mostly for
systems that don't have the WM8350 interrupt infrastructure hooked
up.

Signed-off-by: default avatarMark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: default avatarSamuel Ortiz <sameo@linux.intel.com>
parent 11a441ce
Loading
Loading
Loading
Loading
+29 −6
Original line number Diff line number Diff line
@@ -339,7 +339,6 @@ EXPORT_SYMBOL_GPL(wm8350_reg_unlock);
int wm8350_read_auxadc(struct wm8350 *wm8350, int channel, int scale, int vref)
{
	u16 reg, result = 0;
	int tries = 5;

	if (channel < WM8350_AUXADC_AUX1 || channel > WM8350_AUXADC_TEMP)
		return -EINVAL;
@@ -363,12 +362,13 @@ int wm8350_read_auxadc(struct wm8350 *wm8350, int channel, int scale, int vref)
	reg |= 1 << channel | WM8350_AUXADC_POLL;
	wm8350_reg_write(wm8350, WM8350_DIGITISER_CONTROL_1, reg);

	do {
		schedule_timeout_interruptible(1);
		reg = wm8350_reg_read(wm8350, WM8350_DIGITISER_CONTROL_1);
	} while ((reg & WM8350_AUXADC_POLL) && --tries);
	/* We ignore the result of the completion and just check for a
	 * conversion result, allowing us to soldier on if the IRQ
	 * infrastructure is not set up for the chip. */
	wait_for_completion_timeout(&wm8350->auxadc_done, msecs_to_jiffies(5));

	if (!tries)
	reg = wm8350_reg_read(wm8350, WM8350_DIGITISER_CONTROL_1);
	if (reg & WM8350_AUXADC_POLL)
		dev_err(wm8350->dev, "adc chn %d read timeout\n", channel);
	else
		result = wm8350_reg_read(wm8350,
@@ -385,6 +385,15 @@ int wm8350_read_auxadc(struct wm8350 *wm8350, int channel, int scale, int vref)
}
EXPORT_SYMBOL_GPL(wm8350_read_auxadc);

static irqreturn_t wm8350_auxadc_irq(int irq, void *irq_data)
{
	struct wm8350 *wm8350 = irq_data;

	complete(&wm8350->auxadc_done);

	return IRQ_HANDLED;
}

/*
 * Cache is always host endian.
 */
@@ -682,11 +691,22 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq,
	}

	mutex_init(&wm8350->auxadc_mutex);
	init_completion(&wm8350->auxadc_done);

	ret = wm8350_irq_init(wm8350, irq, pdata);
	if (ret < 0)
		goto err;

	if (wm8350->irq_base) {
		ret = request_threaded_irq(wm8350->irq_base +
					   WM8350_IRQ_AUXADC_DATARDY,
					   NULL, wm8350_auxadc_irq, 0,
					   "auxadc", wm8350);
		if (ret < 0)
			dev_warn(wm8350->dev,
				 "Failed to request AUXADC IRQ: %d\n", ret);
	}

	if (pdata && pdata->init) {
		ret = pdata->init(wm8350);
		if (ret != 0) {
@@ -736,6 +756,9 @@ void wm8350_device_exit(struct wm8350 *wm8350)
	platform_device_unregister(wm8350->gpio.pdev);
	platform_device_unregister(wm8350->codec.pdev);

	if (wm8350->irq_base)
		free_irq(wm8350->irq_base + WM8350_IRQ_AUXADC_DATARDY, wm8350);

	wm8350_irq_exit(wm8350);

	kfree(wm8350->reg_cache);
+2 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
#include <linux/kernel.h>
#include <linux/mutex.h>
#include <linux/interrupt.h>
#include <linux/completion.h>

#include <linux/mfd/wm8350/audio.h>
#include <linux/mfd/wm8350/gpio.h>
@@ -621,6 +622,7 @@ struct wm8350 {
	u16 *reg_cache;

	struct mutex auxadc_mutex;
	struct completion auxadc_done;

	/* Interrupt handling */
	struct mutex irq_lock;