aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm8962.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2012-02-23 16:49:37 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-02-23 17:06:58 -0500
commit0512615db6dbf5ab7d5b6f46ebbe657707bb9dad (patch)
tree6252f96d67a7930505d722d63a10483ad007217f /sound/soc/codecs/wm8962.c
parentd690516c6dcef11b87c35ce294ae1fcf9797276f (diff)
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.c59
1 files changed, 39 insertions, 20 deletions
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index dc5f19e1065..6af794510c6 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)
2969 2969
2970static irqreturn_t wm8962_irq(int irq, void *data) 2970static irqreturn_t wm8962_irq(int irq, void *data)
2971{ 2971{
2972 struct snd_soc_codec *codec = data; 2972 struct device *dev = data;
2973 struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); 2973 struct wm8962_priv *wm8962 = dev_get_drvdata(dev);
2974 int mask; 2974 unsigned int mask;
2975 int active; 2975 unsigned int active;
2976 int reg; 2976 int reg, ret;
2977
2978 ret = regmap_read(wm8962->regmap, WM8962_INTERRUPT_STATUS_2_MASK,
2979 &mask);
2980 if (ret != 0) {
2981 dev_err(dev, "Failed to read interrupt mask: %d\n",
2982 ret);
2983 return IRQ_NONE;
2984 }
2977 2985
2978 mask = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2_MASK); 2986 ret = regmap_read(wm8962->regmap, WM8962_INTERRUPT_STATUS_2, &active);
2987 if (ret != 0) {
2988 dev_err(dev, "Failed to read interrupt: %d\n", ret);
2989 return IRQ_NONE;
2990 }
2979 2991
2980 active = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2);
2981 active &= ~mask; 2992 active &= ~mask;
2982 2993
2983 if (!active) 2994 if (!active)
2984 return IRQ_NONE; 2995 return IRQ_NONE;
2985 2996
2986 /* Acknowledge the interrupts */ 2997 /* Acknowledge the interrupts */
2987 snd_soc_write(codec, WM8962_INTERRUPT_STATUS_2, active); 2998 ret = regmap_write(wm8962->regmap, WM8962_INTERRUPT_STATUS_2, active);
2999 if (ret != 0)
3000 dev_warn(dev, "Failed to ack interrupt: %d\n", ret);
2988 3001
2989 if (active & WM8962_FLL_LOCK_EINT) { 3002 if (active & WM8962_FLL_LOCK_EINT) {
2990 dev_dbg(codec->dev, "FLL locked\n"); 3003 dev_dbg(dev, "FLL locked\n");
2991 complete(&wm8962->fll_lock); 3004 complete(&wm8962->fll_lock);
2992 } 3005 }
2993 3006
2994 if (active & WM8962_FIFOS_ERR_EINT) 3007 if (active & WM8962_FIFOS_ERR_EINT)
2995 dev_err(codec->dev, "FIFO error\n"); 3008 dev_err(dev, "FIFO error\n");
2996 3009
2997 if (active & WM8962_TEMP_SHUT_EINT) { 3010 if (active & WM8962_TEMP_SHUT_EINT) {
2998 dev_crit(codec->dev, "Thermal shutdown\n"); 3011 dev_crit(dev, "Thermal shutdown\n");
2999 3012
3000 reg = snd_soc_read(codec, WM8962_THERMAL_SHUTDOWN_STATUS); 3013 ret = regmap_read(wm8962->regmap,
3014 WM8962_THERMAL_SHUTDOWN_STATUS, &reg);
3015 if (ret != 0) {
3016 dev_warn(dev, "Failed to read thermal status: %d\n",
3017 ret);
3018 reg = 0;
3019 }
3001 3020
3002 if (reg & WM8962_TEMP_ERR_HP) 3021 if (reg & WM8962_TEMP_ERR_HP)
3003 dev_crit(codec->dev, "Headphone thermal error\n"); 3022 dev_crit(dev, "Headphone thermal error\n");
3004 if (reg & WM8962_TEMP_WARN_HP) 3023 if (reg & WM8962_TEMP_WARN_HP)
3005 dev_crit(codec->dev, "Headphone thermal warning\n"); 3024 dev_crit(dev, "Headphone thermal warning\n");
3006 if (reg & WM8962_TEMP_ERR_SPK) 3025 if (reg & WM8962_TEMP_ERR_SPK)
3007 dev_crit(codec->dev, "Speaker thermal error\n"); 3026 dev_crit(dev, "Speaker thermal error\n");
3008 if (reg & WM8962_TEMP_WARN_SPK) 3027 if (reg & WM8962_TEMP_WARN_SPK)
3009 dev_crit(codec->dev, "Speaker thermal warning\n"); 3028 dev_crit(dev, "Speaker thermal warning\n");
3010 } 3029 }
3011 3030
3012 if (active & (WM8962_MICSCD_EINT | WM8962_MICD_EINT)) { 3031 if (active & (WM8962_MICSCD_EINT | WM8962_MICD_EINT)) {
3013 dev_dbg(codec->dev, "Microphone event detected\n"); 3032 dev_dbg(dev, "Microphone event detected\n");
3014 3033
3015#ifndef CONFIG_SND_SOC_WM8962_MODULE 3034#ifndef CONFIG_SND_SOC_WM8962_MODULE
3016 trace_snd_soc_jack_irq(dev_name(codec->dev)); 3035 trace_snd_soc_jack_irq(dev_name(dev));
3017#endif 3036#endif
3018 3037
3019 pm_wakeup_event(codec->dev, 300); 3038 pm_wakeup_event(dev, 300);
3020 3039
3021 schedule_delayed_work(&wm8962->mic_work, 3040 schedule_delayed_work(&wm8962->mic_work,
3022 msecs_to_jiffies(250)); 3041 msecs_to_jiffies(250));
@@ -3497,7 +3516,7 @@ static int wm8962_probe(struct snd_soc_codec *codec)
3497 3516
3498 ret = request_threaded_irq(wm8962->irq, NULL, wm8962_irq, 3517 ret = request_threaded_irq(wm8962->irq, NULL, wm8962_irq,
3499 trigger | IRQF_ONESHOT, 3518 trigger | IRQF_ONESHOT,
3500 "wm8962", codec); 3519 "wm8962", codec->dev);
3501 if (ret != 0) { 3520 if (ret != 0) {
3502 dev_err(codec->dev, "Failed to request IRQ %d: %d\n", 3521 dev_err(codec->dev, "Failed to request IRQ %d: %d\n",
3503 wm8962->irq, ret); 3522 wm8962->irq, ret);