diff options
Diffstat (limited to 'sound/soc/codecs/wm8994.c')
-rw-r--r-- | sound/soc/codecs/wm8994.c | 201 |
1 files changed, 111 insertions, 90 deletions
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 302f69a8ac22..3b269fa226bd 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c | |||
@@ -91,8 +91,6 @@ static int wm8994_retune_mobile_base[] = { | |||
91 | WM8994_AIF2_EQ_GAINS_1, | 91 | WM8994_AIF2_EQ_GAINS_1, |
92 | }; | 92 | }; |
93 | 93 | ||
94 | static void wm8958_default_micdet(u16 status, void *data); | ||
95 | |||
96 | static const struct wm8958_micd_rate micdet_rates[] = { | 94 | static const struct wm8958_micd_rate micdet_rates[] = { |
97 | { 32768, true, 1, 4 }, | 95 | { 32768, true, 1, 4 }, |
98 | { 32768, false, 1, 1 }, | 96 | { 32768, false, 1, 1 }, |
@@ -116,9 +114,6 @@ static void wm8958_micd_set_rate(struct snd_soc_codec *codec) | |||
116 | const struct wm8958_micd_rate *rates; | 114 | const struct wm8958_micd_rate *rates; |
117 | int num_rates; | 115 | int num_rates; |
118 | 116 | ||
119 | if (wm8994->jack_cb != wm8958_default_micdet) | ||
120 | return; | ||
121 | |||
122 | idle = !wm8994->jack_mic; | 117 | idle = !wm8994->jack_mic; |
123 | 118 | ||
124 | sysclk = snd_soc_read(codec, WM8994_CLOCKING_1); | 119 | sysclk = snd_soc_read(codec, WM8994_CLOCKING_1); |
@@ -740,7 +735,7 @@ static void wm1811_jackdet_set_mode(struct snd_soc_codec *codec, u16 mode) | |||
740 | { | 735 | { |
741 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 736 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
742 | 737 | ||
743 | if (!wm8994->jackdet || !wm8994->jack_cb) | 738 | if (!wm8994->jackdet || !wm8994->micdet[0].jack) |
744 | return; | 739 | return; |
745 | 740 | ||
746 | if (wm8994->active_refcount) | 741 | if (wm8994->active_refcount) |
@@ -3405,38 +3400,80 @@ static irqreturn_t wm8994_mic_irq(int irq, void *data) | |||
3405 | return IRQ_HANDLED; | 3400 | return IRQ_HANDLED; |
3406 | } | 3401 | } |
3407 | 3402 | ||
3408 | /* Default microphone detection handler for WM8958 - the user can | 3403 | static void wm1811_micd_stop(struct snd_soc_codec *codec) |
3409 | * override this if they wish. | 3404 | { |
3410 | */ | 3405 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
3411 | static void wm8958_default_micdet(u16 status, void *data) | 3406 | |
3407 | if (!wm8994->jackdet) | ||
3408 | return; | ||
3409 | |||
3410 | mutex_lock(&wm8994->accdet_lock); | ||
3411 | |||
3412 | snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, WM8958_MICD_ENA, 0); | ||
3413 | |||
3414 | wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_JACK); | ||
3415 | |||
3416 | mutex_unlock(&wm8994->accdet_lock); | ||
3417 | |||
3418 | if (wm8994->wm8994->pdata.jd_ext_cap) | ||
3419 | snd_soc_dapm_disable_pin(&codec->dapm, | ||
3420 | "MICBIAS2"); | ||
3421 | } | ||
3422 | |||
3423 | static void wm8958_button_det(struct snd_soc_codec *codec, u16 status) | ||
3412 | { | 3424 | { |
3413 | struct snd_soc_codec *codec = data; | ||
3414 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 3425 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
3415 | int report; | 3426 | int report; |
3416 | 3427 | ||
3417 | dev_dbg(codec->dev, "MICDET %x\n", status); | 3428 | report = 0; |
3429 | if (status & 0x4) | ||
3430 | report |= SND_JACK_BTN_0; | ||
3431 | |||
3432 | if (status & 0x8) | ||
3433 | report |= SND_JACK_BTN_1; | ||
3434 | |||
3435 | if (status & 0x10) | ||
3436 | report |= SND_JACK_BTN_2; | ||
3437 | |||
3438 | if (status & 0x20) | ||
3439 | report |= SND_JACK_BTN_3; | ||
3440 | |||
3441 | if (status & 0x40) | ||
3442 | report |= SND_JACK_BTN_4; | ||
3443 | |||
3444 | if (status & 0x80) | ||
3445 | report |= SND_JACK_BTN_5; | ||
3446 | |||
3447 | snd_soc_jack_report(wm8994->micdet[0].jack, report, | ||
3448 | wm8994->btn_mask); | ||
3449 | } | ||
3450 | |||
3451 | static void wm8958_mic_id(void *data, u16 status) | ||
3452 | { | ||
3453 | struct snd_soc_codec *codec = data; | ||
3454 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | ||
3418 | 3455 | ||
3419 | /* Either nothing present or just starting detection */ | 3456 | /* Either nothing present or just starting detection */ |
3420 | if (!(status & WM8958_MICD_STS)) { | 3457 | if (!(status & WM8958_MICD_STS)) { |
3421 | if (!wm8994->jackdet) { | 3458 | /* If nothing present then clear our statuses */ |
3422 | /* If nothing present then clear our statuses */ | 3459 | dev_dbg(codec->dev, "Detected open circuit\n"); |
3423 | dev_dbg(codec->dev, "Detected open circuit\n"); | 3460 | wm8994->jack_mic = false; |
3424 | wm8994->jack_mic = false; | 3461 | wm8994->mic_detecting = true; |
3425 | wm8994->mic_detecting = true; | ||
3426 | 3462 | ||
3427 | wm8958_micd_set_rate(codec); | 3463 | wm1811_micd_stop(codec); |
3428 | 3464 | ||
3429 | snd_soc_jack_report(wm8994->micdet[0].jack, 0, | 3465 | wm8958_micd_set_rate(codec); |
3430 | wm8994->btn_mask | | 3466 | |
3431 | SND_JACK_HEADSET); | 3467 | snd_soc_jack_report(wm8994->micdet[0].jack, 0, |
3432 | } | 3468 | wm8994->btn_mask | |
3469 | SND_JACK_HEADSET); | ||
3433 | return; | 3470 | return; |
3434 | } | 3471 | } |
3435 | 3472 | ||
3436 | /* If the measurement is showing a high impedence we've got a | 3473 | /* If the measurement is showing a high impedence we've got a |
3437 | * microphone. | 3474 | * microphone. |
3438 | */ | 3475 | */ |
3439 | if (wm8994->mic_detecting && (status & 0x600)) { | 3476 | if (status & 0x600) { |
3440 | dev_dbg(codec->dev, "Detected microphone\n"); | 3477 | dev_dbg(codec->dev, "Detected microphone\n"); |
3441 | 3478 | ||
3442 | wm8994->mic_detecting = false; | 3479 | wm8994->mic_detecting = false; |
@@ -3449,57 +3486,18 @@ static void wm8958_default_micdet(u16 status, void *data) | |||
3449 | } | 3486 | } |
3450 | 3487 | ||
3451 | 3488 | ||
3452 | if (wm8994->mic_detecting && status & 0xfc) { | 3489 | if (status & 0xfc) { |
3453 | dev_dbg(codec->dev, "Detected headphone\n"); | 3490 | dev_dbg(codec->dev, "Detected headphone\n"); |
3454 | wm8994->mic_detecting = false; | 3491 | wm8994->mic_detecting = false; |
3455 | 3492 | ||
3456 | wm8958_micd_set_rate(codec); | 3493 | wm8958_micd_set_rate(codec); |
3457 | 3494 | ||
3458 | /* If we have jackdet that will detect removal */ | 3495 | /* If we have jackdet that will detect removal */ |
3459 | if (wm8994->jackdet) { | 3496 | wm1811_micd_stop(codec); |
3460 | mutex_lock(&wm8994->accdet_lock); | ||
3461 | |||
3462 | snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, | ||
3463 | WM8958_MICD_ENA, 0); | ||
3464 | |||
3465 | wm1811_jackdet_set_mode(codec, | ||
3466 | WM1811_JACKDET_MODE_JACK); | ||
3467 | |||
3468 | mutex_unlock(&wm8994->accdet_lock); | ||
3469 | |||
3470 | if (wm8994->wm8994->pdata.jd_ext_cap) | ||
3471 | snd_soc_dapm_disable_pin(&codec->dapm, | ||
3472 | "MICBIAS2"); | ||
3473 | } | ||
3474 | 3497 | ||
3475 | snd_soc_jack_report(wm8994->micdet[0].jack, SND_JACK_HEADPHONE, | 3498 | snd_soc_jack_report(wm8994->micdet[0].jack, SND_JACK_HEADPHONE, |
3476 | SND_JACK_HEADSET); | 3499 | SND_JACK_HEADSET); |
3477 | } | 3500 | } |
3478 | |||
3479 | /* Report short circuit as a button */ | ||
3480 | if (wm8994->jack_mic) { | ||
3481 | report = 0; | ||
3482 | if (status & 0x4) | ||
3483 | report |= SND_JACK_BTN_0; | ||
3484 | |||
3485 | if (status & 0x8) | ||
3486 | report |= SND_JACK_BTN_1; | ||
3487 | |||
3488 | if (status & 0x10) | ||
3489 | report |= SND_JACK_BTN_2; | ||
3490 | |||
3491 | if (status & 0x20) | ||
3492 | report |= SND_JACK_BTN_3; | ||
3493 | |||
3494 | if (status & 0x40) | ||
3495 | report |= SND_JACK_BTN_4; | ||
3496 | |||
3497 | if (status & 0x80) | ||
3498 | report |= SND_JACK_BTN_5; | ||
3499 | |||
3500 | snd_soc_jack_report(wm8994->micdet[0].jack, report, | ||
3501 | wm8994->btn_mask); | ||
3502 | } | ||
3503 | } | 3501 | } |
3504 | 3502 | ||
3505 | /* Deferred mic detection to allow for extra settling time */ | 3503 | /* Deferred mic detection to allow for extra settling time */ |
@@ -3523,15 +3521,20 @@ static void wm1811_mic_work(struct work_struct *work) | |||
3523 | 3521 | ||
3524 | dev_dbg(codec->dev, "Starting mic detection\n"); | 3522 | dev_dbg(codec->dev, "Starting mic detection\n"); |
3525 | 3523 | ||
3526 | /* | 3524 | /* Use a user-supplied callback if we have one */ |
3527 | * Start off measument of microphone impedence to find out | 3525 | if (wm8994->micd_cb) { |
3528 | * what's actually there. | 3526 | wm8994->micd_cb(wm8994->micd_cb_data); |
3529 | */ | 3527 | } else { |
3530 | wm8994->mic_detecting = true; | 3528 | /* |
3531 | wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_MIC); | 3529 | * Start off measument of microphone impedence to find out |
3530 | * what's actually there. | ||
3531 | */ | ||
3532 | wm8994->mic_detecting = true; | ||
3533 | wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_MIC); | ||
3532 | 3534 | ||
3533 | snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, | 3535 | snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, |
3534 | WM8958_MICD_ENA, WM8958_MICD_ENA); | 3536 | WM8958_MICD_ENA, WM8958_MICD_ENA); |
3537 | } | ||
3535 | 3538 | ||
3536 | mutex_unlock(&wm8994->accdet_lock); | 3539 | mutex_unlock(&wm8994->accdet_lock); |
3537 | 3540 | ||
@@ -3643,7 +3646,8 @@ static void wm1811_jackdet_bootstrap(struct work_struct *work) | |||
3643 | * detection algorithm. | 3646 | * detection algorithm. |
3644 | */ | 3647 | */ |
3645 | int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, | 3648 | int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, |
3646 | wm8958_micdet_cb cb, void *cb_data) | 3649 | wm1811_micdet_cb det_cb, void *det_cb_data, |
3650 | wm1811_mic_id_cb id_cb, void *id_cb_data) | ||
3647 | { | 3651 | { |
3648 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 3652 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
3649 | struct wm8994 *control = wm8994->wm8994; | 3653 | struct wm8994 *control = wm8994->wm8994; |
@@ -3658,21 +3662,26 @@ int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, | |||
3658 | } | 3662 | } |
3659 | 3663 | ||
3660 | if (jack) { | 3664 | if (jack) { |
3661 | if (!cb) { | ||
3662 | dev_dbg(codec->dev, "Using default micdet callback\n"); | ||
3663 | cb = wm8958_default_micdet; | ||
3664 | cb_data = codec; | ||
3665 | } | ||
3666 | |||
3667 | snd_soc_dapm_force_enable_pin(&codec->dapm, "CLK_SYS"); | 3665 | snd_soc_dapm_force_enable_pin(&codec->dapm, "CLK_SYS"); |
3668 | snd_soc_dapm_sync(&codec->dapm); | 3666 | snd_soc_dapm_sync(&codec->dapm); |
3669 | 3667 | ||
3670 | wm8994->micdet[0].jack = jack; | 3668 | wm8994->micdet[0].jack = jack; |
3671 | wm8994->jack_cb = cb; | ||
3672 | wm8994->jack_cb_data = cb_data; | ||
3673 | 3669 | ||
3674 | wm8994->mic_detecting = true; | 3670 | if (det_cb) { |
3675 | wm8994->jack_mic = false; | 3671 | wm8994->micd_cb = det_cb; |
3672 | wm8994->micd_cb_data = det_cb_data; | ||
3673 | } else { | ||
3674 | wm8994->mic_detecting = true; | ||
3675 | wm8994->jack_mic = false; | ||
3676 | } | ||
3677 | |||
3678 | if (id_cb) { | ||
3679 | wm8994->mic_id_cb = id_cb; | ||
3680 | wm8994->mic_id_cb_data = id_cb_data; | ||
3681 | } else { | ||
3682 | wm8994->mic_id_cb = wm8958_mic_id; | ||
3683 | wm8994->mic_id_cb_data = codec; | ||
3684 | } | ||
3676 | 3685 | ||
3677 | wm8958_micd_set_rate(codec); | 3686 | wm8958_micd_set_rate(codec); |
3678 | 3687 | ||
@@ -3772,10 +3781,22 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data) | |||
3772 | trace_snd_soc_jack_irq(dev_name(codec->dev)); | 3781 | trace_snd_soc_jack_irq(dev_name(codec->dev)); |
3773 | #endif | 3782 | #endif |
3774 | 3783 | ||
3775 | if (wm8994->jack_cb) | 3784 | /* Avoid a transient report when the accessory is being removed */ |
3776 | wm8994->jack_cb(reg, wm8994->jack_cb_data); | 3785 | if (wm8994->jackdet) { |
3786 | reg = snd_soc_read(codec, WM1811_JACKDET_CTRL); | ||
3787 | if (reg < 0) { | ||
3788 | dev_err(codec->dev, "Failed to read jack status: %d\n", | ||
3789 | reg); | ||
3790 | } else if (!(reg & WM1811_JACKDET_LVL)) { | ||
3791 | dev_dbg(codec->dev, "Ignoring removed jack\n"); | ||
3792 | return IRQ_HANDLED; | ||
3793 | } | ||
3794 | } | ||
3795 | |||
3796 | if (wm8994->mic_detecting) | ||
3797 | wm8994->mic_id_cb(wm8994->mic_id_cb_data, reg); | ||
3777 | else | 3798 | else |
3778 | dev_warn(codec->dev, "Accessory detection with no callback\n"); | 3799 | wm8958_button_det(codec, reg); |
3779 | 3800 | ||
3780 | out: | 3801 | out: |
3781 | pm_runtime_put(codec->dev); | 3802 | pm_runtime_put(codec->dev); |
@@ -4266,7 +4287,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8994 = { | |||
4266 | .set_bias_level = wm8994_set_bias_level, | 4287 | .set_bias_level = wm8994_set_bias_level, |
4267 | }; | 4288 | }; |
4268 | 4289 | ||
4269 | static int __devinit wm8994_probe(struct platform_device *pdev) | 4290 | static int wm8994_probe(struct platform_device *pdev) |
4270 | { | 4291 | { |
4271 | struct wm8994_priv *wm8994; | 4292 | struct wm8994_priv *wm8994; |
4272 | 4293 | ||
@@ -4282,7 +4303,7 @@ static int __devinit wm8994_probe(struct platform_device *pdev) | |||
4282 | wm8994_dai, ARRAY_SIZE(wm8994_dai)); | 4303 | wm8994_dai, ARRAY_SIZE(wm8994_dai)); |
4283 | } | 4304 | } |
4284 | 4305 | ||
4285 | static int __devexit wm8994_remove(struct platform_device *pdev) | 4306 | static int wm8994_remove(struct platform_device *pdev) |
4286 | { | 4307 | { |
4287 | snd_soc_unregister_codec(&pdev->dev); | 4308 | snd_soc_unregister_codec(&pdev->dev); |
4288 | return 0; | 4309 | return 0; |
@@ -4306,7 +4327,7 @@ static int wm8994_resume(struct device *dev) | |||
4306 | { | 4327 | { |
4307 | struct wm8994_priv *wm8994 = dev_get_drvdata(dev); | 4328 | struct wm8994_priv *wm8994 = dev_get_drvdata(dev); |
4308 | 4329 | ||
4309 | if (wm8994->jackdet && wm8994->jack_cb) | 4330 | if (wm8994->jackdet && wm8994->jackdet_mode) |
4310 | regmap_update_bits(wm8994->wm8994->regmap, WM8994_ANTIPOP_2, | 4331 | regmap_update_bits(wm8994->wm8994->regmap, WM8994_ANTIPOP_2, |
4311 | WM1811_JACKDET_MODE_MASK, | 4332 | WM1811_JACKDET_MODE_MASK, |
4312 | WM1811_JACKDET_MODE_AUDIO); | 4333 | WM1811_JACKDET_MODE_AUDIO); |
@@ -4326,7 +4347,7 @@ static struct platform_driver wm8994_codec_driver = { | |||
4326 | .pm = &wm8994_pm_ops, | 4347 | .pm = &wm8994_pm_ops, |
4327 | }, | 4348 | }, |
4328 | .probe = wm8994_probe, | 4349 | .probe = wm8994_probe, |
4329 | .remove = __devexit_p(wm8994_remove), | 4350 | .remove = wm8994_remove, |
4330 | }; | 4351 | }; |
4331 | 4352 | ||
4332 | module_platform_driver(wm8994_codec_driver); | 4353 | module_platform_driver(wm8994_codec_driver); |