aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs')
-rw-r--r--sound/soc/codecs/wm8994.c150
-rw-r--r--sound/soc/codecs/wm8994.h4
2 files changed, 154 insertions, 0 deletions
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index b30b2dd3f1f4..948677b581b1 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -21,6 +21,7 @@
21#include <linux/regulator/consumer.h> 21#include <linux/regulator/consumer.h>
22#include <linux/slab.h> 22#include <linux/slab.h>
23#include <sound/core.h> 23#include <sound/core.h>
24#include <sound/jack.h>
24#include <sound/pcm.h> 25#include <sound/pcm.h>
25#include <sound/pcm_params.h> 26#include <sound/pcm_params.h>
26#include <sound/soc.h> 27#include <sound/soc.h>
@@ -95,6 +96,11 @@ struct wm8994_priv {
95 96
96 struct wm8994_micdet micdet[2]; 97 struct wm8994_micdet micdet[2];
97 98
99 wm8958_micdet_cb jack_cb;
100 void *jack_cb_data;
101 bool jack_is_mic;
102 bool jack_is_video;
103
98 int revision; 104 int revision;
99 struct wm8994_pdata *pdata; 105 struct wm8994_pdata *pdata;
100}; 106};
@@ -140,6 +146,7 @@ static int wm8994_volatile(unsigned int reg)
140 case WM8994_LDO_1: 146 case WM8994_LDO_1:
141 case WM8994_LDO_2: 147 case WM8994_LDO_2:
142 case WM8958_DSP2_EXECCONTROL: 148 case WM8958_DSP2_EXECCONTROL:
149 case WM8958_MIC_DETECT_3:
143 return 1; 150 return 1;
144 default: 151 default:
145 return 0; 152 return 0;
@@ -2633,6 +2640,133 @@ static irqreturn_t wm8994_mic_irq(int irq, void *data)
2633 return IRQ_HANDLED; 2640 return IRQ_HANDLED;
2634} 2641}
2635 2642
2643/* Default microphone detection handler for WM8958 - the user can
2644 * override this if they wish.
2645 */
2646static void wm8958_default_micdet(u16 status, void *data)
2647{
2648 struct snd_soc_codec *codec = data;
2649 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
2650 int report = 0;
2651
2652 /* If nothing present then clear our statuses */
2653 if (!(status & WM8958_MICD_STS)) {
2654 wm8994->jack_is_video = false;
2655 wm8994->jack_is_mic = false;
2656 goto done;
2657 }
2658
2659 /* Assume anything over 475 ohms is a microphone and remember
2660 * that we've seen one (since buttons override it) */
2661 if (status & 0x600)
2662 wm8994->jack_is_mic = true;
2663 if (wm8994->jack_is_mic)
2664 report |= SND_JACK_MICROPHONE;
2665
2666 /* Video has an impedence of approximately 75 ohms; assume
2667 * this isn't used as a button and remember it since buttons
2668 * override it. */
2669 if (status & 0x40)
2670 wm8994->jack_is_video = true;
2671 if (wm8994->jack_is_video)
2672 report |= SND_JACK_VIDEOOUT;
2673
2674 /* Everything else is buttons; just assign slots */
2675 if (status & 0x4)
2676 report |= SND_JACK_BTN_0;
2677 if (status & 0x8)
2678 report |= SND_JACK_BTN_1;
2679 if (status & 0x10)
2680 report |= SND_JACK_BTN_2;
2681 if (status & 0x20)
2682 report |= SND_JACK_BTN_3;
2683 if (status & 0x80)
2684 report |= SND_JACK_BTN_4;
2685 if (status & 0x100)
2686 report |= SND_JACK_BTN_5;
2687
2688done:
2689 snd_soc_jack_report(wm8994->micdet[0].jack,
2690 SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2 |
2691 SND_JACK_BTN_3 | SND_JACK_BTN_4 | SND_JACK_BTN_5 |
2692 SND_JACK_MICROPHONE | SND_JACK_VIDEOOUT,
2693 report);
2694}
2695
2696/**
2697 * wm8958_mic_detect - Enable microphone detection via the WM8958 IRQ
2698 *
2699 * @codec: WM8958 codec
2700 * @jack: jack to report detection events on
2701 *
2702 * Enable microphone detection functionality for the WM8958. By
2703 * default simple detection which supports the detection of up to 6
2704 * buttons plus video and microphone functionality is supported.
2705 *
2706 * The WM8958 has an advanced jack detection facility which is able to
2707 * support complex accessory detection, especially when used in
2708 * conjunction with external circuitry. In order to provide maximum
2709 * flexiblity a callback is provided which allows a completely custom
2710 * detection algorithm.
2711 */
2712int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
2713 wm8958_micdet_cb cb, void *cb_data)
2714{
2715 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
2716 struct wm8994 *control = codec->control_data;
2717
2718 if (control->type != WM8958)
2719 return -EINVAL;
2720
2721 if (jack) {
2722 if (!cb) {
2723 dev_dbg(codec->dev, "Using default micdet callback\n");
2724 cb = wm8958_default_micdet;
2725 cb_data = codec;
2726 }
2727
2728 wm8994->micdet[0].jack = jack;
2729 wm8994->jack_cb = cb;
2730 wm8994->jack_cb_data = cb_data;
2731
2732 snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
2733 WM8958_MICD_ENA, WM8958_MICD_ENA);
2734 } else {
2735 snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
2736 WM8958_MICD_ENA, 0);
2737 }
2738
2739 return 0;
2740}
2741EXPORT_SYMBOL_GPL(wm8958_mic_detect);
2742
2743static irqreturn_t wm8958_mic_irq(int irq, void *data)
2744{
2745 struct wm8994_priv *wm8994 = data;
2746 struct snd_soc_codec *codec = wm8994->codec;
2747 int reg;
2748
2749 reg = snd_soc_read(codec, WM8958_MIC_DETECT_3);
2750 if (reg < 0) {
2751 dev_err(codec->dev, "Failed to read mic detect status: %d\n",
2752 reg);
2753 return IRQ_NONE;
2754 }
2755
2756 if (!(reg & WM8958_MICD_VALID)) {
2757 dev_dbg(codec->dev, "Mic detect data not valid\n");
2758 goto out;
2759 }
2760
2761 if (wm8994->jack_cb)
2762 wm8994->jack_cb(reg, wm8994->jack_cb_data);
2763 else
2764 dev_warn(codec->dev, "Accessory detection with no callback\n");
2765
2766out:
2767 return IRQ_HANDLED;
2768}
2769
2636static int wm8994_codec_probe(struct snd_soc_codec *codec) 2770static int wm8994_codec_probe(struct snd_soc_codec *codec)
2637{ 2771{
2638 struct wm8994 *control; 2772 struct wm8994 *control;
@@ -2732,6 +2866,17 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
2732 "Failed to request Mic2 short IRQ: %d\n", 2866 "Failed to request Mic2 short IRQ: %d\n",
2733 ret); 2867 ret);
2734 break; 2868 break;
2869
2870 case WM8958:
2871 ret = wm8994_request_irq(codec->control_data,
2872 WM8994_IRQ_MIC1_DET,
2873 wm8958_mic_irq, "Mic detect",
2874 wm8994);
2875 if (ret != 0)
2876 dev_warn(codec->dev,
2877 "Failed to request Mic detect IRQ: %d\n",
2878 ret);
2879 break;
2735 } 2880 }
2736 2881
2737 /* Remember if AIFnLRCLK is configured as a GPIO. This should be 2882 /* Remember if AIFnLRCLK is configured as a GPIO. This should be
@@ -2866,6 +3011,11 @@ static int wm8994_codec_remove(struct snd_soc_codec *codec)
2866 wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_DET, 3011 wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_DET,
2867 wm8994); 3012 wm8994);
2868 break; 3013 break;
3014
3015 case WM8958:
3016 wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_DET,
3017 wm8994);
3018 break;
2869 } 3019 }
2870 kfree(wm8994->retune_mobile_texts); 3020 kfree(wm8994->retune_mobile_texts);
2871 kfree(wm8994->drc_texts); 3021 kfree(wm8994->drc_texts);
diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h
index b8b3166e1f03..455cae6b4356 100644
--- a/sound/soc/codecs/wm8994.h
+++ b/sound/soc/codecs/wm8994.h
@@ -28,8 +28,12 @@
28#define WM8994_FLL_SRC_LRCLK 3 28#define WM8994_FLL_SRC_LRCLK 3
29#define WM8994_FLL_SRC_BCLK 4 29#define WM8994_FLL_SRC_BCLK 4
30 30
31typedef void (*wm8958_micdet_cb)(u16 status, void *data);
32
31int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, 33int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
32 int micbias, int det, int shrt); 34 int micbias, int det, int shrt);
35int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
36 wm8958_micdet_cb cb, void *cb_data);
33 37
34#define WM8994_CACHE_SIZE 1570 38#define WM8994_CACHE_SIZE 1570
35 39