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.c201
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
94static void wm8958_default_micdet(u16 status, void *data);
95
96static const struct wm8958_micd_rate micdet_rates[] = { 94static 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 3403static 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);
3411static 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
3423static 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
3451static 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 */
3645int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, 3648int 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
3780out: 3801out:
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
4269static int __devinit wm8994_probe(struct platform_device *pdev) 4290static 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
4285static int __devexit wm8994_remove(struct platform_device *pdev) 4306static 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
4332module_platform_driver(wm8994_codec_driver); 4353module_platform_driver(wm8994_codec_driver);