diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-02-23 21:49:37 +0000 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-02-23 22:06:58 +0000 |
commit | 0512615db6dbf5ab7d5b6f46ebbe657707bb9dad (patch) | |
tree | 6252f96d67a7930505d722d63a10483ad007217f /sound/soc/codecs/wm8962.c | |
parent | d690516c6dcef11b87c35ce294ae1fcf9797276f (diff) | |
download | linux-0512615db6dbf5ab7d5b6f46ebbe657707bb9dad.tar.gz linux-0512615db6dbf5ab7d5b6f46ebbe657707bb9dad.tar.xz |
ASoC: wm8962: Convert interrupt handler to direct regmap usage
Avoids potential locking issues with anything that needs the CODEC lock.
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/codecs/wm8962.c')
-rw-r--r-- | sound/soc/codecs/wm8962.c | 59 |
1 files changed, 39 insertions, 20 deletions
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index dc5f19e1065f..6af794510c60 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -2969,54 +2969,73 @@ static void wm8962_mic_work(struct work_struct *work) static irqreturn_t wm8962_irq(int irq, void *data) { - struct snd_soc_codec *codec = data; - struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); - int mask; - int active; - int reg; + struct device *dev = data; + struct wm8962_priv *wm8962 = dev_get_drvdata(dev); + unsigned int mask; + unsigned int active; + int reg, ret; + + ret = regmap_read(wm8962->regmap, WM8962_INTERRUPT_STATUS_2_MASK, + &mask); + if (ret != 0) { + dev_err(dev, "Failed to read interrupt mask: %d\n", + ret); + return IRQ_NONE; + } - mask = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2_MASK); + ret = regmap_read(wm8962->regmap, WM8962_INTERRUPT_STATUS_2, &active); + if (ret != 0) { + dev_err(dev, "Failed to read interrupt: %d\n", ret); + return IRQ_NONE; + } - active = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2); active &= ~mask; if (!active) return IRQ_NONE; /* Acknowledge the interrupts */ - snd_soc_write(codec, WM8962_INTERRUPT_STATUS_2, active); + ret = regmap_write(wm8962->regmap, WM8962_INTERRUPT_STATUS_2, active); + if (ret != 0) + dev_warn(dev, "Failed to ack interrupt: %d\n", ret); if (active & WM8962_FLL_LOCK_EINT) { - dev_dbg(codec->dev, "FLL locked\n"); + dev_dbg(dev, "FLL locked\n"); complete(&wm8962->fll_lock); } if (active & WM8962_FIFOS_ERR_EINT) - dev_err(codec->dev, "FIFO error\n"); + dev_err(dev, "FIFO error\n"); if (active & WM8962_TEMP_SHUT_EINT) { - dev_crit(codec->dev, "Thermal shutdown\n"); + dev_crit(dev, "Thermal shutdown\n"); - reg = snd_soc_read(codec, WM8962_THERMAL_SHUTDOWN_STATUS); + ret = regmap_read(wm8962->regmap, + WM8962_THERMAL_SHUTDOWN_STATUS, ®); + if (ret != 0) { + dev_warn(dev, "Failed to read thermal status: %d\n", + ret); + reg = 0; + } if (reg & WM8962_TEMP_ERR_HP) - dev_crit(codec->dev, "Headphone thermal error\n"); + dev_crit(dev, "Headphone thermal error\n"); if (reg & WM8962_TEMP_WARN_HP) - dev_crit(codec->dev, "Headphone thermal warning\n"); + dev_crit(dev, "Headphone thermal warning\n"); if (reg & WM8962_TEMP_ERR_SPK) - dev_crit(codec->dev, "Speaker thermal error\n"); + dev_crit(dev, "Speaker thermal error\n"); if (reg & WM8962_TEMP_WARN_SPK) - dev_crit(codec->dev, "Speaker thermal warning\n"); + dev_crit(dev, "Speaker thermal warning\n"); } if (active & (WM8962_MICSCD_EINT | WM8962_MICD_EINT)) { - dev_dbg(codec->dev, "Microphone event detected\n"); + dev_dbg(dev, "Microphone event detected\n"); #ifndef CONFIG_SND_SOC_WM8962_MODULE - trace_snd_soc_jack_irq(dev_name(codec->dev)); + trace_snd_soc_jack_irq(dev_name(dev)); #endif - pm_wakeup_event(codec->dev, 300); + pm_wakeup_event(dev, 300); schedule_delayed_work(&wm8962->mic_work, msecs_to_jiffies(250)); @@ -3497,7 +3516,7 @@ static int wm8962_probe(struct snd_soc_codec *codec) ret = request_threaded_irq(wm8962->irq, NULL, wm8962_irq, trigger | IRQF_ONESHOT, - "wm8962", codec); + "wm8962", codec->dev); if (ret != 0) { dev_err(codec->dev, "Failed to request IRQ %d: %d\n", wm8962->irq, ret); |