diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-02-23 16:49:37 -0500 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-02-23 17:06:58 -0500 |
commit | 0512615db6dbf5ab7d5b6f46ebbe657707bb9dad (patch) | |
tree | 6252f96d67a7930505d722d63a10483ad007217f /sound/soc/codecs/wm8962.c | |
parent | d690516c6dcef11b87c35ce294ae1fcf9797276f (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.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) | |||
2969 | 2969 | ||
2970 | static irqreturn_t wm8962_irq(int irq, void *data) | 2970 | static 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, ®); | ||
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); |