aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@linaro.org>2013-06-17 12:20:32 -0400
committerMark Brown <broonie@linaro.org>2013-06-17 12:20:32 -0400
commit5464389755b78e235c999c2dcf58718d23326d46 (patch)
treea21c3bb7c2fdc087a3c30735ebfc481fc5798a0e
parentf57019aa0a796251e671882004dd58d2cc55f8f1 (diff)
parent2da1c4bf765cb32024e5db6fa75dab92916fa3b1 (diff)
Merge remote-tracking branch 'asoc/topic/wm8994' into asoc-next
-rw-r--r--include/linux/mfd/wm8994/pdata.h5
-rw-r--r--include/linux/mfd/wm8994/registers.h8
-rw-r--r--sound/soc/codecs/wm8994.c188
-rw-r--r--sound/soc/codecs/wm8994.h3
4 files changed, 161 insertions, 43 deletions
diff --git a/include/linux/mfd/wm8994/pdata.h b/include/linux/mfd/wm8994/pdata.h
index 68e776594889..b5046f6313a9 100644
--- a/include/linux/mfd/wm8994/pdata.h
+++ b/include/linux/mfd/wm8994/pdata.h
@@ -182,6 +182,11 @@ struct wm8994_pdata {
182 */ 182 */
183 int micdet_delay; 183 int micdet_delay;
184 184
185 /* Delay between microphone detect completing and reporting on
186 * insert (specified in ms)
187 */
188 int mic_id_delay;
189
185 /* IRQ for microphone detection if brought out directly as a 190 /* IRQ for microphone detection if brought out directly as a
186 * signal. 191 * signal.
187 */ 192 */
diff --git a/include/linux/mfd/wm8994/registers.h b/include/linux/mfd/wm8994/registers.h
index 053548961c15..db8cef3d5321 100644
--- a/include/linux/mfd/wm8994/registers.h
+++ b/include/linux/mfd/wm8994/registers.h
@@ -2668,6 +2668,10 @@
2668/* 2668/*
2669 * R772 (0x304) - AIF1ADC LRCLK 2669 * R772 (0x304) - AIF1ADC LRCLK
2670 */ 2670 */
2671#define WM8958_AIF1_LRCLK_INV 0x1000 /* AIF1_LRCLK_INV */
2672#define WM8958_AIF1_LRCLK_INV_MASK 0x1000 /* AIF1_LRCLK_INV */
2673#define WM8958_AIF1_LRCLK_INV_SHIFT 12 /* AIF1_LRCLK_INV */
2674#define WM8958_AIF1_LRCLK_INV_WIDTH 1 /* AIF1_LRCLK_INV */
2671#define WM8994_AIF1ADC_LRCLK_DIR 0x0800 /* AIF1ADC_LRCLK_DIR */ 2675#define WM8994_AIF1ADC_LRCLK_DIR 0x0800 /* AIF1ADC_LRCLK_DIR */
2672#define WM8994_AIF1ADC_LRCLK_DIR_MASK 0x0800 /* AIF1ADC_LRCLK_DIR */ 2676#define WM8994_AIF1ADC_LRCLK_DIR_MASK 0x0800 /* AIF1ADC_LRCLK_DIR */
2673#define WM8994_AIF1ADC_LRCLK_DIR_SHIFT 11 /* AIF1ADC_LRCLK_DIR */ 2677#define WM8994_AIF1ADC_LRCLK_DIR_SHIFT 11 /* AIF1ADC_LRCLK_DIR */
@@ -2679,6 +2683,10 @@
2679/* 2683/*
2680 * R773 (0x305) - AIF1DAC LRCLK 2684 * R773 (0x305) - AIF1DAC LRCLK
2681 */ 2685 */
2686#define WM8958_AIF1_LRCLK_INV 0x1000 /* AIF1_LRCLK_INV */
2687#define WM8958_AIF1_LRCLK_INV_MASK 0x1000 /* AIF1_LRCLK_INV */
2688#define WM8958_AIF1_LRCLK_INV_SHIFT 12 /* AIF1_LRCLK_INV */
2689#define WM8958_AIF1_LRCLK_INV_WIDTH 1 /* AIF1_LRCLK_INV */
2682#define WM8994_AIF1DAC_LRCLK_DIR 0x0800 /* AIF1DAC_LRCLK_DIR */ 2690#define WM8994_AIF1DAC_LRCLK_DIR 0x0800 /* AIF1DAC_LRCLK_DIR */
2683#define WM8994_AIF1DAC_LRCLK_DIR_MASK 0x0800 /* AIF1DAC_LRCLK_DIR */ 2691#define WM8994_AIF1DAC_LRCLK_DIR_MASK 0x0800 /* AIF1DAC_LRCLK_DIR */
2684#define WM8994_AIF1DAC_LRCLK_DIR_SHIFT 11 /* AIF1DAC_LRCLK_DIR */ 2692#define WM8994_AIF1DAC_LRCLK_DIR_SHIFT 11 /* AIF1DAC_LRCLK_DIR */
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index 29e95f93d482..25580b5a853f 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -16,6 +16,7 @@
16#include <linux/init.h> 16#include <linux/init.h>
17#include <linux/delay.h> 17#include <linux/delay.h>
18#include <linux/pm.h> 18#include <linux/pm.h>
19#include <linux/gcd.h>
19#include <linux/i2c.h> 20#include <linux/i2c.h>
20#include <linux/platform_device.h> 21#include <linux/platform_device.h>
21#include <linux/pm_runtime.h> 22#include <linux/pm_runtime.h>
@@ -1498,6 +1499,24 @@ static const char *aif1dac_text[] = {
1498 "AIF1DACDAT", "AIF3DACDAT", 1499 "AIF1DACDAT", "AIF3DACDAT",
1499}; 1500};
1500 1501
1502static const char *loopback_text[] = {
1503 "None", "ADCDAT",
1504};
1505
1506static const struct soc_enum aif1_loopback_enum =
1507 SOC_ENUM_SINGLE(WM8994_AIF1_CONTROL_2, WM8994_AIF1_LOOPBACK_SHIFT, 2,
1508 loopback_text);
1509
1510static const struct snd_kcontrol_new aif1_loopback =
1511 SOC_DAPM_ENUM("AIF1 Loopback", aif1_loopback_enum);
1512
1513static const struct soc_enum aif2_loopback_enum =
1514 SOC_ENUM_SINGLE(WM8994_AIF2_CONTROL_2, WM8994_AIF2_LOOPBACK_SHIFT, 2,
1515 loopback_text);
1516
1517static const struct snd_kcontrol_new aif2_loopback =
1518 SOC_DAPM_ENUM("AIF2 Loopback", aif2_loopback_enum);
1519
1501static const struct soc_enum aif1dac_enum = 1520static const struct soc_enum aif1dac_enum =
1502 SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 0, 2, aif1dac_text); 1521 SOC_ENUM_SINGLE(WM8994_POWER_MANAGEMENT_6, 0, 2, aif1dac_text);
1503 1522
@@ -1744,6 +1763,9 @@ SND_SOC_DAPM_ADC("DMIC1R", NULL, WM8994_POWER_MANAGEMENT_4, 2, 0),
1744SND_SOC_DAPM_ADC("ADCL", NULL, SND_SOC_NOPM, 1, 0), 1763SND_SOC_DAPM_ADC("ADCL", NULL, SND_SOC_NOPM, 1, 0),
1745SND_SOC_DAPM_ADC("ADCR", NULL, SND_SOC_NOPM, 0, 0), 1764SND_SOC_DAPM_ADC("ADCR", NULL, SND_SOC_NOPM, 0, 0),
1746 1765
1766SND_SOC_DAPM_MUX("AIF1 Loopback", SND_SOC_NOPM, 0, 0, &aif1_loopback),
1767SND_SOC_DAPM_MUX("AIF2 Loopback", SND_SOC_NOPM, 0, 0, &aif2_loopback),
1768
1747SND_SOC_DAPM_POST("Debug log", post_ev), 1769SND_SOC_DAPM_POST("Debug log", post_ev),
1748}; 1770};
1749 1771
@@ -1875,9 +1897,9 @@ static const struct snd_soc_dapm_route intercon[] = {
1875 { "AIF1DAC2L", NULL, "AIF1DAC Mux" }, 1897 { "AIF1DAC2L", NULL, "AIF1DAC Mux" },
1876 { "AIF1DAC2R", NULL, "AIF1DAC Mux" }, 1898 { "AIF1DAC2R", NULL, "AIF1DAC Mux" },
1877 1899
1878 { "AIF1DAC Mux", "AIF1DACDAT", "AIF1DACDAT" }, 1900 { "AIF1DAC Mux", "AIF1DACDAT", "AIF1 Loopback" },
1879 { "AIF1DAC Mux", "AIF3DACDAT", "AIF3DACDAT" }, 1901 { "AIF1DAC Mux", "AIF3DACDAT", "AIF3DACDAT" },
1880 { "AIF2DAC Mux", "AIF2DACDAT", "AIF2DACDAT" }, 1902 { "AIF2DAC Mux", "AIF2DACDAT", "AIF2 Loopback" },
1881 { "AIF2DAC Mux", "AIF3DACDAT", "AIF3DACDAT" }, 1903 { "AIF2DAC Mux", "AIF3DACDAT", "AIF3DACDAT" },
1882 { "AIF2ADC Mux", "AIF2ADCDAT", "AIF2ADCL" }, 1904 { "AIF2ADC Mux", "AIF2ADCDAT", "AIF2ADCL" },
1883 { "AIF2ADC Mux", "AIF2ADCDAT", "AIF2ADCR" }, 1905 { "AIF2ADC Mux", "AIF2ADCDAT", "AIF2ADCR" },
@@ -1928,6 +1950,12 @@ static const struct snd_soc_dapm_route intercon[] = {
1928 { "AIF3ADCDAT", "AIF2DACDAT", "AIF2DACL" }, 1950 { "AIF3ADCDAT", "AIF2DACDAT", "AIF2DACL" },
1929 { "AIF3ADCDAT", "AIF2DACDAT", "AIF2DACR" }, 1951 { "AIF3ADCDAT", "AIF2DACDAT", "AIF2DACR" },
1930 1952
1953 /* Loopback */
1954 { "AIF1 Loopback", "ADCDAT", "AIF1ADCDAT" },
1955 { "AIF1 Loopback", "None", "AIF1DACDAT" },
1956 { "AIF2 Loopback", "ADCDAT", "AIF2ADCDAT" },
1957 { "AIF2 Loopback", "None", "AIF2DACDAT" },
1958
1931 /* Sidetone */ 1959 /* Sidetone */
1932 { "Left Sidetone", "ADC/DMIC1", "ADCL Mux" }, 1960 { "Left Sidetone", "ADC/DMIC1", "ADCL Mux" },
1933 { "Left Sidetone", "DMIC2", "DMIC2L" }, 1961 { "Left Sidetone", "DMIC2", "DMIC2L" },
@@ -2010,15 +2038,16 @@ struct fll_div {
2010 u16 outdiv; 2038 u16 outdiv;
2011 u16 n; 2039 u16 n;
2012 u16 k; 2040 u16 k;
2041 u16 lambda;
2013 u16 clk_ref_div; 2042 u16 clk_ref_div;
2014 u16 fll_fratio; 2043 u16 fll_fratio;
2015}; 2044};
2016 2045
2017static int wm8994_get_fll_config(struct fll_div *fll, 2046static int wm8994_get_fll_config(struct wm8994 *control, struct fll_div *fll,
2018 int freq_in, int freq_out) 2047 int freq_in, int freq_out)
2019{ 2048{
2020 u64 Kpart; 2049 u64 Kpart;
2021 unsigned int K, Ndiv, Nmod; 2050 unsigned int K, Ndiv, Nmod, gcd_fll;
2022 2051
2023 pr_debug("FLL input=%dHz, output=%dHz\n", freq_in, freq_out); 2052 pr_debug("FLL input=%dHz, output=%dHz\n", freq_in, freq_out);
2024 2053
@@ -2067,20 +2096,32 @@ static int wm8994_get_fll_config(struct fll_div *fll,
2067 Nmod = freq_out % freq_in; 2096 Nmod = freq_out % freq_in;
2068 pr_debug("Nmod=%d\n", Nmod); 2097 pr_debug("Nmod=%d\n", Nmod);
2069 2098
2070 /* Calculate fractional part - scale up so we can round. */ 2099 switch (control->type) {
2071 Kpart = FIXED_FLL_SIZE * (long long)Nmod; 2100 case WM8994:
2101 /* Calculate fractional part - scale up so we can round. */
2102 Kpart = FIXED_FLL_SIZE * (long long)Nmod;
2103
2104 do_div(Kpart, freq_in);
2105
2106 K = Kpart & 0xFFFFFFFF;
2072 2107
2073 do_div(Kpart, freq_in); 2108 if ((K % 10) >= 5)
2109 K += 5;
2074 2110
2075 K = Kpart & 0xFFFFFFFF; 2111 /* Move down to proper range now rounding is done */
2112 fll->k = K / 10;
2113 fll->lambda = 0;
2076 2114
2077 if ((K % 10) >= 5) 2115 pr_debug("N=%x K=%x\n", fll->n, fll->k);
2078 K += 5; 2116 break;
2079 2117
2080 /* Move down to proper range now rounding is done */ 2118 default:
2081 fll->k = K / 10; 2119 gcd_fll = gcd(freq_out, freq_in);
2082 2120
2083 pr_debug("N=%x K=%x\n", fll->n, fll->k); 2121 fll->k = (freq_out - (freq_in * fll->n)) / gcd_fll;
2122 fll->lambda = freq_in / gcd_fll;
2123
2124 }
2084 2125
2085 return 0; 2126 return 0;
2086} 2127}
@@ -2144,9 +2185,9 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src,
2144 * analysis bugs spewing warnings. 2185 * analysis bugs spewing warnings.
2145 */ 2186 */
2146 if (freq_out) 2187 if (freq_out)
2147 ret = wm8994_get_fll_config(&fll, freq_in, freq_out); 2188 ret = wm8994_get_fll_config(control, &fll, freq_in, freq_out);
2148 else 2189 else
2149 ret = wm8994_get_fll_config(&fll, wm8994->fll[id].in, 2190 ret = wm8994_get_fll_config(control, &fll, wm8994->fll[id].in,
2150 wm8994->fll[id].out); 2191 wm8994->fll[id].out);
2151 if (ret < 0) 2192 if (ret < 0)
2152 return ret; 2193 return ret;
@@ -2191,6 +2232,17 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src,
2191 WM8994_FLL1_N_MASK, 2232 WM8994_FLL1_N_MASK,
2192 fll.n << WM8994_FLL1_N_SHIFT); 2233 fll.n << WM8994_FLL1_N_SHIFT);
2193 2234
2235 if (fll.lambda) {
2236 snd_soc_update_bits(codec, WM8958_FLL1_EFS_1 + reg_offset,
2237 WM8958_FLL1_LAMBDA_MASK,
2238 fll.lambda);
2239 snd_soc_update_bits(codec, WM8958_FLL1_EFS_2 + reg_offset,
2240 WM8958_FLL1_EFS_ENA, WM8958_FLL1_EFS_ENA);
2241 } else {
2242 snd_soc_update_bits(codec, WM8958_FLL1_EFS_2 + reg_offset,
2243 WM8958_FLL1_EFS_ENA, 0);
2244 }
2245
2194 snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_5 + reg_offset, 2246 snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_5 + reg_offset,
2195 WM8994_FLL1_FRC_NCO | WM8958_FLL1_BYP | 2247 WM8994_FLL1_FRC_NCO | WM8958_FLL1_BYP |
2196 WM8994_FLL1_REFCLK_DIV_MASK | 2248 WM8994_FLL1_REFCLK_DIV_MASK |
@@ -2555,17 +2607,24 @@ static int wm8994_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
2555 struct wm8994 *control = wm8994->wm8994; 2607 struct wm8994 *control = wm8994->wm8994;
2556 int ms_reg; 2608 int ms_reg;
2557 int aif1_reg; 2609 int aif1_reg;
2610 int dac_reg;
2611 int adc_reg;
2558 int ms = 0; 2612 int ms = 0;
2559 int aif1 = 0; 2613 int aif1 = 0;
2614 int lrclk = 0;
2560 2615
2561 switch (dai->id) { 2616 switch (dai->id) {
2562 case 1: 2617 case 1:
2563 ms_reg = WM8994_AIF1_MASTER_SLAVE; 2618 ms_reg = WM8994_AIF1_MASTER_SLAVE;
2564 aif1_reg = WM8994_AIF1_CONTROL_1; 2619 aif1_reg = WM8994_AIF1_CONTROL_1;
2620 dac_reg = WM8994_AIF1DAC_LRCLK;
2621 adc_reg = WM8994_AIF1ADC_LRCLK;
2565 break; 2622 break;
2566 case 2: 2623 case 2:
2567 ms_reg = WM8994_AIF2_MASTER_SLAVE; 2624 ms_reg = WM8994_AIF2_MASTER_SLAVE;
2568 aif1_reg = WM8994_AIF2_CONTROL_1; 2625 aif1_reg = WM8994_AIF2_CONTROL_1;
2626 dac_reg = WM8994_AIF1DAC_LRCLK;
2627 adc_reg = WM8994_AIF1ADC_LRCLK;
2569 break; 2628 break;
2570 default: 2629 default:
2571 return -EINVAL; 2630 return -EINVAL;
@@ -2584,6 +2643,7 @@ static int wm8994_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
2584 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 2643 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
2585 case SND_SOC_DAIFMT_DSP_B: 2644 case SND_SOC_DAIFMT_DSP_B:
2586 aif1 |= WM8994_AIF1_LRCLK_INV; 2645 aif1 |= WM8994_AIF1_LRCLK_INV;
2646 lrclk |= WM8958_AIF1_LRCLK_INV;
2587 case SND_SOC_DAIFMT_DSP_A: 2647 case SND_SOC_DAIFMT_DSP_A:
2588 aif1 |= 0x18; 2648 aif1 |= 0x18;
2589 break; 2649 break;
@@ -2622,12 +2682,14 @@ static int wm8994_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
2622 break; 2682 break;
2623 case SND_SOC_DAIFMT_IB_IF: 2683 case SND_SOC_DAIFMT_IB_IF:
2624 aif1 |= WM8994_AIF1_BCLK_INV | WM8994_AIF1_LRCLK_INV; 2684 aif1 |= WM8994_AIF1_BCLK_INV | WM8994_AIF1_LRCLK_INV;
2685 lrclk |= WM8958_AIF1_LRCLK_INV;
2625 break; 2686 break;
2626 case SND_SOC_DAIFMT_IB_NF: 2687 case SND_SOC_DAIFMT_IB_NF:
2627 aif1 |= WM8994_AIF1_BCLK_INV; 2688 aif1 |= WM8994_AIF1_BCLK_INV;
2628 break; 2689 break;
2629 case SND_SOC_DAIFMT_NB_IF: 2690 case SND_SOC_DAIFMT_NB_IF:
2630 aif1 |= WM8994_AIF1_LRCLK_INV; 2691 aif1 |= WM8994_AIF1_LRCLK_INV;
2692 lrclk |= WM8958_AIF1_LRCLK_INV;
2631 break; 2693 break;
2632 default: 2694 default:
2633 return -EINVAL; 2695 return -EINVAL;
@@ -2658,6 +2720,10 @@ static int wm8994_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
2658 aif1); 2720 aif1);
2659 snd_soc_update_bits(codec, ms_reg, WM8994_AIF1_MSTR, 2721 snd_soc_update_bits(codec, ms_reg, WM8994_AIF1_MSTR,
2660 ms); 2722 ms);
2723 snd_soc_update_bits(codec, dac_reg,
2724 WM8958_AIF1_LRCLK_INV, lrclk);
2725 snd_soc_update_bits(codec, adc_reg,
2726 WM8958_AIF1_LRCLK_INV, lrclk);
2661 2727
2662 return 0; 2728 return 0;
2663} 2729}
@@ -3096,24 +3162,7 @@ static int wm8994_codec_suspend(struct snd_soc_codec *codec)
3096static int wm8994_codec_resume(struct snd_soc_codec *codec) 3162static int wm8994_codec_resume(struct snd_soc_codec *codec)
3097{ 3163{
3098 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); 3164 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
3099 struct wm8994 *control = wm8994->wm8994;
3100 int i, ret; 3165 int i, ret;
3101 unsigned int val, mask;
3102
3103 if (control->revision < 4) {
3104 /* force a HW read */
3105 ret = regmap_read(control->regmap,
3106 WM8994_POWER_MANAGEMENT_5, &val);
3107
3108 /* modify the cache only */
3109 codec->cache_only = 1;
3110 mask = WM8994_DAC1R_ENA | WM8994_DAC1L_ENA |
3111 WM8994_DAC2R_ENA | WM8994_DAC2L_ENA;
3112 val &= mask;
3113 snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_5,
3114 mask, val);
3115 codec->cache_only = 0;
3116 }
3117 3166
3118 for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) { 3167 for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) {
3119 if (!wm8994->fll_suspend[i].out) 3168 if (!wm8994->fll_suspend[i].out)
@@ -3495,6 +3544,31 @@ static void wm8958_button_det(struct snd_soc_codec *codec, u16 status)
3495 wm8994->btn_mask); 3544 wm8994->btn_mask);
3496} 3545}
3497 3546
3547static void wm8958_open_circuit_work(struct work_struct *work)
3548{
3549 struct wm8994_priv *wm8994 = container_of(work,
3550 struct wm8994_priv,
3551 open_circuit_work.work);
3552 struct device *dev = wm8994->wm8994->dev;
3553
3554 wm1811_micd_stop(wm8994->hubs.codec);
3555
3556 mutex_lock(&wm8994->accdet_lock);
3557
3558 dev_dbg(dev, "Reporting open circuit\n");
3559
3560 wm8994->jack_mic = false;
3561 wm8994->mic_detecting = true;
3562
3563 wm8958_micd_set_rate(wm8994->hubs.codec);
3564
3565 snd_soc_jack_report(wm8994->micdet[0].jack, 0,
3566 wm8994->btn_mask |
3567 SND_JACK_HEADSET);
3568
3569 mutex_unlock(&wm8994->accdet_lock);
3570}
3571
3498static void wm8958_mic_id(void *data, u16 status) 3572static void wm8958_mic_id(void *data, u16 status)
3499{ 3573{
3500 struct snd_soc_codec *codec = data; 3574 struct snd_soc_codec *codec = data;
@@ -3504,16 +3578,9 @@ static void wm8958_mic_id(void *data, u16 status)
3504 if (!(status & WM8958_MICD_STS)) { 3578 if (!(status & WM8958_MICD_STS)) {
3505 /* If nothing present then clear our statuses */ 3579 /* If nothing present then clear our statuses */
3506 dev_dbg(codec->dev, "Detected open circuit\n"); 3580 dev_dbg(codec->dev, "Detected open circuit\n");
3507 wm8994->jack_mic = false;
3508 wm8994->mic_detecting = true;
3509
3510 wm1811_micd_stop(codec);
3511
3512 wm8958_micd_set_rate(codec);
3513 3581
3514 snd_soc_jack_report(wm8994->micdet[0].jack, 0, 3582 schedule_delayed_work(&wm8994->open_circuit_work,
3515 wm8994->btn_mask | 3583 msecs_to_jiffies(2500));
3516 SND_JACK_HEADSET);
3517 return; 3584 return;
3518 } 3585 }
3519 3586
@@ -3598,6 +3665,8 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data)
3598 3665
3599 pm_runtime_get_sync(codec->dev); 3666 pm_runtime_get_sync(codec->dev);
3600 3667
3668 cancel_delayed_work_sync(&wm8994->mic_complete_work);
3669
3601 mutex_lock(&wm8994->accdet_lock); 3670 mutex_lock(&wm8994->accdet_lock);
3602 3671
3603 reg = snd_soc_read(codec, WM1811_JACKDET_CTRL); 3672 reg = snd_soc_read(codec, WM1811_JACKDET_CTRL);
@@ -3780,11 +3849,33 @@ int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
3780} 3849}
3781EXPORT_SYMBOL_GPL(wm8958_mic_detect); 3850EXPORT_SYMBOL_GPL(wm8958_mic_detect);
3782 3851
3852static void wm8958_mic_work(struct work_struct *work)
3853{
3854 struct wm8994_priv *wm8994 = container_of(work,
3855 struct wm8994_priv,
3856 mic_complete_work.work);
3857 struct snd_soc_codec *codec = wm8994->hubs.codec;
3858
3859 dev_crit(codec->dev, "MIC WORK %x\n", wm8994->mic_status);
3860
3861 pm_runtime_get_sync(codec->dev);
3862
3863 mutex_lock(&wm8994->accdet_lock);
3864
3865 wm8994->mic_id_cb(wm8994->mic_id_cb_data, wm8994->mic_status);
3866
3867 mutex_unlock(&wm8994->accdet_lock);
3868
3869 pm_runtime_put(codec->dev);
3870
3871 dev_crit(codec->dev, "MIC WORK %x DONE\n", wm8994->mic_status);
3872}
3873
3783static irqreturn_t wm8958_mic_irq(int irq, void *data) 3874static irqreturn_t wm8958_mic_irq(int irq, void *data)
3784{ 3875{
3785 struct wm8994_priv *wm8994 = data; 3876 struct wm8994_priv *wm8994 = data;
3786 struct snd_soc_codec *codec = wm8994->hubs.codec; 3877 struct snd_soc_codec *codec = wm8994->hubs.codec;
3787 int reg, count, ret; 3878 int reg, count, ret, id_delay;
3788 3879
3789 /* 3880 /*
3790 * Jack detection may have detected a removal simulataneously 3881 * Jack detection may have detected a removal simulataneously
@@ -3794,6 +3885,9 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data)
3794 if (!(snd_soc_read(codec, WM8958_MIC_DETECT_1) & WM8958_MICD_ENA)) 3885 if (!(snd_soc_read(codec, WM8958_MIC_DETECT_1) & WM8958_MICD_ENA))
3795 return IRQ_HANDLED; 3886 return IRQ_HANDLED;
3796 3887
3888 cancel_delayed_work_sync(&wm8994->mic_complete_work);
3889 cancel_delayed_work_sync(&wm8994->open_circuit_work);
3890
3797 pm_runtime_get_sync(codec->dev); 3891 pm_runtime_get_sync(codec->dev);
3798 3892
3799 /* We may occasionally read a detection without an impedence 3893 /* We may occasionally read a detection without an impedence
@@ -3846,8 +3940,12 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data)
3846 goto out; 3940 goto out;
3847 } 3941 }
3848 3942
3943 wm8994->mic_status = reg;
3944 id_delay = wm8994->wm8994->pdata.mic_id_delay;
3945
3849 if (wm8994->mic_detecting) 3946 if (wm8994->mic_detecting)
3850 wm8994->mic_id_cb(wm8994->mic_id_cb_data, reg); 3947 schedule_delayed_work(&wm8994->mic_complete_work,
3948 msecs_to_jiffies(id_delay));
3851 else 3949 else
3852 wm8958_button_det(codec, reg); 3950 wm8958_button_det(codec, reg);
3853 3951
@@ -3899,6 +3997,8 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
3899 mutex_init(&wm8994->accdet_lock); 3997 mutex_init(&wm8994->accdet_lock);
3900 INIT_DELAYED_WORK(&wm8994->jackdet_bootstrap, 3998 INIT_DELAYED_WORK(&wm8994->jackdet_bootstrap,
3901 wm1811_jackdet_bootstrap); 3999 wm1811_jackdet_bootstrap);
4000 INIT_DELAYED_WORK(&wm8994->open_circuit_work,
4001 wm8958_open_circuit_work);
3902 4002
3903 switch (control->type) { 4003 switch (control->type) {
3904 case WM8994: 4004 case WM8994:
@@ -3911,6 +4011,8 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
3911 break; 4011 break;
3912 } 4012 }
3913 4013
4014 INIT_DELAYED_WORK(&wm8994->mic_complete_work, wm8958_mic_work);
4015
3914 for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) 4016 for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++)
3915 init_completion(&wm8994->fll_locked[i]); 4017 init_completion(&wm8994->fll_locked[i]);
3916 4018
diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h
index 55ddf4d57d9b..6536f8d45ac6 100644
--- a/sound/soc/codecs/wm8994.h
+++ b/sound/soc/codecs/wm8994.h
@@ -134,6 +134,9 @@ struct wm8994_priv {
134 struct mutex accdet_lock; 134 struct mutex accdet_lock;
135 struct wm8994_micdet micdet[2]; 135 struct wm8994_micdet micdet[2];
136 struct delayed_work mic_work; 136 struct delayed_work mic_work;
137 struct delayed_work open_circuit_work;
138 struct delayed_work mic_complete_work;
139 u16 mic_status;
137 bool mic_detecting; 140 bool mic_detecting;
138 bool jack_mic; 141 bool jack_mic;
139 int btn_mask; 142 int btn_mask;