Skip to content

Commit

Permalink
ASoC: Initial WM8962 IRQ support
Browse files Browse the repository at this point in the history
Provide an initial hookup for interrupts on the WM8962. Currently we simply
report error status via log messages if an IRQ is provided for the device.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Acked-by: Liam Girdwood <lrg@slimlogic.co.uk>
  • Loading branch information
Mark Brown committed Sep 29, 2010
1 parent ea738ba commit 45e6550
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 1 deletion.
2 changes: 2 additions & 0 deletions include/sound/wm8962.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
struct wm8962_pdata {
u32 gpio_init[WM8962_MAX_GPIO];

bool irq_active_low;

bool spk_mono; /* Speaker outputs tied together as mono */
};

Expand Down
60 changes: 59 additions & 1 deletion sound/soc/codecs/wm8962.c
Original file line number Diff line number Diff line change
Expand Up @@ -1461,6 +1461,29 @@ static struct snd_soc_dai_driver wm8962_dai = {
.symmetric_rates = 1,
};

static irqreturn_t wm8962_irq(int irq, void *data)
{
struct snd_soc_codec *codec = data;
int mask;
int active;

mask = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2);

active = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2);
active &= ~mask;

if (active & WM8962_FIFOS_ERR_EINT)
dev_err(codec->dev, "FIFO error\n");

if (active & WM8962_TEMP_SHUT_EINT)
dev_crit(codec->dev, "Thermal shutdown\n");

/* Acknowledge the interrupts */
snd_soc_write(codec, WM8962_INTERRUPT_STATUS_2, active);

return IRQ_HANDLED;
}

#ifdef CONFIG_PM
static int wm8962_resume(struct snd_soc_codec *codec)
{
Expand Down Expand Up @@ -1632,7 +1655,9 @@ static int wm8962_probe(struct snd_soc_codec *codec)
int ret;
struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
struct wm8962_pdata *pdata = dev_get_platdata(codec->dev);
int i;
struct i2c_client *i2c = container_of(codec->dev, struct i2c_client,
dev);
int i, trigger, irq_pol;

wm8962->codec = codec;

Expand Down Expand Up @@ -1748,6 +1773,34 @@ static int wm8962_probe(struct snd_soc_codec *codec)

wm8962_init_beep(codec);

if (i2c->irq) {
if (pdata && pdata->irq_active_low) {
trigger = IRQF_TRIGGER_LOW;
irq_pol = WM8962_IRQ_POL;
} else {
trigger = IRQF_TRIGGER_HIGH;
irq_pol = 0;
}

snd_soc_update_bits(codec, WM8962_INTERRUPT_CONTROL,
WM8962_IRQ_POL, irq_pol);

ret = request_threaded_irq(i2c->irq, NULL, wm8962_irq,
trigger | IRQF_ONESHOT,
"wm8962", codec);
if (ret != 0) {
dev_err(codec->dev, "Failed to request IRQ %d: %d\n",
i2c->irq, ret);
/* Non-fatal */
} else {
/* Enable error reporting IRQs by default */
snd_soc_update_bits(codec,
WM8962_INTERRUPT_STATUS_2_MASK,
WM8962_TEMP_SHUT_EINT |
WM8962_FIFOS_ERR_EINT, 0);
}
}

return 0;

err_enable:
Expand All @@ -1762,8 +1815,13 @@ static int wm8962_probe(struct snd_soc_codec *codec)
static int wm8962_remove(struct snd_soc_codec *codec)
{
struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
struct i2c_client *i2c = container_of(codec->dev, struct i2c_client,
dev);
int i;

if (i2c->irq)
free_irq(i2c->irq, codec);

wm8962_free_beep(codec);
for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++)
regulator_unregister_notifier(wm8962->supplies[i].consumer,
Expand Down

0 comments on commit 45e6550

Please sign in to comment.