Lines Matching +full:debounce +full:- +full:press +full:- +full:ms

1 // SPDX-License-Identifier: GPL-2.0
5 // Copyright (C) 2022-2023 Cirrus Logic, Inc. and
15 #include <linux/mfd/cs42l43-regs.h>
26 #include <sound/soc-component.h>
27 #include <sound/soc-jack.h>
50 struct cs42l43 *cs42l43 = priv->core; in cs42l43_find_index()
53 ret = device_property_read_u32(cs42l43->dev, prop, &defval); in cs42l43_find_index()
54 if (ret != -EINVAL && ret < 0) { in cs42l43_find_index()
55 dev_err(priv->dev, "Property %s malformed: %d\n", prop, ret); in cs42l43_find_index()
66 dev_err(priv->dev, "Invalid value for property %s: %d\n", prop, defval); in cs42l43_find_index()
67 return -EINVAL; in cs42l43_find_index()
74 struct cs42l43 *cs42l43 = priv->core; in cs42l43_set_jack()
81 dev_dbg(priv->dev, "Configure accessory detect\n"); in cs42l43_set_jack()
83 ret = pm_runtime_resume_and_get(priv->dev); in cs42l43_set_jack()
85 dev_err(priv->dev, "Failed to resume for jack config: %d\n", ret); in cs42l43_set_jack()
89 mutex_lock(&priv->jack_lock); in cs42l43_set_jack()
91 priv->jack_hp = jack; in cs42l43_set_jack()
96 ret = device_property_count_u32(cs42l43->dev, "cirrus,buttons-ohms"); in cs42l43_set_jack()
97 if (ret != -EINVAL) { in cs42l43_set_jack()
99 dev_err(priv->dev, "Property cirrus,buttons-ohms malformed: %d\n", in cs42l43_set_jack()
105 ret = -EINVAL; in cs42l43_set_jack()
106 dev_err(priv->dev, "Property cirrus,buttons-ohms too many entries\n"); in cs42l43_set_jack()
110 ret = device_property_read_u32_array(cs42l43->dev, "cirrus,buttons-ohms", in cs42l43_set_jack()
111 priv->buttons, ret); in cs42l43_set_jack()
113 dev_err(priv->dev, "Property cirrus,button-ohms malformed: %d\n", in cs42l43_set_jack()
118 priv->buttons[0] = 70; in cs42l43_set_jack()
119 priv->buttons[1] = 185; in cs42l43_set_jack()
120 priv->buttons[2] = 355; in cs42l43_set_jack()
121 priv->buttons[3] = 735; in cs42l43_set_jack()
124 ret = cs42l43_find_index(priv, "cirrus,detect-us", 50000, &priv->detect_us, in cs42l43_set_jack()
131 priv->bias_low = device_property_read_bool(cs42l43->dev, "cirrus,bias-low"); in cs42l43_set_jack()
133 ret = cs42l43_find_index(priv, "cirrus,bias-ramp-ms", 170, in cs42l43_set_jack()
134 &priv->bias_ramp_ms, cs42l43_accdet_ramp_ms, in cs42l43_set_jack()
141 ret = cs42l43_find_index(priv, "cirrus,bias-sense-microamp", 14, in cs42l43_set_jack()
142 &priv->bias_sense_ua, cs42l43_accdet_bias_sense, in cs42l43_set_jack()
147 if (priv->bias_sense_ua) in cs42l43_set_jack()
150 if (!device_property_read_bool(cs42l43->dev, "cirrus,button-automute")) in cs42l43_set_jack()
153 ret = device_property_read_u32(cs42l43->dev, "cirrus,tip-debounce-ms", in cs42l43_set_jack()
154 &priv->tip_debounce_ms); in cs42l43_set_jack()
155 if (ret < 0 && ret != -EINVAL) { in cs42l43_set_jack()
156 dev_err(priv->dev, "Property cirrus,tip-debounce-ms malformed: %d\n", ret); in cs42l43_set_jack()
161 if (device_property_read_bool(cs42l43->dev, "cirrus,tip-invert")) in cs42l43_set_jack()
164 if (device_property_read_bool(cs42l43->dev, "cirrus,tip-disable-pullup")) in cs42l43_set_jack()
169 ret = cs42l43_find_index(priv, "cirrus,tip-fall-db-ms", 500, in cs42l43_set_jack()
177 ret = cs42l43_find_index(priv, "cirrus,tip-rise-db-ms", 500, in cs42l43_set_jack()
185 if (device_property_read_bool(cs42l43->dev, "cirrus,use-ring-sense")) { in cs42l43_set_jack()
188 priv->use_ring_sense = true; in cs42l43_set_jack()
191 if (!device_property_read_bool(cs42l43->dev, "cirrus,ring-invert")) in cs42l43_set_jack()
194 if (!device_property_read_bool(cs42l43->dev, in cs42l43_set_jack()
195 "cirrus,ring-disable-pullup")) in cs42l43_set_jack()
198 ret = cs42l43_find_index(priv, "cirrus,ring-fall-db-ms", 500, in cs42l43_set_jack()
206 ret = cs42l43_find_index(priv, "cirrus,ring-rise-db-ms", 500, in cs42l43_set_jack()
215 regmap_update_bits(cs42l43->regmap, CS42L43_RINGSENSE_DEB_CTRL, in cs42l43_set_jack()
223 regmap_update_bits(cs42l43->regmap, CS42L43_TIPSENSE_DEB_CTRL, in cs42l43_set_jack()
227 regmap_update_bits(cs42l43->regmap, CS42L43_HS2, in cs42l43_set_jack()
234 regmap_update_bits(cs42l43->regmap, CS42L43_HS_BIAS_SENSE_AND_CLAMP_AUTOCONTROL, in cs42l43_set_jack()
237 regmap_update_bits(cs42l43->regmap, CS42L43_PDNCNTL, in cs42l43_set_jack()
240 dev_dbg(priv->dev, "Successfully configured accessory detect\n"); in cs42l43_set_jack()
243 mutex_unlock(&priv->jack_lock); in cs42l43_set_jack()
245 pm_runtime_mark_last_busy(priv->dev); in cs42l43_set_jack()
246 pm_runtime_put_autosuspend(priv->dev); in cs42l43_set_jack()
253 struct cs42l43 *cs42l43 = priv->core; in cs42l43_start_hs_bias()
256 dev_dbg(priv->dev, "Start headset bias\n"); in cs42l43_start_hs_bias()
258 regmap_update_bits(cs42l43->regmap, CS42L43_HS2, in cs42l43_start_hs_bias()
262 if (priv->bias_low) in cs42l43_start_hs_bias()
265 if (priv->bias_sense_ua) in cs42l43_start_hs_bias()
266 regmap_update_bits(cs42l43->regmap, in cs42l43_start_hs_bias()
274 regmap_update_bits(cs42l43->regmap, CS42L43_MIC_DETECT_CONTROL_1, in cs42l43_start_hs_bias()
277 msleep(priv->bias_ramp_ms); in cs42l43_start_hs_bias()
282 struct cs42l43 *cs42l43 = priv->core; in cs42l43_stop_hs_bias()
284 dev_dbg(priv->dev, "Stop headset bias\n"); in cs42l43_stop_hs_bias()
286 regmap_update_bits(cs42l43->regmap, CS42L43_MIC_DETECT_CONTROL_1, in cs42l43_stop_hs_bias()
289 regmap_update_bits(cs42l43->regmap, CS42L43_HS2, in cs42l43_stop_hs_bias()
292 if (priv->bias_sense_ua) { in cs42l43_stop_hs_bias()
293 regmap_update_bits(cs42l43->regmap, in cs42l43_stop_hs_bias()
304 queue_delayed_work(system_wq, &priv->bias_sense_timeout, in cs42l43_bias_detect_clamp()
324 struct cs42l43 *cs42l43 = priv->core; in cs42l43_jack_present()
327 regmap_read(cs42l43->regmap, CS42L43_TIP_RING_SENSE_INTERRUPT_STATUS, &sts); in cs42l43_jack_present()
336 struct cs42l43 *cs42l43 = priv->core; in cs42l43_start_button_detect()
339 dev_dbg(priv->dev, "Start button detect\n"); in cs42l43_start_button_detect()
341 priv->button_detect_running = true; in cs42l43_start_button_detect()
343 if (priv->bias_low) in cs42l43_start_button_detect()
346 regmap_update_bits(cs42l43->regmap, CS42L43_MIC_DETECT_CONTROL_1, in cs42l43_start_button_detect()
353 struct cs42l43 *cs42l43 = priv->core; in cs42l43_stop_button_detect()
355 dev_dbg(priv->dev, "Stop button detect\n"); in cs42l43_stop_button_detect()
357 regmap_update_bits(cs42l43->regmap, CS42L43_MIC_DETECT_CONTROL_1, in cs42l43_stop_button_detect()
362 priv->button_detect_running = false; in cs42l43_stop_button_detect()
372 struct cs42l43 *cs42l43 = priv->core; in cs42l43_button_press_work()
377 ret = pm_runtime_resume_and_get(priv->dev); in cs42l43_button_press_work()
379 dev_err(priv->dev, "Failed to resume for button press: %d\n", ret); in cs42l43_button_press_work()
383 mutex_lock(&priv->jack_lock); in cs42l43_button_press_work()
385 if (!priv->button_detect_running) { in cs42l43_button_press_work()
386 dev_dbg(priv->dev, "Spurious button press IRQ\n"); in cs42l43_button_press_work()
390 regmap_read(cs42l43->regmap, CS42L43_DETECT_STATUS_1, &val); in cs42l43_button_press_work()
394 dev_dbg(priv->dev, "Button ignored due to removal\n"); in cs42l43_button_press_work()
399 dev_dbg(priv->dev, "Button ignored due to bias sense\n"); in cs42l43_button_press_work()
404 val = ((CS42L43_BUTTON_COMB_MAX << 20) / (val + 1)) - (1 << 20); in cs42l43_button_press_work()
411 if (val < priv->buttons[i]) { in cs42l43_button_press_work()
413 dev_dbg(priv->dev, "Detected button %d at %d Ohms\n", i, val); in cs42l43_button_press_work()
419 dev_dbg(priv->dev, "Unrecognised button: %d Ohms\n", val); in cs42l43_button_press_work()
421 snd_soc_jack_report(priv->jack_hp, buttons, CS42L43_JACK_BUTTONS); in cs42l43_button_press_work()
424 mutex_unlock(&priv->jack_lock); in cs42l43_button_press_work()
426 pm_runtime_mark_last_busy(priv->dev); in cs42l43_button_press_work()
427 pm_runtime_put_autosuspend(priv->dev); in cs42l43_button_press_work()
435 queue_delayed_work(system_wq, &priv->button_press_work, in cs42l43_button_press()
447 ret = pm_runtime_resume_and_get(priv->dev); in cs42l43_button_release_work()
449 dev_err(priv->dev, "Failed to resume for button release: %d\n", ret); in cs42l43_button_release_work()
453 mutex_lock(&priv->jack_lock); in cs42l43_button_release_work()
455 if (priv->button_detect_running) { in cs42l43_button_release_work()
456 dev_dbg(priv->dev, "Button release IRQ\n"); in cs42l43_button_release_work()
458 snd_soc_jack_report(priv->jack_hp, 0, CS42L43_JACK_BUTTONS); in cs42l43_button_release_work()
460 dev_dbg(priv->dev, "Spurious button release IRQ\n"); in cs42l43_button_release_work()
463 mutex_unlock(&priv->jack_lock); in cs42l43_button_release_work()
465 pm_runtime_mark_last_busy(priv->dev); in cs42l43_button_release_work()
466 pm_runtime_put_autosuspend(priv->dev); in cs42l43_button_release_work()
473 queue_work(system_wq, &priv->button_release_work); in cs42l43_button_release()
482 struct cs42l43 *cs42l43 = priv->core; in cs42l43_bias_sense_timeout()
485 ret = pm_runtime_resume_and_get(priv->dev); in cs42l43_bias_sense_timeout()
487 dev_err(priv->dev, "Failed to resume for bias sense: %d\n", ret); in cs42l43_bias_sense_timeout()
491 mutex_lock(&priv->jack_lock); in cs42l43_bias_sense_timeout()
493 if (cs42l43_jack_present(priv) && priv->button_detect_running) { in cs42l43_bias_sense_timeout()
494 dev_dbg(priv->dev, "Bias sense timeout out, restore bias\n"); in cs42l43_bias_sense_timeout()
496 regmap_update_bits(cs42l43->regmap, in cs42l43_bias_sense_timeout()
499 regmap_update_bits(cs42l43->regmap, in cs42l43_bias_sense_timeout()
505 mutex_unlock(&priv->jack_lock); in cs42l43_bias_sense_timeout()
507 pm_runtime_mark_last_busy(priv->dev); in cs42l43_bias_sense_timeout()
508 pm_runtime_put_autosuspend(priv->dev); in cs42l43_bias_sense_timeout()
513 struct cs42l43 *cs42l43 = priv->core; in cs42l43_start_load_detect()
515 dev_dbg(priv->dev, "Start load detect\n"); in cs42l43_start_load_detect()
517 snd_soc_dapm_mutex_lock(snd_soc_component_get_dapm(priv->component)); in cs42l43_start_load_detect()
519 priv->load_detect_running = true; in cs42l43_start_load_detect()
521 if (priv->hp_ena && !priv->hp_ilimited) { in cs42l43_start_load_detect()
524 reinit_completion(&priv->hp_shutdown); in cs42l43_start_load_detect()
526 regmap_update_bits(cs42l43->regmap, CS42L43_BLOCK_EN8, in cs42l43_start_load_detect()
529 time_left = wait_for_completion_timeout(&priv->hp_shutdown, in cs42l43_start_load_detect()
532 dev_err(priv->dev, "Load detect HP power down timed out\n"); in cs42l43_start_load_detect()
535 regmap_update_bits(cs42l43->regmap, CS42L43_BLOCK_EN3, in cs42l43_start_load_detect()
537 regmap_update_bits(cs42l43->regmap, CS42L43_DACCNFG2, CS42L43_HP_HPF_EN_MASK, 0); in cs42l43_start_load_detect()
538 regmap_update_bits(cs42l43->regmap, CS42L43_MIC_DETECT_CONTROL_1, in cs42l43_start_load_detect()
540 regmap_update_bits(cs42l43->regmap, CS42L43_CTRL, in cs42l43_start_load_detect()
542 regmap_update_bits(cs42l43->regmap, CS42L43_PGAVOL, in cs42l43_start_load_detect()
544 regmap_update_bits(cs42l43->regmap, CS42L43_DACCNFG1, in cs42l43_start_load_detect()
547 regmap_update_bits(cs42l43->regmap, CS42L43_HS2, in cs42l43_start_load_detect()
550 regmap_update_bits(cs42l43->regmap, CS42L43_LOADDETENA, in cs42l43_start_load_detect()
554 snd_soc_dapm_mutex_unlock(snd_soc_component_get_dapm(priv->component)); in cs42l43_start_load_detect()
559 struct cs42l43 *cs42l43 = priv->core; in cs42l43_stop_load_detect()
561 dev_dbg(priv->dev, "Stop load detect\n"); in cs42l43_stop_load_detect()
563 snd_soc_dapm_mutex_lock(snd_soc_component_get_dapm(priv->component)); in cs42l43_stop_load_detect()
565 regmap_update_bits(cs42l43->regmap, CS42L43_LOADDETENA, in cs42l43_stop_load_detect()
567 regmap_update_bits(cs42l43->regmap, CS42L43_HS2, in cs42l43_stop_load_detect()
569 regmap_update_bits(cs42l43->regmap, CS42L43_DACCNFG1, in cs42l43_stop_load_detect()
572 regmap_update_bits(cs42l43->regmap, CS42L43_PGAVOL, in cs42l43_stop_load_detect()
575 regmap_update_bits(cs42l43->regmap, CS42L43_CTRL, in cs42l43_stop_load_detect()
577 regmap_update_bits(cs42l43->regmap, CS42L43_MIC_DETECT_CONTROL_1, in cs42l43_stop_load_detect()
579 regmap_update_bits(cs42l43->regmap, CS42L43_DACCNFG2, in cs42l43_stop_load_detect()
582 regmap_update_bits(cs42l43->regmap, CS42L43_BLOCK_EN3, in cs42l43_stop_load_detect()
584 priv->adc_ena); in cs42l43_stop_load_detect()
586 if (priv->hp_ena && !priv->hp_ilimited) { in cs42l43_stop_load_detect()
589 reinit_completion(&priv->hp_startup); in cs42l43_stop_load_detect()
591 regmap_update_bits(cs42l43->regmap, CS42L43_BLOCK_EN8, in cs42l43_stop_load_detect()
592 CS42L43_HP_EN_MASK, priv->hp_ena); in cs42l43_stop_load_detect()
594 time_left = wait_for_completion_timeout(&priv->hp_startup, in cs42l43_stop_load_detect()
597 dev_err(priv->dev, "Load detect HP restore timed out\n"); in cs42l43_stop_load_detect()
600 priv->load_detect_running = false; in cs42l43_stop_load_detect()
602 snd_soc_dapm_mutex_unlock(snd_soc_component_get_dapm(priv->component)); in cs42l43_stop_load_detect()
607 struct cs42l43 *cs42l43 = priv->core; in cs42l43_run_load_detect()
611 reinit_completion(&priv->load_detect); in cs42l43_run_load_detect()
614 time_left = wait_for_completion_timeout(&priv->load_detect, in cs42l43_run_load_detect()
619 return -ETIMEDOUT; in cs42l43_run_load_detect()
621 regmap_read(cs42l43->regmap, CS42L43_LOADDETRESULTS, &val); in cs42l43_run_load_detect()
623 dev_dbg(priv->dev, "Headphone load detect: 0x%x\n", val); in cs42l43_run_load_detect()
627 return -ENODEV; in cs42l43_run_load_detect()
644 return -EINVAL; in cs42l43_run_load_detect()
650 struct cs42l43 *cs42l43 = priv->core; in cs42l43_run_type_detect()
651 int timeout_ms = ((2 * priv->detect_us) / USEC_PER_MSEC) + 200; in cs42l43_run_type_detect()
655 reinit_completion(&priv->type_detect); in cs42l43_run_type_detect()
658 regmap_update_bits(cs42l43->regmap, CS42L43_HS2, in cs42l43_run_type_detect()
661 time_left = wait_for_completion_timeout(&priv->type_detect, in cs42l43_run_type_detect()
664 regmap_update_bits(cs42l43->regmap, CS42L43_HS2, in cs42l43_run_type_detect()
669 return -ETIMEDOUT; in cs42l43_run_type_detect()
671 regmap_read(cs42l43->regmap, CS42L43_HS_STAT, &type); in cs42l43_run_type_detect()
673 dev_dbg(priv->dev, "Type detect: 0x%x\n", type); in cs42l43_run_type_detect()
677 return -ENODEV; in cs42l43_run_type_detect()
683 case 0x2: // 3-pole in cs42l43_run_type_detect()
685 case 0x3: // Open-circuit in cs42l43_run_type_detect()
688 return -EINVAL; in cs42l43_run_type_detect()
694 struct cs42l43 *cs42l43 = priv->core; in cs42l43_clear_jack()
699 regmap_update_bits(cs42l43->regmap, CS42L43_ADC_B_CTRL1, in cs42l43_clear_jack()
701 regmap_update_bits(cs42l43->regmap, CS42L43_ADC_B_CTRL2, in cs42l43_clear_jack()
703 regmap_update_bits(cs42l43->regmap, CS42L43_STEREO_MIC_CTRL, in cs42l43_clear_jack()
705 regmap_update_bits(cs42l43->regmap, CS42L43_HS2, in cs42l43_clear_jack()
709 snd_soc_jack_report(priv->jack_hp, 0, 0xFFFF); in cs42l43_clear_jack()
716 struct cs42l43 *cs42l43 = priv->core; in cs42l43_tip_sense_work()
721 ret = pm_runtime_resume_and_get(priv->dev); in cs42l43_tip_sense_work()
723 dev_err(priv->dev, "Failed to resume for tip work: %d\n", ret); in cs42l43_tip_sense_work()
727 mutex_lock(&priv->jack_lock); in cs42l43_tip_sense_work()
729 regmap_read(cs42l43->regmap, CS42L43_TIP_RING_SENSE_INTERRUPT_STATUS, &sts); in cs42l43_tip_sense_work()
731 dev_dbg(priv->dev, "Tip sense: 0x%x\n", sts); in cs42l43_tip_sense_work()
737 if (cs42l43->sdw && !priv->jack_present) { in cs42l43_tip_sense_work()
738 priv->jack_present = true; in cs42l43_tip_sense_work()
739 pm_runtime_get(priv->dev); in cs42l43_tip_sense_work()
742 if (priv->use_ring_sense && ring == CS42L43_JACK_ABSENT) { in cs42l43_tip_sense_work()
747 dev_err(priv->dev, "Jack detect failed: %d\n", report); in cs42l43_tip_sense_work()
752 snd_soc_jack_report(priv->jack_hp, report, report); in cs42l43_tip_sense_work()
754 priv->jack_override = 0; in cs42l43_tip_sense_work()
758 if (cs42l43->sdw && priv->jack_present) { in cs42l43_tip_sense_work()
759 pm_runtime_put(priv->dev); in cs42l43_tip_sense_work()
760 priv->jack_present = false; in cs42l43_tip_sense_work()
765 mutex_unlock(&priv->jack_lock); in cs42l43_tip_sense_work()
767 pm_runtime_mark_last_busy(priv->dev); in cs42l43_tip_sense_work()
768 pm_runtime_put_autosuspend(priv->dev); in cs42l43_tip_sense_work()
775 cancel_delayed_work(&priv->bias_sense_timeout); in cs42l43_tip_sense()
776 cancel_delayed_work(&priv->tip_sense_work); in cs42l43_tip_sense()
777 cancel_delayed_work(&priv->button_press_work); in cs42l43_tip_sense()
778 cancel_work(&priv->button_release_work); in cs42l43_tip_sense()
780 queue_delayed_work(system_long_wq, &priv->tip_sense_work, in cs42l43_tip_sense()
781 msecs_to_jiffies(priv->tip_debounce_ms)); in cs42l43_tip_sense()
856 "None", "CTIA", "OMTP", "Headphone", "Line-Out",
857 "Line-In", "Microphone", "Optical",
861 ARRAY_SIZE(cs42l43_jack_text) - 1);
870 mutex_lock(&priv->jack_lock); in cs42l43_jack_get()
871 ucontrol->value.integer.value[0] = priv->jack_override; in cs42l43_jack_get()
872 mutex_unlock(&priv->jack_lock); in cs42l43_jack_get()
881 struct cs42l43 *cs42l43 = priv->core; in cs42l43_jack_put()
882 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; in cs42l43_jack_put()
883 unsigned int override = ucontrol->value.integer.value[0]; in cs42l43_jack_put()
885 if (override >= e->items) in cs42l43_jack_put()
886 return -EINVAL; in cs42l43_jack_put()
888 mutex_lock(&priv->jack_lock); in cs42l43_jack_put()
891 mutex_unlock(&priv->jack_lock); in cs42l43_jack_put()
892 return -EBUSY; in cs42l43_jack_put()
895 if (override == priv->jack_override) { in cs42l43_jack_put()
896 mutex_unlock(&priv->jack_lock); in cs42l43_jack_put()
900 priv->jack_override = override; in cs42l43_jack_put()
905 queue_delayed_work(system_long_wq, &priv->tip_sense_work, 0); in cs42l43_jack_put()
907 override--; in cs42l43_jack_put()
909 regmap_update_bits(cs42l43->regmap, CS42L43_HS2, in cs42l43_jack_put()
921 regmap_update_bits(cs42l43->regmap, CS42L43_STEREO_MIC_CTRL, in cs42l43_jack_put()
925 regmap_update_bits(cs42l43->regmap, CS42L43_STEREO_MIC_CLAMP_CTRL, in cs42l43_jack_put()
936 regmap_update_bits(cs42l43->regmap, CS42L43_ADC_B_CTRL1, in cs42l43_jack_put()
939 regmap_update_bits(cs42l43->regmap, CS42L43_ADC_B_CTRL2, in cs42l43_jack_put()
950 snd_soc_jack_report(priv->jack_hp, in cs42l43_jack_put()
955 mutex_unlock(&priv->jack_lock); in cs42l43_jack_put()