Skip to content

Commit

Permalink
mfd: Use completion interrupt for WM835x AUXADC
Browse files Browse the repository at this point in the history
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: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
  • Loading branch information
Mark Brown authored and Samuel Ortiz committed Mar 7, 2010
1 parent 11a441c commit d19663a
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 6 deletions.
35 changes: 29 additions & 6 deletions drivers/mfd/wm8350-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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,
Expand All @@ -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.
*/
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions include/linux/mfd/wm8350/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -621,6 +622,7 @@ struct wm8350 {
u16 *reg_cache;

struct mutex auxadc_mutex;
struct completion auxadc_done;

/* Interrupt handling */
struct mutex irq_lock;
Expand Down

0 comments on commit d19663a

Please sign in to comment.