diff options
-rw-r--r-- | sound/soc/codecs/wm8994.c | 110 |
1 files changed, 76 insertions, 34 deletions
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 283399468b0c..8232d5e73194 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c | |||
@@ -1535,6 +1535,7 @@ static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai, | |||
1535 | static int wm8994_set_bias_level(struct snd_soc_codec *codec, | 1535 | static int wm8994_set_bias_level(struct snd_soc_codec *codec, |
1536 | enum snd_soc_bias_level level) | 1536 | enum snd_soc_bias_level level) |
1537 | { | 1537 | { |
1538 | struct wm8994 *control = codec->control_data; | ||
1538 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 1539 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
1539 | 1540 | ||
1540 | switch (level) { | 1541 | switch (level) { |
@@ -1551,7 +1552,7 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec, | |||
1551 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 1552 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { |
1552 | /* Tweak DC servo and DSP configuration for | 1553 | /* Tweak DC servo and DSP configuration for |
1553 | * improved performance. */ | 1554 | * improved performance. */ |
1554 | if (wm8994->revision < 4) { | 1555 | if (control->type == WM8994 && wm8994->revision < 4) { |
1555 | /* Tweak DC servo and DSP configuration for | 1556 | /* Tweak DC servo and DSP configuration for |
1556 | * improved performance. */ | 1557 | * improved performance. */ |
1557 | snd_soc_write(codec, 0x102, 0x3); | 1558 | snd_soc_write(codec, 0x102, 0x3); |
@@ -2264,8 +2265,12 @@ int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, | |||
2264 | { | 2265 | { |
2265 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 2266 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
2266 | struct wm8994_micdet *micdet; | 2267 | struct wm8994_micdet *micdet; |
2268 | struct wm8994 *control = codec->control_data; | ||
2267 | int reg; | 2269 | int reg; |
2268 | 2270 | ||
2271 | if (control->type != WM8994) | ||
2272 | return -EINVAL; | ||
2273 | |||
2269 | switch (micbias) { | 2274 | switch (micbias) { |
2270 | case 1: | 2275 | case 1: |
2271 | micdet = &wm8994->micdet[0]; | 2276 | micdet = &wm8994->micdet[0]; |
@@ -2334,11 +2339,13 @@ static irqreturn_t wm8994_mic_irq(int irq, void *data) | |||
2334 | 2339 | ||
2335 | static int wm8994_codec_probe(struct snd_soc_codec *codec) | 2340 | static int wm8994_codec_probe(struct snd_soc_codec *codec) |
2336 | { | 2341 | { |
2342 | struct wm8994 *control; | ||
2337 | struct wm8994_priv *wm8994; | 2343 | struct wm8994_priv *wm8994; |
2338 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 2344 | struct snd_soc_dapm_context *dapm = &codec->dapm; |
2339 | int ret, i; | 2345 | int ret, i; |
2340 | 2346 | ||
2341 | codec->control_data = dev_get_drvdata(codec->dev->parent); | 2347 | codec->control_data = dev_get_drvdata(codec->dev->parent); |
2348 | control = codec->control_data; | ||
2342 | 2349 | ||
2343 | wm8994 = kzalloc(sizeof(struct wm8994_priv), GFP_KERNEL); | 2350 | wm8994 = kzalloc(sizeof(struct wm8994_priv), GFP_KERNEL); |
2344 | if (wm8994 == NULL) | 2351 | if (wm8994 == NULL) |
@@ -2369,41 +2376,67 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
2369 | 2376 | ||
2370 | /* Set revision-specific configuration */ | 2377 | /* Set revision-specific configuration */ |
2371 | wm8994->revision = snd_soc_read(codec, WM8994_CHIP_REVISION); | 2378 | wm8994->revision = snd_soc_read(codec, WM8994_CHIP_REVISION); |
2372 | switch (wm8994->revision) { | 2379 | switch (control->type) { |
2373 | case 2: | 2380 | case WM8994: |
2374 | case 3: | 2381 | switch (wm8994->revision) { |
2375 | wm8994->hubs.dcs_codes = -5; | 2382 | case 2: |
2376 | wm8994->hubs.hp_startup_mode = 1; | 2383 | case 3: |
2384 | wm8994->hubs.dcs_codes = -5; | ||
2385 | wm8994->hubs.hp_startup_mode = 1; | ||
2386 | wm8994->hubs.dcs_readback_mode = 1; | ||
2387 | break; | ||
2388 | default: | ||
2389 | wm8994->hubs.dcs_readback_mode = 1; | ||
2390 | break; | ||
2391 | } | ||
2392 | |||
2393 | case WM8958: | ||
2377 | wm8994->hubs.dcs_readback_mode = 1; | 2394 | wm8994->hubs.dcs_readback_mode = 1; |
2378 | break; | 2395 | break; |
2396 | |||
2379 | default: | 2397 | default: |
2380 | wm8994->hubs.dcs_readback_mode = 1; | ||
2381 | break; | 2398 | break; |
2382 | } | 2399 | } |
2383 | 2400 | ||
2384 | ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC1_DET, | 2401 | switch (control->type) { |
2385 | wm8994_mic_irq, "Mic 1 detect", wm8994); | 2402 | case WM8994: |
2386 | if (ret != 0) | 2403 | ret = wm8994_request_irq(codec->control_data, |
2387 | dev_warn(codec->dev, | 2404 | WM8994_IRQ_MIC1_DET, |
2388 | "Failed to request Mic1 detect IRQ: %d\n", ret); | 2405 | wm8994_mic_irq, "Mic 1 detect", |
2389 | 2406 | wm8994); | |
2390 | ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, | 2407 | if (ret != 0) |
2391 | wm8994_mic_irq, "Mic 1 short", wm8994); | 2408 | dev_warn(codec->dev, |
2392 | if (ret != 0) | 2409 | "Failed to request Mic1 detect IRQ: %d\n", |
2393 | dev_warn(codec->dev, | 2410 | ret); |
2394 | "Failed to request Mic1 short IRQ: %d\n", ret); | 2411 | |
2395 | 2412 | ret = wm8994_request_irq(codec->control_data, | |
2396 | ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC2_DET, | 2413 | WM8994_IRQ_MIC1_SHRT, |
2397 | wm8994_mic_irq, "Mic 2 detect", wm8994); | 2414 | wm8994_mic_irq, "Mic 1 short", |
2398 | if (ret != 0) | 2415 | wm8994); |
2399 | dev_warn(codec->dev, | 2416 | if (ret != 0) |
2400 | "Failed to request Mic2 detect IRQ: %d\n", ret); | 2417 | dev_warn(codec->dev, |
2401 | 2418 | "Failed to request Mic1 short IRQ: %d\n", | |
2402 | ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, | 2419 | ret); |
2403 | wm8994_mic_irq, "Mic 2 short", wm8994); | 2420 | |
2404 | if (ret != 0) | 2421 | ret = wm8994_request_irq(codec->control_data, |
2405 | dev_warn(codec->dev, | 2422 | WM8994_IRQ_MIC2_DET, |
2406 | "Failed to request Mic2 short IRQ: %d\n", ret); | 2423 | wm8994_mic_irq, "Mic 2 detect", |
2424 | wm8994); | ||
2425 | if (ret != 0) | ||
2426 | dev_warn(codec->dev, | ||
2427 | "Failed to request Mic2 detect IRQ: %d\n", | ||
2428 | ret); | ||
2429 | |||
2430 | ret = wm8994_request_irq(codec->control_data, | ||
2431 | WM8994_IRQ_MIC2_SHRT, | ||
2432 | wm8994_mic_irq, "Mic 2 short", | ||
2433 | wm8994); | ||
2434 | if (ret != 0) | ||
2435 | dev_warn(codec->dev, | ||
2436 | "Failed to request Mic2 short IRQ: %d\n", | ||
2437 | ret); | ||
2438 | break; | ||
2439 | } | ||
2407 | 2440 | ||
2408 | /* Remember if AIFnLRCLK is configured as a GPIO. This should be | 2441 | /* Remember if AIFnLRCLK is configured as a GPIO. This should be |
2409 | * configured on init - if a system wants to do this dynamically | 2442 | * configured on init - if a system wants to do this dynamically |
@@ -2496,13 +2529,22 @@ err: | |||
2496 | static int wm8994_codec_remove(struct snd_soc_codec *codec) | 2529 | static int wm8994_codec_remove(struct snd_soc_codec *codec) |
2497 | { | 2530 | { |
2498 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 2531 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
2532 | struct wm8994 *control = codec->control_data; | ||
2499 | 2533 | ||
2500 | wm8994_set_bias_level(codec, SND_SOC_BIAS_OFF); | 2534 | wm8994_set_bias_level(codec, SND_SOC_BIAS_OFF); |
2501 | 2535 | ||
2502 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, wm8994); | 2536 | switch (control->type) { |
2503 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET, wm8994); | 2537 | case WM8994: |
2504 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, wm8994); | 2538 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, |
2505 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_DET, wm8994); | 2539 | wm8994); |
2540 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET, | ||
2541 | wm8994); | ||
2542 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, | ||
2543 | wm8994); | ||
2544 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_DET, | ||
2545 | wm8994); | ||
2546 | break; | ||
2547 | } | ||
2506 | kfree(wm8994->retune_mobile_texts); | 2548 | kfree(wm8994->retune_mobile_texts); |
2507 | kfree(wm8994->drc_texts); | 2549 | kfree(wm8994->drc_texts); |
2508 | kfree(wm8994); | 2550 | kfree(wm8994); |