diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2011-05-24 05:35:53 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2011-10-04 06:59:46 -0400 |
commit | 81204c84ca46604a04ab3d43ccfa1e464e6b1303 (patch) | |
tree | 408e2360161557a17b81f2405a09c80966bf8e41 /sound/soc/codecs/wm8994.c | |
parent | b1f43bf3a52b085b786adf0b719712df574955f9 (diff) |
ASoC: Add WM1811 support
The WM1811 is mostly register compatible with the WM8994 and WM8958,
providing a high performance audio hub CODEC in a small form factor
suitable for ultra compact system designs.
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/codecs/wm8994.c')
-rw-r--r-- | sound/soc/codecs/wm8994.c | 83 |
1 files changed, 78 insertions, 5 deletions
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index e5372675123d..5e8d66d085f5 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c | |||
@@ -283,6 +283,7 @@ static const DECLARE_TLV_DB_SCALE(st_tlv, -3600, 300, 0); | |||
283 | static const DECLARE_TLV_DB_SCALE(wm8994_3d_tlv, -1600, 183, 0); | 283 | static const DECLARE_TLV_DB_SCALE(wm8994_3d_tlv, -1600, 183, 0); |
284 | static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); | 284 | static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); |
285 | static const DECLARE_TLV_DB_SCALE(ng_tlv, -10200, 600, 0); | 285 | static const DECLARE_TLV_DB_SCALE(ng_tlv, -10200, 600, 0); |
286 | static const DECLARE_TLV_DB_SCALE(mixin_boost_tlv, 0, 900, 0); | ||
286 | 287 | ||
287 | #define WM8994_DRC_SWITCH(xname, reg, shift) \ | 288 | #define WM8994_DRC_SWITCH(xname, reg, shift) \ |
288 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | 289 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ |
@@ -703,6 +704,13 @@ SOC_SINGLE_TLV("AIF2DAC Noise Gate Threshold Volume", | |||
703 | 7, 1, ng_tlv), | 704 | 7, 1, ng_tlv), |
704 | }; | 705 | }; |
705 | 706 | ||
707 | static const struct snd_kcontrol_new wm1811_snd_controls[] = { | ||
708 | SOC_SINGLE_TLV("MIXINL IN1LP Boost Volume", WM8994_INPUT_MIXER_1, 7, 1, 0, | ||
709 | mixin_boost_tlv), | ||
710 | SOC_SINGLE_TLV("MIXINL IN1RP Boost Volume", WM8994_INPUT_MIXER_1, 8, 1, 0, | ||
711 | mixin_boost_tlv), | ||
712 | }; | ||
713 | |||
706 | static int clk_sys_event(struct snd_soc_dapm_widget *w, | 714 | static int clk_sys_event(struct snd_soc_dapm_widget *w, |
707 | struct snd_kcontrol *kcontrol, int event) | 715 | struct snd_kcontrol *kcontrol, int event) |
708 | { | 716 | { |
@@ -2053,6 +2061,15 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec, | |||
2053 | WM8958_CP_DISCH); | 2061 | WM8958_CP_DISCH); |
2054 | } | 2062 | } |
2055 | break; | 2063 | break; |
2064 | |||
2065 | case WM1811: | ||
2066 | if (wm8994->revision < 2) { | ||
2067 | snd_soc_write(codec, 0x102, 0x3); | ||
2068 | snd_soc_write(codec, 0x5d, 0x7e); | ||
2069 | snd_soc_write(codec, 0x5e, 0x0); | ||
2070 | snd_soc_write(codec, 0x102, 0x0); | ||
2071 | } | ||
2072 | break; | ||
2056 | } | 2073 | } |
2057 | 2074 | ||
2058 | /* Discharge LINEOUT1 & 2 */ | 2075 | /* Discharge LINEOUT1 & 2 */ |
@@ -2168,10 +2185,18 @@ static int wm8994_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
2168 | 2185 | ||
2169 | /* The AIF2 format configuration needs to be mirrored to AIF3 | 2186 | /* The AIF2 format configuration needs to be mirrored to AIF3 |
2170 | * on WM8958 if it's in use so just do it all the time. */ | 2187 | * on WM8958 if it's in use so just do it all the time. */ |
2171 | if (control->type == WM8958 && dai->id == 2) | 2188 | switch (control->type) { |
2172 | snd_soc_update_bits(codec, WM8958_AIF3_CONTROL_1, | 2189 | case WM1811: |
2173 | WM8994_AIF1_LRCLK_INV | | 2190 | case WM8958: |
2174 | WM8958_AIF3_FMT_MASK, aif1); | 2191 | if (dai->id == 2) |
2192 | snd_soc_update_bits(codec, WM8958_AIF3_CONTROL_1, | ||
2193 | WM8994_AIF1_LRCLK_INV | | ||
2194 | WM8958_AIF3_FMT_MASK, aif1); | ||
2195 | break; | ||
2196 | |||
2197 | default: | ||
2198 | break; | ||
2199 | } | ||
2175 | 2200 | ||
2176 | snd_soc_update_bits(codec, aif1_reg, | 2201 | snd_soc_update_bits(codec, aif1_reg, |
2177 | WM8994_AIF1_BCLK_INV | WM8994_AIF1_LRCLK_INV | | 2202 | WM8994_AIF1_BCLK_INV | WM8994_AIF1_LRCLK_INV | |
@@ -2258,6 +2283,7 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream, | |||
2258 | break; | 2283 | break; |
2259 | case 3: | 2284 | case 3: |
2260 | switch (control->type) { | 2285 | switch (control->type) { |
2286 | case WM1811: | ||
2261 | case WM8958: | 2287 | case WM8958: |
2262 | aif1_reg = WM8958_AIF3_CONTROL_1; | 2288 | aif1_reg = WM8958_AIF3_CONTROL_1; |
2263 | break; | 2289 | break; |
@@ -2384,6 +2410,7 @@ static int wm8994_aif3_hw_params(struct snd_pcm_substream *substream, | |||
2384 | switch (dai->id) { | 2410 | switch (dai->id) { |
2385 | case 3: | 2411 | case 3: |
2386 | switch (control->type) { | 2412 | switch (control->type) { |
2413 | case WM1811: | ||
2387 | case WM8958: | 2414 | case WM8958: |
2388 | aif1_reg = WM8958_AIF3_CONTROL_1; | 2415 | aif1_reg = WM8958_AIF3_CONTROL_1; |
2389 | break; | 2416 | break; |
@@ -2614,6 +2641,7 @@ static int wm8994_suspend(struct snd_soc_codec *codec, pm_message_t state) | |||
2614 | case WM8994: | 2641 | case WM8994: |
2615 | snd_soc_update_bits(codec, WM8994_MICBIAS, WM8994_MICD_ENA, 0); | 2642 | snd_soc_update_bits(codec, WM8994_MICBIAS, WM8994_MICD_ENA, 0); |
2616 | break; | 2643 | break; |
2644 | case WM1811: | ||
2617 | case WM8958: | 2645 | case WM8958: |
2618 | snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, | 2646 | snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, |
2619 | WM8958_MICD_ENA, 0); | 2647 | WM8958_MICD_ENA, 0); |
@@ -2682,6 +2710,7 @@ static int wm8994_resume(struct snd_soc_codec *codec) | |||
2682 | snd_soc_update_bits(codec, WM8994_MICBIAS, | 2710 | snd_soc_update_bits(codec, WM8994_MICBIAS, |
2683 | WM8994_MICD_ENA, WM8994_MICD_ENA); | 2711 | WM8994_MICD_ENA, WM8994_MICD_ENA); |
2684 | break; | 2712 | break; |
2713 | case WM1811: | ||
2685 | case WM8958: | 2714 | case WM8958: |
2686 | if (wm8994->jack_cb) | 2715 | if (wm8994->jack_cb) |
2687 | snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, | 2716 | snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, |
@@ -2980,8 +3009,13 @@ int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, | |||
2980 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 3009 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
2981 | struct wm8994 *control = codec->control_data; | 3010 | struct wm8994 *control = codec->control_data; |
2982 | 3011 | ||
2983 | if (control->type != WM8958) | 3012 | switch (control->type) { |
3013 | case WM1811: | ||
3014 | case WM8958: | ||
3015 | break; | ||
3016 | default: | ||
2984 | return -EINVAL; | 3017 | return -EINVAL; |
3018 | } | ||
2985 | 3019 | ||
2986 | if (jack) { | 3020 | if (jack) { |
2987 | if (!cb) { | 3021 | if (!cb) { |
@@ -3135,6 +3169,24 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
3135 | wm8994->hubs.dcs_readback_mode = 1; | 3169 | wm8994->hubs.dcs_readback_mode = 1; |
3136 | break; | 3170 | break; |
3137 | 3171 | ||
3172 | case WM1811: | ||
3173 | wm8994->hubs.dcs_readback_mode = 2; | ||
3174 | wm8994->hubs.no_series_update = 1; | ||
3175 | |||
3176 | switch (wm8994->revision) { | ||
3177 | case 0: | ||
3178 | case 1: | ||
3179 | wm8994->hubs.dcs_codes_l = -7; | ||
3180 | wm8994->hubs.dcs_codes_r = -4; | ||
3181 | break; | ||
3182 | default: | ||
3183 | break; | ||
3184 | } | ||
3185 | |||
3186 | snd_soc_update_bits(codec, WM8994_ANALOGUE_HP_1, | ||
3187 | WM1811_HPOUT1_ATTN, WM1811_HPOUT1_ATTN); | ||
3188 | break; | ||
3189 | |||
3138 | default: | 3190 | default: |
3139 | break; | 3191 | break; |
3140 | } | 3192 | } |
@@ -3195,6 +3247,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
3195 | break; | 3247 | break; |
3196 | 3248 | ||
3197 | case WM8958: | 3249 | case WM8958: |
3250 | case WM1811: | ||
3198 | if (wm8994->micdet_irq) { | 3251 | if (wm8994->micdet_irq) { |
3199 | ret = request_threaded_irq(wm8994->micdet_irq, NULL, | 3252 | ret = request_threaded_irq(wm8994->micdet_irq, NULL, |
3200 | wm8958_mic_irq, | 3253 | wm8958_mic_irq, |
@@ -3357,6 +3410,19 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
3357 | ARRAY_SIZE(wm8994_dac_widgets)); | 3410 | ARRAY_SIZE(wm8994_dac_widgets)); |
3358 | } | 3411 | } |
3359 | break; | 3412 | break; |
3413 | |||
3414 | case WM1811: | ||
3415 | snd_soc_add_controls(codec, wm8958_snd_controls, | ||
3416 | ARRAY_SIZE(wm8958_snd_controls)); | ||
3417 | snd_soc_dapm_new_controls(dapm, wm8958_dapm_widgets, | ||
3418 | ARRAY_SIZE(wm8958_dapm_widgets)); | ||
3419 | snd_soc_dapm_new_controls(dapm, wm8994_lateclk_widgets, | ||
3420 | ARRAY_SIZE(wm8994_lateclk_widgets)); | ||
3421 | snd_soc_dapm_new_controls(dapm, wm8994_adc_widgets, | ||
3422 | ARRAY_SIZE(wm8994_adc_widgets)); | ||
3423 | snd_soc_dapm_new_controls(dapm, wm8994_dac_widgets, | ||
3424 | ARRAY_SIZE(wm8994_dac_widgets)); | ||
3425 | break; | ||
3360 | } | 3426 | } |
3361 | 3427 | ||
3362 | 3428 | ||
@@ -3393,6 +3459,12 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
3393 | 3459 | ||
3394 | wm8958_dsp2_init(codec); | 3460 | wm8958_dsp2_init(codec); |
3395 | break; | 3461 | break; |
3462 | case WM1811: | ||
3463 | snd_soc_dapm_add_routes(dapm, wm8994_lateclk_intercon, | ||
3464 | ARRAY_SIZE(wm8994_lateclk_intercon)); | ||
3465 | snd_soc_dapm_add_routes(dapm, wm8958_intercon, | ||
3466 | ARRAY_SIZE(wm8958_intercon)); | ||
3467 | break; | ||
3396 | } | 3468 | } |
3397 | 3469 | ||
3398 | return 0; | 3470 | return 0; |
@@ -3448,6 +3520,7 @@ static int wm8994_codec_remove(struct snd_soc_codec *codec) | |||
3448 | wm8994); | 3520 | wm8994); |
3449 | break; | 3521 | break; |
3450 | 3522 | ||
3523 | case WM1811: | ||
3451 | case WM8958: | 3524 | case WM8958: |
3452 | if (wm8994->micdet_irq) | 3525 | if (wm8994->micdet_irq) |
3453 | free_irq(wm8994->micdet_irq, wm8994); | 3526 | free_irq(wm8994->micdet_irq, wm8994); |