diff options
Diffstat (limited to 'sound/soc/codecs/wm8962.c')
-rw-r--r-- | sound/soc/codecs/wm8962.c | 222 |
1 files changed, 202 insertions, 20 deletions
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index d2c315fa1b9b..f60dfa16545e 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c | |||
@@ -63,6 +63,8 @@ struct wm8962_priv { | |||
63 | int fll_fref; | 63 | int fll_fref; |
64 | int fll_fout; | 64 | int fll_fout; |
65 | 65 | ||
66 | u16 dsp2_ena; | ||
67 | |||
66 | struct delayed_work mic_work; | 68 | struct delayed_work mic_work; |
67 | struct snd_soc_jack *jack; | 69 | struct snd_soc_jack *jack; |
68 | 70 | ||
@@ -837,7 +839,7 @@ static const struct wm8962_reg_access { | |||
837 | [40] = { 0x00FF, 0x01FF, 0x0000 }, /* R40 - SPKOUTL volume */ | 839 | [40] = { 0x00FF, 0x01FF, 0x0000 }, /* R40 - SPKOUTL volume */ |
838 | [41] = { 0x00FF, 0x01FF, 0x0000 }, /* R41 - SPKOUTR volume */ | 840 | [41] = { 0x00FF, 0x01FF, 0x0000 }, /* R41 - SPKOUTR volume */ |
839 | 841 | ||
840 | [47] = { 0x000F, 0x0000, 0x0000 }, /* R47 - Thermal Shutdown Status */ | 842 | [47] = { 0x000F, 0x0000, 0xFFFF }, /* R47 - Thermal Shutdown Status */ |
841 | [48] = { 0x7EC7, 0x7E07, 0xFFFF }, /* R48 - Additional Control (4) */ | 843 | [48] = { 0x7EC7, 0x7E07, 0xFFFF }, /* R48 - Additional Control (4) */ |
842 | [49] = { 0x00D3, 0x00D7, 0xFFFF }, /* R49 - Class D Control 1 */ | 844 | [49] = { 0x00D3, 0x00D7, 0xFFFF }, /* R49 - Class D Control 1 */ |
843 | [51] = { 0x0047, 0x0047, 0x0000 }, /* R51 - Class D Control 2 */ | 845 | [51] = { 0x0047, 0x0047, 0x0000 }, /* R51 - Class D Control 2 */ |
@@ -965,7 +967,7 @@ static const struct wm8962_reg_access { | |||
965 | [584] = { 0x002D, 0x002D, 0x0000 }, /* R584 - IRQ Debounce */ | 967 | [584] = { 0x002D, 0x002D, 0x0000 }, /* R584 - IRQ Debounce */ |
966 | [586] = { 0xC000, 0xC000, 0x0000 }, /* R586 - MICINT Source Pol */ | 968 | [586] = { 0xC000, 0xC000, 0x0000 }, /* R586 - MICINT Source Pol */ |
967 | [768] = { 0x0001, 0x0001, 0x0000 }, /* R768 - DSP2 Power Management */ | 969 | [768] = { 0x0001, 0x0001, 0x0000 }, /* R768 - DSP2 Power Management */ |
968 | [1037] = { 0x0000, 0x003F, 0x0000 }, /* R1037 - DSP2_ExecControl */ | 970 | [1037] = { 0x0000, 0x003F, 0xFFFF }, /* R1037 - DSP2_ExecControl */ |
969 | [4096] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4096 - Write Sequencer 0 */ | 971 | [4096] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4096 - Write Sequencer 0 */ |
970 | [4097] = { 0x00FF, 0x00FF, 0x0000 }, /* R4097 - Write Sequencer 1 */ | 972 | [4097] = { 0x00FF, 0x00FF, 0x0000 }, /* R4097 - Write Sequencer 1 */ |
971 | [4098] = { 0x070F, 0x070F, 0x0000 }, /* R4098 - Write Sequencer 2 */ | 973 | [4098] = { 0x070F, 0x070F, 0x0000 }, /* R4098 - Write Sequencer 2 */ |
@@ -1986,6 +1988,122 @@ static const unsigned int classd_tlv[] = { | |||
1986 | }; | 1988 | }; |
1987 | static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); | 1989 | static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); |
1988 | 1990 | ||
1991 | static int wm8962_dsp2_write_config(struct snd_soc_codec *codec) | ||
1992 | { | ||
1993 | return 0; | ||
1994 | } | ||
1995 | |||
1996 | static int wm8962_dsp2_set_enable(struct snd_soc_codec *codec, u16 val) | ||
1997 | { | ||
1998 | u16 adcl = snd_soc_read(codec, WM8962_LEFT_ADC_VOLUME); | ||
1999 | u16 adcr = snd_soc_read(codec, WM8962_RIGHT_ADC_VOLUME); | ||
2000 | u16 dac = snd_soc_read(codec, WM8962_ADC_DAC_CONTROL_1); | ||
2001 | |||
2002 | /* Mute the ADCs and DACs */ | ||
2003 | snd_soc_write(codec, WM8962_LEFT_ADC_VOLUME, 0); | ||
2004 | snd_soc_write(codec, WM8962_RIGHT_ADC_VOLUME, WM8962_ADC_VU); | ||
2005 | snd_soc_update_bits(codec, WM8962_ADC_DAC_CONTROL_1, | ||
2006 | WM8962_DAC_MUTE, WM8962_DAC_MUTE); | ||
2007 | |||
2008 | snd_soc_write(codec, WM8962_SOUNDSTAGE_ENABLES_0, val); | ||
2009 | |||
2010 | /* Restore the ADCs and DACs */ | ||
2011 | snd_soc_write(codec, WM8962_LEFT_ADC_VOLUME, adcl); | ||
2012 | snd_soc_write(codec, WM8962_RIGHT_ADC_VOLUME, adcr); | ||
2013 | snd_soc_update_bits(codec, WM8962_ADC_DAC_CONTROL_1, | ||
2014 | WM8962_DAC_MUTE, dac); | ||
2015 | |||
2016 | return 0; | ||
2017 | } | ||
2018 | |||
2019 | static int wm8962_dsp2_start(struct snd_soc_codec *codec) | ||
2020 | { | ||
2021 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); | ||
2022 | |||
2023 | wm8962_dsp2_write_config(codec); | ||
2024 | |||
2025 | snd_soc_write(codec, WM8962_DSP2_EXECCONTROL, WM8962_DSP2_RUNR); | ||
2026 | |||
2027 | wm8962_dsp2_set_enable(codec, wm8962->dsp2_ena); | ||
2028 | |||
2029 | return 0; | ||
2030 | } | ||
2031 | |||
2032 | static int wm8962_dsp2_stop(struct snd_soc_codec *codec) | ||
2033 | { | ||
2034 | wm8962_dsp2_set_enable(codec, 0); | ||
2035 | |||
2036 | snd_soc_write(codec, WM8962_DSP2_EXECCONTROL, WM8962_DSP2_STOP); | ||
2037 | |||
2038 | return 0; | ||
2039 | } | ||
2040 | |||
2041 | #define WM8962_DSP2_ENABLE(xname, xshift) \ | ||
2042 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | ||
2043 | .info = wm8962_dsp2_ena_info, \ | ||
2044 | .get = wm8962_dsp2_ena_get, .put = wm8962_dsp2_ena_put, \ | ||
2045 | .private_value = xshift } | ||
2046 | |||
2047 | static int wm8962_dsp2_ena_info(struct snd_kcontrol *kcontrol, | ||
2048 | struct snd_ctl_elem_info *uinfo) | ||
2049 | { | ||
2050 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
2051 | |||
2052 | uinfo->count = 1; | ||
2053 | uinfo->value.integer.min = 0; | ||
2054 | uinfo->value.integer.max = 1; | ||
2055 | |||
2056 | return 0; | ||
2057 | } | ||
2058 | |||
2059 | static int wm8962_dsp2_ena_get(struct snd_kcontrol *kcontrol, | ||
2060 | struct snd_ctl_elem_value *ucontrol) | ||
2061 | { | ||
2062 | int shift = kcontrol->private_value; | ||
2063 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
2064 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); | ||
2065 | |||
2066 | ucontrol->value.integer.value[0] = !!(wm8962->dsp2_ena & 1 << shift); | ||
2067 | |||
2068 | return 0; | ||
2069 | } | ||
2070 | |||
2071 | static int wm8962_dsp2_ena_put(struct snd_kcontrol *kcontrol, | ||
2072 | struct snd_ctl_elem_value *ucontrol) | ||
2073 | { | ||
2074 | int shift = kcontrol->private_value; | ||
2075 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
2076 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); | ||
2077 | int old = wm8962->dsp2_ena; | ||
2078 | int ret = 0; | ||
2079 | int dsp2_running = snd_soc_read(codec, WM8962_DSP2_POWER_MANAGEMENT) & | ||
2080 | WM8962_DSP2_ENA; | ||
2081 | |||
2082 | mutex_lock(&codec->mutex); | ||
2083 | |||
2084 | if (ucontrol->value.integer.value[0]) | ||
2085 | wm8962->dsp2_ena |= 1 << shift; | ||
2086 | else | ||
2087 | wm8962->dsp2_ena &= ~(1 << shift); | ||
2088 | |||
2089 | if (wm8962->dsp2_ena == old) | ||
2090 | goto out; | ||
2091 | |||
2092 | ret = 1; | ||
2093 | |||
2094 | if (dsp2_running) { | ||
2095 | if (wm8962->dsp2_ena) | ||
2096 | wm8962_dsp2_set_enable(codec, wm8962->dsp2_ena); | ||
2097 | else | ||
2098 | wm8962_dsp2_stop(codec); | ||
2099 | } | ||
2100 | |||
2101 | out: | ||
2102 | mutex_unlock(&codec->mutex); | ||
2103 | |||
2104 | return ret; | ||
2105 | } | ||
2106 | |||
1989 | /* The VU bits for the headphones are in a different register to the mute | 2107 | /* The VU bits for the headphones are in a different register to the mute |
1990 | * bits and only take effect on the PGA if it is actually powered. | 2108 | * bits and only take effect on the PGA if it is actually powered. |
1991 | */ | 2109 | */ |
@@ -2021,7 +2139,6 @@ static int wm8962_put_spk_sw(struct snd_kcontrol *kcontrol, | |||
2021 | struct snd_ctl_elem_value *ucontrol) | 2139 | struct snd_ctl_elem_value *ucontrol) |
2022 | { | 2140 | { |
2023 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 2141 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
2024 | u16 *reg_cache = codec->reg_cache; | ||
2025 | int ret; | 2142 | int ret; |
2026 | 2143 | ||
2027 | /* Apply the update (if any) */ | 2144 | /* Apply the update (if any) */ |
@@ -2030,16 +2147,19 @@ static int wm8962_put_spk_sw(struct snd_kcontrol *kcontrol, | |||
2030 | return 0; | 2147 | return 0; |
2031 | 2148 | ||
2032 | /* If the left PGA is enabled hit that VU bit... */ | 2149 | /* If the left PGA is enabled hit that VU bit... */ |
2033 | if (reg_cache[WM8962_PWR_MGMT_2] & WM8962_SPKOUTL_PGA_ENA) | 2150 | ret = snd_soc_read(codec, WM8962_PWR_MGMT_2); |
2034 | return snd_soc_write(codec, WM8962_SPKOUTL_VOLUME, | 2151 | if (ret & WM8962_SPKOUTL_PGA_ENA) { |
2035 | reg_cache[WM8962_SPKOUTL_VOLUME]); | 2152 | snd_soc_write(codec, WM8962_SPKOUTL_VOLUME, |
2153 | snd_soc_read(codec, WM8962_SPKOUTL_VOLUME)); | ||
2154 | return 1; | ||
2155 | } | ||
2036 | 2156 | ||
2037 | /* ...otherwise the right. The VU is stereo. */ | 2157 | /* ...otherwise the right. The VU is stereo. */ |
2038 | if (reg_cache[WM8962_PWR_MGMT_2] & WM8962_SPKOUTR_PGA_ENA) | 2158 | if (ret & WM8962_SPKOUTR_PGA_ENA) |
2039 | return snd_soc_write(codec, WM8962_SPKOUTR_VOLUME, | 2159 | snd_soc_write(codec, WM8962_SPKOUTR_VOLUME, |
2040 | reg_cache[WM8962_SPKOUTR_VOLUME]); | 2160 | snd_soc_read(codec, WM8962_SPKOUTR_VOLUME)); |
2041 | 2161 | ||
2042 | return 0; | 2162 | return 1; |
2043 | } | 2163 | } |
2044 | 2164 | ||
2045 | static const char *cap_hpf_mode_text[] = { | 2165 | static const char *cap_hpf_mode_text[] = { |
@@ -2049,6 +2169,14 @@ static const char *cap_hpf_mode_text[] = { | |||
2049 | static const struct soc_enum cap_hpf_mode = | 2169 | static const struct soc_enum cap_hpf_mode = |
2050 | SOC_ENUM_SINGLE(WM8962_ADC_DAC_CONTROL_2, 10, 2, cap_hpf_mode_text); | 2170 | SOC_ENUM_SINGLE(WM8962_ADC_DAC_CONTROL_2, 10, 2, cap_hpf_mode_text); |
2051 | 2171 | ||
2172 | |||
2173 | static const char *cap_lhpf_mode_text[] = { | ||
2174 | "LPF", "HPF" | ||
2175 | }; | ||
2176 | |||
2177 | static const struct soc_enum cap_lhpf_mode = | ||
2178 | SOC_ENUM_SINGLE(WM8962_LHPF1, 1, 2, cap_lhpf_mode_text); | ||
2179 | |||
2052 | static const struct snd_kcontrol_new wm8962_snd_controls[] = { | 2180 | static const struct snd_kcontrol_new wm8962_snd_controls[] = { |
2053 | SOC_DOUBLE("Input Mixer Switch", WM8962_INPUT_MIXER_CONTROL_1, 3, 2, 1, 1), | 2181 | SOC_DOUBLE("Input Mixer Switch", WM8962_INPUT_MIXER_CONTROL_1, 3, 2, 1, 1), |
2054 | 2182 | ||
@@ -2077,6 +2205,8 @@ SOC_DOUBLE_R("Capture ZC Switch", WM8962_LEFT_INPUT_VOLUME, | |||
2077 | SOC_SINGLE("Capture HPF Switch", WM8962_ADC_DAC_CONTROL_1, 0, 1, 1), | 2205 | SOC_SINGLE("Capture HPF Switch", WM8962_ADC_DAC_CONTROL_1, 0, 1, 1), |
2078 | SOC_ENUM("Capture HPF Mode", cap_hpf_mode), | 2206 | SOC_ENUM("Capture HPF Mode", cap_hpf_mode), |
2079 | SOC_SINGLE("Capture HPF Cutoff", WM8962_ADC_DAC_CONTROL_2, 7, 7, 0), | 2207 | SOC_SINGLE("Capture HPF Cutoff", WM8962_ADC_DAC_CONTROL_2, 7, 7, 0), |
2208 | SOC_SINGLE("Capture LHPF Switch", WM8962_LHPF1, 0, 1, 0), | ||
2209 | SOC_ENUM("Capture LHPF Mode", cap_lhpf_mode), | ||
2080 | 2210 | ||
2081 | SOC_DOUBLE_R_TLV("Sidetone Volume", WM8962_DAC_DSP_MIXING_1, | 2211 | SOC_DOUBLE_R_TLV("Sidetone Volume", WM8962_DAC_DSP_MIXING_1, |
2082 | WM8962_DAC_DSP_MIXING_2, 4, 12, 0, st_tlv), | 2212 | WM8962_DAC_DSP_MIXING_2, 4, 12, 0, st_tlv), |
@@ -2134,6 +2264,11 @@ SOC_DOUBLE_R_TLV("EQ4 Volume", WM8962_EQ3, WM8962_EQ23, | |||
2134 | WM8962_EQL_B4_GAIN_SHIFT, 31, 0, eq_tlv), | 2264 | WM8962_EQL_B4_GAIN_SHIFT, 31, 0, eq_tlv), |
2135 | SOC_DOUBLE_R_TLV("EQ5 Volume", WM8962_EQ3, WM8962_EQ23, | 2265 | SOC_DOUBLE_R_TLV("EQ5 Volume", WM8962_EQ3, WM8962_EQ23, |
2136 | WM8962_EQL_B5_GAIN_SHIFT, 31, 0, eq_tlv), | 2266 | WM8962_EQL_B5_GAIN_SHIFT, 31, 0, eq_tlv), |
2267 | |||
2268 | WM8962_DSP2_ENABLE("VSS Switch", WM8962_VSS_ENA_SHIFT), | ||
2269 | WM8962_DSP2_ENABLE("HPF1 Switch", WM8962_HPF1_ENA_SHIFT), | ||
2270 | WM8962_DSP2_ENABLE("HPF2 Switch", WM8962_HPF2_ENA_SHIFT), | ||
2271 | WM8962_DSP2_ENABLE("HD Bass Switch", WM8962_HDBASS_ENA_SHIFT), | ||
2137 | }; | 2272 | }; |
2138 | 2273 | ||
2139 | static const struct snd_kcontrol_new wm8962_spk_mono_controls[] = { | 2274 | static const struct snd_kcontrol_new wm8962_spk_mono_controls[] = { |
@@ -2365,7 +2500,6 @@ static int out_pga_event(struct snd_soc_dapm_widget *w, | |||
2365 | struct snd_kcontrol *kcontrol, int event) | 2500 | struct snd_kcontrol *kcontrol, int event) |
2366 | { | 2501 | { |
2367 | struct snd_soc_codec *codec = w->codec; | 2502 | struct snd_soc_codec *codec = w->codec; |
2368 | u16 *reg_cache = codec->reg_cache; | ||
2369 | int reg; | 2503 | int reg; |
2370 | 2504 | ||
2371 | switch (w->shift) { | 2505 | switch (w->shift) { |
@@ -2388,11 +2522,36 @@ static int out_pga_event(struct snd_soc_dapm_widget *w, | |||
2388 | 2522 | ||
2389 | switch (event) { | 2523 | switch (event) { |
2390 | case SND_SOC_DAPM_POST_PMU: | 2524 | case SND_SOC_DAPM_POST_PMU: |
2391 | return snd_soc_write(codec, reg, reg_cache[reg]); | 2525 | return snd_soc_write(codec, reg, snd_soc_read(codec, reg)); |
2526 | default: | ||
2527 | BUG(); | ||
2528 | return -EINVAL; | ||
2529 | } | ||
2530 | } | ||
2531 | |||
2532 | static int dsp2_event(struct snd_soc_dapm_widget *w, | ||
2533 | struct snd_kcontrol *kcontrol, int event) | ||
2534 | { | ||
2535 | struct snd_soc_codec *codec = w->codec; | ||
2536 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); | ||
2537 | |||
2538 | switch (event) { | ||
2539 | case SND_SOC_DAPM_POST_PMU: | ||
2540 | if (wm8962->dsp2_ena) | ||
2541 | wm8962_dsp2_start(codec); | ||
2542 | break; | ||
2543 | |||
2544 | case SND_SOC_DAPM_PRE_PMD: | ||
2545 | if (wm8962->dsp2_ena) | ||
2546 | wm8962_dsp2_stop(codec); | ||
2547 | break; | ||
2548 | |||
2392 | default: | 2549 | default: |
2393 | BUG(); | 2550 | BUG(); |
2394 | return -EINVAL; | 2551 | return -EINVAL; |
2395 | } | 2552 | } |
2553 | |||
2554 | return 0; | ||
2396 | } | 2555 | } |
2397 | 2556 | ||
2398 | static const char *st_text[] = { "None", "Right", "Left" }; | 2557 | static const char *st_text[] = { "None", "Right", "Left" }; |
@@ -2509,7 +2668,7 @@ SND_SOC_DAPM_INPUT("IN4R"), | |||
2509 | SND_SOC_DAPM_INPUT("Beep"), | 2668 | SND_SOC_DAPM_INPUT("Beep"), |
2510 | SND_SOC_DAPM_INPUT("DMICDAT"), | 2669 | SND_SOC_DAPM_INPUT("DMICDAT"), |
2511 | 2670 | ||
2512 | SND_SOC_DAPM_MICBIAS("MICBIAS", WM8962_PWR_MGMT_1, 1, 0), | 2671 | SND_SOC_DAPM_SUPPLY("MICBIAS", WM8962_PWR_MGMT_1, 1, 0, NULL, 0), |
2513 | 2672 | ||
2514 | SND_SOC_DAPM_SUPPLY("Class G", WM8962_CHARGE_PUMP_B, 0, 1, NULL, 0), | 2673 | SND_SOC_DAPM_SUPPLY("Class G", WM8962_CHARGE_PUMP_B, 0, 1, NULL, 0), |
2515 | SND_SOC_DAPM_SUPPLY("SYSCLK", WM8962_CLOCKING2, 5, 0, sysclk_event, | 2674 | SND_SOC_DAPM_SUPPLY("SYSCLK", WM8962_CLOCKING2, 5, 0, sysclk_event, |
@@ -2517,6 +2676,9 @@ SND_SOC_DAPM_SUPPLY("SYSCLK", WM8962_CLOCKING2, 5, 0, sysclk_event, | |||
2517 | SND_SOC_DAPM_SUPPLY("Charge Pump", WM8962_CHARGE_PUMP_1, 0, 0, cp_event, | 2676 | SND_SOC_DAPM_SUPPLY("Charge Pump", WM8962_CHARGE_PUMP_1, 0, 0, cp_event, |
2518 | SND_SOC_DAPM_POST_PMU), | 2677 | SND_SOC_DAPM_POST_PMU), |
2519 | SND_SOC_DAPM_SUPPLY("TOCLK", WM8962_ADDITIONAL_CONTROL_1, 0, 0, NULL, 0), | 2678 | SND_SOC_DAPM_SUPPLY("TOCLK", WM8962_ADDITIONAL_CONTROL_1, 0, 0, NULL, 0), |
2679 | SND_SOC_DAPM_SUPPLY_S("DSP2", 1, WM8962_DSP2_POWER_MANAGEMENT, | ||
2680 | WM8962_DSP2_ENA_SHIFT, 0, dsp2_event, | ||
2681 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | ||
2520 | 2682 | ||
2521 | SND_SOC_DAPM_MIXER("INPGAL", WM8962_LEFT_INPUT_PGA_CONTROL, 4, 0, | 2683 | SND_SOC_DAPM_MIXER("INPGAL", WM8962_LEFT_INPUT_PGA_CONTROL, 4, 0, |
2522 | inpgal, ARRAY_SIZE(inpgal)), | 2684 | inpgal, ARRAY_SIZE(inpgal)), |
@@ -2527,7 +2689,7 @@ SND_SOC_DAPM_MIXER("MIXINL", WM8962_PWR_MGMT_1, 5, 0, | |||
2527 | SND_SOC_DAPM_MIXER("MIXINR", WM8962_PWR_MGMT_1, 4, 0, | 2689 | SND_SOC_DAPM_MIXER("MIXINR", WM8962_PWR_MGMT_1, 4, 0, |
2528 | mixinr, ARRAY_SIZE(mixinr)), | 2690 | mixinr, ARRAY_SIZE(mixinr)), |
2529 | 2691 | ||
2530 | SND_SOC_DAPM_AIF_IN("DMIC", NULL, 0, WM8962_PWR_MGMT_1, 10, 0), | 2692 | SND_SOC_DAPM_AIF_IN("DMIC_ENA", NULL, 0, WM8962_PWR_MGMT_1, 10, 0), |
2531 | 2693 | ||
2532 | SND_SOC_DAPM_ADC("ADCL", "Capture", WM8962_PWR_MGMT_1, 3, 0), | 2694 | SND_SOC_DAPM_ADC("ADCL", "Capture", WM8962_PWR_MGMT_1, 3, 0), |
2533 | SND_SOC_DAPM_ADC("ADCR", "Capture", WM8962_PWR_MGMT_1, 2, 0), | 2695 | SND_SOC_DAPM_ADC("ADCR", "Capture", WM8962_PWR_MGMT_1, 2, 0), |
@@ -2606,17 +2768,19 @@ static const struct snd_soc_dapm_route wm8962_intercon[] = { | |||
2606 | 2768 | ||
2607 | { "MICBIAS", NULL, "SYSCLK" }, | 2769 | { "MICBIAS", NULL, "SYSCLK" }, |
2608 | 2770 | ||
2609 | { "DMIC", NULL, "DMICDAT" }, | 2771 | { "DMIC_ENA", NULL, "DMICDAT" }, |
2610 | 2772 | ||
2611 | { "ADCL", NULL, "SYSCLK" }, | 2773 | { "ADCL", NULL, "SYSCLK" }, |
2612 | { "ADCL", NULL, "TOCLK" }, | 2774 | { "ADCL", NULL, "TOCLK" }, |
2613 | { "ADCL", NULL, "MIXINL" }, | 2775 | { "ADCL", NULL, "MIXINL" }, |
2614 | { "ADCL", NULL, "DMIC" }, | 2776 | { "ADCL", NULL, "DMIC_ENA" }, |
2777 | { "ADCL", NULL, "DSP2" }, | ||
2615 | 2778 | ||
2616 | { "ADCR", NULL, "SYSCLK" }, | 2779 | { "ADCR", NULL, "SYSCLK" }, |
2617 | { "ADCR", NULL, "TOCLK" }, | 2780 | { "ADCR", NULL, "TOCLK" }, |
2618 | { "ADCR", NULL, "MIXINR" }, | 2781 | { "ADCR", NULL, "MIXINR" }, |
2619 | { "ADCR", NULL, "DMIC" }, | 2782 | { "ADCR", NULL, "DMIC_ENA" }, |
2783 | { "ADCR", NULL, "DSP2" }, | ||
2620 | 2784 | ||
2621 | { "STL", "Left", "ADCL" }, | 2785 | { "STL", "Left", "ADCL" }, |
2622 | { "STL", "Right", "ADCR" }, | 2786 | { "STL", "Right", "ADCR" }, |
@@ -2628,11 +2792,13 @@ static const struct snd_soc_dapm_route wm8962_intercon[] = { | |||
2628 | { "DACL", NULL, "TOCLK" }, | 2792 | { "DACL", NULL, "TOCLK" }, |
2629 | { "DACL", NULL, "Beep" }, | 2793 | { "DACL", NULL, "Beep" }, |
2630 | { "DACL", NULL, "STL" }, | 2794 | { "DACL", NULL, "STL" }, |
2795 | { "DACL", NULL, "DSP2" }, | ||
2631 | 2796 | ||
2632 | { "DACR", NULL, "SYSCLK" }, | 2797 | { "DACR", NULL, "SYSCLK" }, |
2633 | { "DACR", NULL, "TOCLK" }, | 2798 | { "DACR", NULL, "TOCLK" }, |
2634 | { "DACR", NULL, "Beep" }, | 2799 | { "DACR", NULL, "Beep" }, |
2635 | { "DACR", NULL, "STR" }, | 2800 | { "DACR", NULL, "STR" }, |
2801 | { "DACR", NULL, "DSP2" }, | ||
2636 | 2802 | ||
2637 | { "HPMIXL", "IN4L Switch", "IN4L" }, | 2803 | { "HPMIXL", "IN4L Switch", "IN4L" }, |
2638 | { "HPMIXL", "IN4R Switch", "IN4R" }, | 2804 | { "HPMIXL", "IN4R Switch", "IN4R" }, |
@@ -3058,9 +3224,9 @@ static int wm8962_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
3058 | int aif0 = 0; | 3224 | int aif0 = 0; |
3059 | 3225 | ||
3060 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | 3226 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
3061 | case SND_SOC_DAIFMT_DSP_A: | ||
3062 | aif0 |= WM8962_LRCLK_INV; | ||
3063 | case SND_SOC_DAIFMT_DSP_B: | 3227 | case SND_SOC_DAIFMT_DSP_B: |
3228 | aif0 |= WM8962_LRCLK_INV | 3; | ||
3229 | case SND_SOC_DAIFMT_DSP_A: | ||
3064 | aif0 |= 3; | 3230 | aif0 |= 3; |
3065 | 3231 | ||
3066 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | 3232 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { |
@@ -3403,12 +3569,16 @@ static irqreturn_t wm8962_irq(int irq, void *data) | |||
3403 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); | 3569 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); |
3404 | int mask; | 3570 | int mask; |
3405 | int active; | 3571 | int active; |
3572 | int reg; | ||
3406 | 3573 | ||
3407 | mask = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2_MASK); | 3574 | mask = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2_MASK); |
3408 | 3575 | ||
3409 | active = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2); | 3576 | active = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2); |
3410 | active &= ~mask; | 3577 | active &= ~mask; |
3411 | 3578 | ||
3579 | if (!active) | ||
3580 | return IRQ_NONE; | ||
3581 | |||
3412 | /* Acknowledge the interrupts */ | 3582 | /* Acknowledge the interrupts */ |
3413 | snd_soc_write(codec, WM8962_INTERRUPT_STATUS_2, active); | 3583 | snd_soc_write(codec, WM8962_INTERRUPT_STATUS_2, active); |
3414 | 3584 | ||
@@ -3420,9 +3590,21 @@ static irqreturn_t wm8962_irq(int irq, void *data) | |||
3420 | if (active & WM8962_FIFOS_ERR_EINT) | 3590 | if (active & WM8962_FIFOS_ERR_EINT) |
3421 | dev_err(codec->dev, "FIFO error\n"); | 3591 | dev_err(codec->dev, "FIFO error\n"); |
3422 | 3592 | ||
3423 | if (active & WM8962_TEMP_SHUT_EINT) | 3593 | if (active & WM8962_TEMP_SHUT_EINT) { |
3424 | dev_crit(codec->dev, "Thermal shutdown\n"); | 3594 | dev_crit(codec->dev, "Thermal shutdown\n"); |
3425 | 3595 | ||
3596 | reg = snd_soc_read(codec, WM8962_THERMAL_SHUTDOWN_STATUS); | ||
3597 | |||
3598 | if (reg & WM8962_TEMP_ERR_HP) | ||
3599 | dev_crit(codec->dev, "Headphone thermal error\n"); | ||
3600 | if (reg & WM8962_TEMP_WARN_HP) | ||
3601 | dev_crit(codec->dev, "Headphone thermal warning\n"); | ||
3602 | if (reg & WM8962_TEMP_ERR_SPK) | ||
3603 | dev_crit(codec->dev, "Speaker thermal error\n"); | ||
3604 | if (reg & WM8962_TEMP_WARN_SPK) | ||
3605 | dev_crit(codec->dev, "Speaker thermal warning\n"); | ||
3606 | } | ||
3607 | |||
3426 | if (active & (WM8962_MICSCD_EINT | WM8962_MICD_EINT)) { | 3608 | if (active & (WM8962_MICSCD_EINT | WM8962_MICD_EINT)) { |
3427 | dev_dbg(codec->dev, "Microphone event detected\n"); | 3609 | dev_dbg(codec->dev, "Microphone event detected\n"); |
3428 | 3610 | ||