aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm8994.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/wm8994.c')
-rw-r--r--sound/soc/codecs/wm8994.c75
1 files changed, 75 insertions, 0 deletions
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index e84a1177f350..a87046a96f2a 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -1677,6 +1677,26 @@ static struct {
1677 1677
1678static int wm8994_readable(unsigned int reg) 1678static int wm8994_readable(unsigned int reg)
1679{ 1679{
1680 switch (reg) {
1681 case WM8994_GPIO_1:
1682 case WM8994_GPIO_2:
1683 case WM8994_GPIO_3:
1684 case WM8994_GPIO_4:
1685 case WM8994_GPIO_5:
1686 case WM8994_GPIO_6:
1687 case WM8994_GPIO_7:
1688 case WM8994_GPIO_8:
1689 case WM8994_GPIO_9:
1690 case WM8994_GPIO_10:
1691 case WM8994_GPIO_11:
1692 case WM8994_INTERRUPT_STATUS_1:
1693 case WM8994_INTERRUPT_STATUS_2:
1694 case WM8994_INTERRUPT_RAW_STATUS_2:
1695 return 1;
1696 default:
1697 break;
1698 }
1699
1680 if (reg >= ARRAY_SIZE(access_masks)) 1700 if (reg >= ARRAY_SIZE(access_masks))
1681 return 0; 1701 return 0;
1682 return access_masks[reg].readable != 0; 1702 return access_masks[reg].readable != 0;
@@ -2341,6 +2361,20 @@ SOC_DAPM_SINGLE("AIF2 Switch", WM8994_AIF1_ADC1_RIGHT_MIXER_ROUTING,
2341 0, 1, 0), 2361 0, 1, 0),
2342}; 2362};
2343 2363
2364static const struct snd_kcontrol_new aif1adc2l_mix[] = {
2365SOC_DAPM_SINGLE("DMIC Switch", WM8994_AIF1_ADC2_LEFT_MIXER_ROUTING,
2366 1, 1, 0),
2367SOC_DAPM_SINGLE("AIF2 Switch", WM8994_AIF1_ADC2_LEFT_MIXER_ROUTING,
2368 0, 1, 0),
2369};
2370
2371static const struct snd_kcontrol_new aif1adc2r_mix[] = {
2372SOC_DAPM_SINGLE("DMIC Switch", WM8994_AIF1_ADC2_RIGHT_MIXER_ROUTING,
2373 1, 1, 0),
2374SOC_DAPM_SINGLE("AIF2 Switch", WM8994_AIF1_ADC2_RIGHT_MIXER_ROUTING,
2375 0, 1, 0),
2376};
2377
2344static const struct snd_kcontrol_new aif2dac2l_mix[] = { 2378static const struct snd_kcontrol_new aif2dac2l_mix[] = {
2345SOC_DAPM_SINGLE("Right Sidetone Switch", WM8994_DAC2_LEFT_MIXER_ROUTING, 2379SOC_DAPM_SINGLE("Right Sidetone Switch", WM8994_DAC2_LEFT_MIXER_ROUTING,
2346 5, 1, 0), 2380 5, 1, 0),
@@ -2472,6 +2506,7 @@ static const struct snd_kcontrol_new aif3adc_mux =
2472static const struct snd_soc_dapm_widget wm8994_dapm_widgets[] = { 2506static const struct snd_soc_dapm_widget wm8994_dapm_widgets[] = {
2473SND_SOC_DAPM_INPUT("DMIC1DAT"), 2507SND_SOC_DAPM_INPUT("DMIC1DAT"),
2474SND_SOC_DAPM_INPUT("DMIC2DAT"), 2508SND_SOC_DAPM_INPUT("DMIC2DAT"),
2509SND_SOC_DAPM_INPUT("Clock"),
2475 2510
2476SND_SOC_DAPM_SUPPLY("CLK_SYS", SND_SOC_NOPM, 0, 0, clk_sys_event, 2511SND_SOC_DAPM_SUPPLY("CLK_SYS", SND_SOC_NOPM, 0, 0, clk_sys_event,
2477 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), 2512 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
@@ -2506,6 +2541,11 @@ SND_SOC_DAPM_MIXER("AIF1ADC1L Mixer", SND_SOC_NOPM, 0, 0,
2506SND_SOC_DAPM_MIXER("AIF1ADC1R Mixer", SND_SOC_NOPM, 0, 0, 2541SND_SOC_DAPM_MIXER("AIF1ADC1R Mixer", SND_SOC_NOPM, 0, 0,
2507 aif1adc1r_mix, ARRAY_SIZE(aif1adc1r_mix)), 2542 aif1adc1r_mix, ARRAY_SIZE(aif1adc1r_mix)),
2508 2543
2544SND_SOC_DAPM_MIXER("AIF1ADC2L Mixer", SND_SOC_NOPM, 0, 0,
2545 aif1adc2l_mix, ARRAY_SIZE(aif1adc2l_mix)),
2546SND_SOC_DAPM_MIXER("AIF1ADC2R Mixer", SND_SOC_NOPM, 0, 0,
2547 aif1adc2r_mix, ARRAY_SIZE(aif1adc2r_mix)),
2548
2509SND_SOC_DAPM_MIXER("AIF2DAC2L Mixer", SND_SOC_NOPM, 0, 0, 2549SND_SOC_DAPM_MIXER("AIF2DAC2L Mixer", SND_SOC_NOPM, 0, 0,
2510 aif2dac2l_mix, ARRAY_SIZE(aif2dac2l_mix)), 2550 aif2dac2l_mix, ARRAY_SIZE(aif2dac2l_mix)),
2511SND_SOC_DAPM_MIXER("AIF2DAC2R Mixer", SND_SOC_NOPM, 0, 0, 2551SND_SOC_DAPM_MIXER("AIF2DAC2R Mixer", SND_SOC_NOPM, 0, 0,
@@ -2668,6 +2708,14 @@ static const struct snd_soc_dapm_route intercon[] = {
2668 { "AIF1ADC1R Mixer", "ADC/DMIC Switch", "ADCR Mux" }, 2708 { "AIF1ADC1R Mixer", "ADC/DMIC Switch", "ADCR Mux" },
2669 { "AIF1ADC1R Mixer", "AIF2 Switch", "AIF2DACR" }, 2709 { "AIF1ADC1R Mixer", "AIF2 Switch", "AIF2DACR" },
2670 2710
2711 { "AIF1ADC2L", NULL, "AIF1ADC2L Mixer" },
2712 { "AIF1ADC2L Mixer", "DMIC Switch", "DMIC2L" },
2713 { "AIF1ADC2L Mixer", "AIF2 Switch", "AIF2DACL" },
2714
2715 { "AIF1ADC2R", NULL, "AIF1ADC2R Mixer" },
2716 { "AIF1ADC2R Mixer", "DMIC Switch", "DMIC2R" },
2717 { "AIF1ADC2R Mixer", "AIF2 Switch", "AIF2DACR" },
2718
2671 /* Pin level routing for AIF3 */ 2719 /* Pin level routing for AIF3 */
2672 { "AIF1DAC1L", NULL, "AIF1DAC Mux" }, 2720 { "AIF1DAC1L", NULL, "AIF1DAC Mux" },
2673 { "AIF1DAC1R", NULL, "AIF1DAC Mux" }, 2721 { "AIF1DAC1R", NULL, "AIF1DAC Mux" },
@@ -2946,11 +2994,14 @@ static int wm8994_set_fll(struct snd_soc_dai *dai, int id, int src,
2946 return 0; 2994 return 0;
2947} 2995}
2948 2996
2997static int opclk_divs[] = { 10, 20, 30, 40, 55, 60, 80, 120, 160 };
2998
2949static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai, 2999static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai,
2950 int clk_id, unsigned int freq, int dir) 3000 int clk_id, unsigned int freq, int dir)
2951{ 3001{
2952 struct snd_soc_codec *codec = dai->codec; 3002 struct snd_soc_codec *codec = dai->codec;
2953 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); 3003 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
3004 int i;
2954 3005
2955 switch (dai->id) { 3006 switch (dai->id) {
2956 case 1: 3007 case 1:
@@ -2988,6 +3039,25 @@ static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai,
2988 dev_dbg(dai->dev, "AIF%d using FLL2\n", dai->id); 3039 dev_dbg(dai->dev, "AIF%d using FLL2\n", dai->id);
2989 break; 3040 break;
2990 3041
3042 case WM8994_SYSCLK_OPCLK:
3043 /* Special case - a division (times 10) is given and
3044 * no effect on main clocking.
3045 */
3046 if (freq) {
3047 for (i = 0; i < ARRAY_SIZE(opclk_divs); i++)
3048 if (opclk_divs[i] == freq)
3049 break;
3050 if (i == ARRAY_SIZE(opclk_divs))
3051 return -EINVAL;
3052 snd_soc_update_bits(codec, WM8994_CLOCKING_2,
3053 WM8994_OPCLK_DIV_MASK, i);
3054 snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_2,
3055 WM8994_OPCLK_ENA, WM8994_OPCLK_ENA);
3056 } else {
3057 snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_2,
3058 WM8994_OPCLK_ENA, 0);
3059 }
3060
2991 default: 3061 default:
2992 return -EINVAL; 3062 return -EINVAL;
2993 } 3063 }
@@ -4004,6 +4074,11 @@ static int wm8994_codec_probe(struct platform_device *pdev)
4004 1 << WM8994_AIF2DAC_3D_GAIN_SHIFT, 4074 1 << WM8994_AIF2DAC_3D_GAIN_SHIFT,
4005 1 << WM8994_AIF2DAC_3D_GAIN_SHIFT); 4075 1 << WM8994_AIF2DAC_3D_GAIN_SHIFT);
4006 4076
4077 /* Unconditionally enable AIF1 ADC TDM mode; it only affects
4078 * behaviour on idle TDM clock cycles. */
4079 snd_soc_update_bits(codec, WM8994_AIF1_CONTROL_1,
4080 WM8994_AIF1ADC_TDM, WM8994_AIF1ADC_TDM);
4081
4007 wm8994_update_class_w(codec); 4082 wm8994_update_class_w(codec);
4008 4083
4009 ret = snd_soc_register_codec(codec); 4084 ret = snd_soc_register_codec(codec);