Lines Matching +full:use +full:- +full:ring +full:- +full:sense

1 // SPDX-License-Identifier: GPL-2.0
5 // Copyright (C) 2022-2023 Cirrus Logic, Inc. and
14 #include <linux/mfd/cs42l43-regs.h>
21 #include <sound/soc-component.h>
44 struct cs42l43 *cs42l43 = priv->core; in cs42l43_find_index()
47 ret = device_property_read_u32(cs42l43->dev, prop, &defval); in cs42l43_find_index()
48 if (ret != -EINVAL && ret < 0) { in cs42l43_find_index()
49 dev_err(priv->dev, "Property %s malformed: %d\n", prop, ret); in cs42l43_find_index()
60 dev_err(priv->dev, "Invalid value for property %s: %d\n", prop, defval); in cs42l43_find_index()
61 return -EINVAL; in cs42l43_find_index()
68 struct cs42l43 *cs42l43 = priv->core; in cs42l43_set_jack()
69 /* This tip sense invert is always set, HW wants an inverted signal */ in cs42l43_set_jack()
75 dev_dbg(priv->dev, "Configure accessory detect\n"); in cs42l43_set_jack()
77 ret = pm_runtime_resume_and_get(priv->dev); in cs42l43_set_jack()
79 dev_err(priv->dev, "Failed to resume for jack config: %d\n", ret); in cs42l43_set_jack()
83 mutex_lock(&priv->jack_lock); in cs42l43_set_jack()
85 priv->jack_hp = jack; in cs42l43_set_jack()
90 ret = device_property_count_u32(cs42l43->dev, "cirrus,buttons-ohms"); in cs42l43_set_jack()
91 if (ret != -EINVAL) { in cs42l43_set_jack()
93 dev_err(priv->dev, "Property cirrus,buttons-ohms malformed: %d\n", in cs42l43_set_jack()
99 ret = -EINVAL; in cs42l43_set_jack()
100 dev_err(priv->dev, "Property cirrus,buttons-ohms too many entries\n"); in cs42l43_set_jack()
104 device_property_read_u32_array(cs42l43->dev, "cirrus,buttons-ohms", in cs42l43_set_jack()
105 priv->buttons, ret); in cs42l43_set_jack()
107 priv->buttons[0] = 70; in cs42l43_set_jack()
108 priv->buttons[1] = 185; in cs42l43_set_jack()
109 priv->buttons[2] = 355; in cs42l43_set_jack()
110 priv->buttons[3] = 735; in cs42l43_set_jack()
113 ret = cs42l43_find_index(priv, "cirrus,detect-us", 10000, &priv->detect_us, in cs42l43_set_jack()
120 priv->bias_low = device_property_read_bool(cs42l43->dev, "cirrus,bias-low"); in cs42l43_set_jack()
122 ret = cs42l43_find_index(priv, "cirrus,bias-ramp-ms", 170, in cs42l43_set_jack()
123 &priv->bias_ramp_ms, cs42l43_accdet_ramp_ms, in cs42l43_set_jack()
130 ret = cs42l43_find_index(priv, "cirrus,bias-sense-microamp", 0, in cs42l43_set_jack()
131 &priv->bias_sense_ua, cs42l43_accdet_bias_sense, in cs42l43_set_jack()
136 if (priv->bias_sense_ua) in cs42l43_set_jack()
139 if (!device_property_read_bool(cs42l43->dev, "cirrus,button-automute")) in cs42l43_set_jack()
142 ret = device_property_read_u32(cs42l43->dev, "cirrus,tip-debounce-ms", in cs42l43_set_jack()
143 &priv->tip_debounce_ms); in cs42l43_set_jack()
144 if (ret < 0 && ret != -EINVAL) { in cs42l43_set_jack()
145 dev_err(priv->dev, "Property cirrus,tip-debounce-ms malformed: %d\n", ret); in cs42l43_set_jack()
149 /* This tip sense invert is set normally, as TIPSENSE_INV already inverted */ in cs42l43_set_jack()
150 if (device_property_read_bool(cs42l43->dev, "cirrus,tip-invert")) in cs42l43_set_jack()
153 if (device_property_read_bool(cs42l43->dev, "cirrus,tip-disable-pullup")) in cs42l43_set_jack()
158 ret = cs42l43_find_index(priv, "cirrus,tip-fall-db-ms", 500, in cs42l43_set_jack()
166 ret = cs42l43_find_index(priv, "cirrus,tip-rise-db-ms", 500, in cs42l43_set_jack()
174 if (device_property_read_bool(cs42l43->dev, "cirrus,use-ring-sense")) { in cs42l43_set_jack()
177 priv->use_ring_sense = true; in cs42l43_set_jack()
180 if (!device_property_read_bool(cs42l43->dev, "cirrus,ring-invert")) in cs42l43_set_jack()
183 if (!device_property_read_bool(cs42l43->dev, in cs42l43_set_jack()
184 "cirrus,ring-disable-pullup")) in cs42l43_set_jack()
187 ret = cs42l43_find_index(priv, "cirrus,ring-fall-db-ms", 500, in cs42l43_set_jack()
195 ret = cs42l43_find_index(priv, "cirrus,ring-rise-db-ms", 500, in cs42l43_set_jack()
204 regmap_update_bits(cs42l43->regmap, CS42L43_RINGSENSE_DEB_CTRL, in cs42l43_set_jack()
212 regmap_update_bits(cs42l43->regmap, CS42L43_TIPSENSE_DEB_CTRL, in cs42l43_set_jack()
216 regmap_update_bits(cs42l43->regmap, CS42L43_HS2, in cs42l43_set_jack()
223 regmap_update_bits(cs42l43->regmap, CS42L43_HS_BIAS_SENSE_AND_CLAMP_AUTOCONTROL, in cs42l43_set_jack()
226 regmap_update_bits(cs42l43->regmap, CS42L43_PDNCNTL, in cs42l43_set_jack()
229 dev_dbg(priv->dev, "Successfully configured accessory detect\n"); in cs42l43_set_jack()
232 mutex_unlock(&priv->jack_lock); in cs42l43_set_jack()
234 pm_runtime_mark_last_busy(priv->dev); in cs42l43_set_jack()
235 pm_runtime_put_autosuspend(priv->dev); in cs42l43_set_jack()
242 struct cs42l43 *cs42l43 = priv->core; in cs42l43_start_hs_bias()
245 dev_dbg(priv->dev, "Start headset bias\n"); in cs42l43_start_hs_bias()
247 regmap_update_bits(cs42l43->regmap, CS42L43_HS2, in cs42l43_start_hs_bias()
250 if (!force_high && priv->bias_low) in cs42l43_start_hs_bias()
253 regmap_update_bits(cs42l43->regmap, CS42L43_MIC_DETECT_CONTROL_1, in cs42l43_start_hs_bias()
256 msleep(priv->bias_ramp_ms); in cs42l43_start_hs_bias()
261 struct cs42l43 *cs42l43 = priv->core; in cs42l43_stop_hs_bias()
263 dev_dbg(priv->dev, "Stop headset bias\n"); in cs42l43_stop_hs_bias()
265 regmap_update_bits(cs42l43->regmap, CS42L43_MIC_DETECT_CONTROL_1, in cs42l43_stop_hs_bias()
268 regmap_update_bits(cs42l43->regmap, CS42L43_HS2, in cs42l43_stop_hs_bias()
276 queue_delayed_work(system_wq, &priv->bias_sense_timeout, in cs42l43_bias_detect_clamp()
296 struct cs42l43 *cs42l43 = priv->core; in cs42l43_jack_present()
299 regmap_read(cs42l43->regmap, CS42L43_TIP_RING_SENSE_INTERRUPT_STATUS, &sts); in cs42l43_jack_present()
308 struct cs42l43 *cs42l43 = priv->core; in cs42l43_start_button_detect()
311 dev_dbg(priv->dev, "Start button detect\n"); in cs42l43_start_button_detect()
313 priv->button_detect_running = true; in cs42l43_start_button_detect()
315 if (priv->bias_low) in cs42l43_start_button_detect()
318 regmap_update_bits(cs42l43->regmap, CS42L43_MIC_DETECT_CONTROL_1, in cs42l43_start_button_detect()
322 if (priv->bias_sense_ua) { in cs42l43_start_button_detect()
323 regmap_update_bits(cs42l43->regmap, in cs42l43_start_button_detect()
334 struct cs42l43 *cs42l43 = priv->core; in cs42l43_stop_button_detect()
336 dev_dbg(priv->dev, "Stop button detect\n"); in cs42l43_stop_button_detect()
338 if (priv->bias_sense_ua) { in cs42l43_stop_button_detect()
339 regmap_update_bits(cs42l43->regmap, in cs42l43_stop_button_detect()
345 regmap_update_bits(cs42l43->regmap, CS42L43_MIC_DETECT_CONTROL_1, in cs42l43_stop_button_detect()
350 priv->button_detect_running = false; in cs42l43_stop_button_detect()
360 struct cs42l43 *cs42l43 = priv->core; in cs42l43_button_press_work()
365 ret = pm_runtime_resume_and_get(priv->dev); in cs42l43_button_press_work()
367 dev_err(priv->dev, "Failed to resume for button press: %d\n", ret); in cs42l43_button_press_work()
371 mutex_lock(&priv->jack_lock); in cs42l43_button_press_work()
373 if (!priv->button_detect_running) { in cs42l43_button_press_work()
374 dev_dbg(priv->dev, "Spurious button press IRQ\n"); in cs42l43_button_press_work()
378 regmap_read(cs42l43->regmap, CS42L43_DETECT_STATUS_1, &val); in cs42l43_button_press_work()
382 dev_dbg(priv->dev, "Button ignored due to removal\n"); in cs42l43_button_press_work()
387 dev_dbg(priv->dev, "Button ignored due to bias sense\n"); in cs42l43_button_press_work()
392 val = ((CS42L43_BUTTON_COMB_MAX << 20) / (val + 1)) - (1 << 20); in cs42l43_button_press_work()
399 if (val < priv->buttons[i]) { in cs42l43_button_press_work()
401 dev_dbg(priv->dev, "Detected button %d at %d Ohms\n", i, val); in cs42l43_button_press_work()
407 dev_dbg(priv->dev, "Unrecognised button: %d Ohms\n", val); in cs42l43_button_press_work()
409 snd_soc_jack_report(priv->jack_hp, buttons, CS42L43_JACK_BUTTONS); in cs42l43_button_press_work()
412 mutex_unlock(&priv->jack_lock); in cs42l43_button_press_work()
414 pm_runtime_mark_last_busy(priv->dev); in cs42l43_button_press_work()
415 pm_runtime_put_autosuspend(priv->dev); in cs42l43_button_press_work()
423 queue_delayed_work(system_wq, &priv->button_press_work, in cs42l43_button_press()
435 ret = pm_runtime_resume_and_get(priv->dev); in cs42l43_button_release_work()
437 dev_err(priv->dev, "Failed to resume for button release: %d\n", ret); in cs42l43_button_release_work()
441 mutex_lock(&priv->jack_lock); in cs42l43_button_release_work()
443 if (priv->button_detect_running) { in cs42l43_button_release_work()
444 dev_dbg(priv->dev, "Button release IRQ\n"); in cs42l43_button_release_work()
446 snd_soc_jack_report(priv->jack_hp, 0, CS42L43_JACK_BUTTONS); in cs42l43_button_release_work()
448 dev_dbg(priv->dev, "Spurious button release IRQ\n"); in cs42l43_button_release_work()
451 mutex_unlock(&priv->jack_lock); in cs42l43_button_release_work()
453 pm_runtime_mark_last_busy(priv->dev); in cs42l43_button_release_work()
454 pm_runtime_put_autosuspend(priv->dev); in cs42l43_button_release_work()
461 queue_work(system_wq, &priv->button_release_work); in cs42l43_button_release()
470 struct cs42l43 *cs42l43 = priv->core; in cs42l43_bias_sense_timeout()
473 ret = pm_runtime_resume_and_get(priv->dev); in cs42l43_bias_sense_timeout()
475 dev_err(priv->dev, "Failed to resume for bias sense: %d\n", ret); in cs42l43_bias_sense_timeout()
479 mutex_lock(&priv->jack_lock); in cs42l43_bias_sense_timeout()
481 if (cs42l43_jack_present(priv) && priv->button_detect_running) { in cs42l43_bias_sense_timeout()
482 dev_dbg(priv->dev, "Bias sense timeout out, restore bias\n"); in cs42l43_bias_sense_timeout()
484 regmap_update_bits(cs42l43->regmap, in cs42l43_bias_sense_timeout()
487 regmap_update_bits(cs42l43->regmap, in cs42l43_bias_sense_timeout()
493 mutex_unlock(&priv->jack_lock); in cs42l43_bias_sense_timeout()
495 pm_runtime_mark_last_busy(priv->dev); in cs42l43_bias_sense_timeout()
496 pm_runtime_put_autosuspend(priv->dev); in cs42l43_bias_sense_timeout()
501 struct cs42l43 *cs42l43 = priv->core; in cs42l43_start_load_detect()
503 dev_dbg(priv->dev, "Start load detect\n"); in cs42l43_start_load_detect()
505 snd_soc_dapm_mutex_lock(snd_soc_component_get_dapm(priv->component)); in cs42l43_start_load_detect()
507 priv->load_detect_running = true; in cs42l43_start_load_detect()
509 if (priv->hp_ena) { in cs42l43_start_load_detect()
512 reinit_completion(&priv->hp_shutdown); in cs42l43_start_load_detect()
514 regmap_update_bits(cs42l43->regmap, CS42L43_BLOCK_EN8, in cs42l43_start_load_detect()
517 time_left = wait_for_completion_timeout(&priv->hp_shutdown, in cs42l43_start_load_detect()
520 dev_err(priv->dev, "Load detect HP power down timed out\n"); in cs42l43_start_load_detect()
523 regmap_update_bits(cs42l43->regmap, CS42L43_BLOCK_EN3, in cs42l43_start_load_detect()
525 regmap_update_bits(cs42l43->regmap, CS42L43_DACCNFG2, CS42L43_HP_HPF_EN_MASK, 0); in cs42l43_start_load_detect()
526 regmap_update_bits(cs42l43->regmap, CS42L43_MIC_DETECT_CONTROL_1, in cs42l43_start_load_detect()
528 regmap_update_bits(cs42l43->regmap, CS42L43_CTRL, in cs42l43_start_load_detect()
530 regmap_update_bits(cs42l43->regmap, CS42L43_PGAVOL, in cs42l43_start_load_detect()
532 regmap_update_bits(cs42l43->regmap, CS42L43_DACCNFG1, in cs42l43_start_load_detect()
535 regmap_update_bits(cs42l43->regmap, CS42L43_HS2, in cs42l43_start_load_detect()
538 regmap_update_bits(cs42l43->regmap, CS42L43_LOADDETENA, in cs42l43_start_load_detect()
542 snd_soc_dapm_mutex_unlock(snd_soc_component_get_dapm(priv->component)); in cs42l43_start_load_detect()
547 struct cs42l43 *cs42l43 = priv->core; in cs42l43_stop_load_detect()
549 dev_dbg(priv->dev, "Stop load detect\n"); in cs42l43_stop_load_detect()
551 snd_soc_dapm_mutex_lock(snd_soc_component_get_dapm(priv->component)); in cs42l43_stop_load_detect()
553 regmap_update_bits(cs42l43->regmap, CS42L43_LOADDETENA, in cs42l43_stop_load_detect()
555 regmap_update_bits(cs42l43->regmap, CS42L43_HS2, in cs42l43_stop_load_detect()
557 regmap_update_bits(cs42l43->regmap, CS42L43_DACCNFG1, in cs42l43_stop_load_detect()
560 regmap_update_bits(cs42l43->regmap, CS42L43_PGAVOL, in cs42l43_stop_load_detect()
563 regmap_update_bits(cs42l43->regmap, CS42L43_CTRL, in cs42l43_stop_load_detect()
565 regmap_update_bits(cs42l43->regmap, CS42L43_MIC_DETECT_CONTROL_1, in cs42l43_stop_load_detect()
567 regmap_update_bits(cs42l43->regmap, CS42L43_DACCNFG2, in cs42l43_stop_load_detect()
570 regmap_update_bits(cs42l43->regmap, CS42L43_BLOCK_EN3, in cs42l43_stop_load_detect()
572 priv->adc_ena); in cs42l43_stop_load_detect()
574 if (priv->hp_ena) { in cs42l43_stop_load_detect()
577 reinit_completion(&priv->hp_startup); in cs42l43_stop_load_detect()
579 regmap_update_bits(cs42l43->regmap, CS42L43_BLOCK_EN8, in cs42l43_stop_load_detect()
580 CS42L43_HP_EN_MASK, priv->hp_ena); in cs42l43_stop_load_detect()
582 time_left = wait_for_completion_timeout(&priv->hp_startup, in cs42l43_stop_load_detect()
585 dev_err(priv->dev, "Load detect HP restore timed out\n"); in cs42l43_stop_load_detect()
588 priv->load_detect_running = false; in cs42l43_stop_load_detect()
590 snd_soc_dapm_mutex_unlock(snd_soc_component_get_dapm(priv->component)); in cs42l43_stop_load_detect()
595 struct cs42l43 *cs42l43 = priv->core; in cs42l43_run_load_detect()
599 reinit_completion(&priv->load_detect); in cs42l43_run_load_detect()
602 time_left = wait_for_completion_timeout(&priv->load_detect, in cs42l43_run_load_detect()
607 return -ETIMEDOUT; in cs42l43_run_load_detect()
609 regmap_read(cs42l43->regmap, CS42L43_LOADDETRESULTS, &val); in cs42l43_run_load_detect()
611 dev_dbg(priv->dev, "Headphone load detect: 0x%x\n", val); in cs42l43_run_load_detect()
615 return -ENODEV; in cs42l43_run_load_detect()
632 return -EINVAL; in cs42l43_run_load_detect()
638 struct cs42l43 *cs42l43 = priv->core; in cs42l43_run_type_detect()
639 int timeout_ms = ((2 * priv->detect_us) / 1000) + 200; in cs42l43_run_type_detect()
643 reinit_completion(&priv->type_detect); in cs42l43_run_type_detect()
646 regmap_update_bits(cs42l43->regmap, CS42L43_HS2, in cs42l43_run_type_detect()
649 time_left = wait_for_completion_timeout(&priv->type_detect, in cs42l43_run_type_detect()
652 regmap_update_bits(cs42l43->regmap, CS42L43_HS2, in cs42l43_run_type_detect()
657 return -ETIMEDOUT; in cs42l43_run_type_detect()
659 regmap_read(cs42l43->regmap, CS42L43_HS_STAT, &type); in cs42l43_run_type_detect()
661 dev_dbg(priv->dev, "Type detect: 0x%x\n", type); in cs42l43_run_type_detect()
665 return -ENODEV; in cs42l43_run_type_detect()
671 case 0x2: // 3-pole in cs42l43_run_type_detect()
673 case 0x3: // Open-circuit in cs42l43_run_type_detect()
676 return -EINVAL; in cs42l43_run_type_detect()
682 struct cs42l43 *cs42l43 = priv->core; in cs42l43_clear_jack()
687 regmap_update_bits(cs42l43->regmap, CS42L43_ADC_B_CTRL1, in cs42l43_clear_jack()
689 regmap_update_bits(cs42l43->regmap, CS42L43_ADC_B_CTRL2, in cs42l43_clear_jack()
691 regmap_update_bits(cs42l43->regmap, CS42L43_STEREO_MIC_CTRL, in cs42l43_clear_jack()
693 regmap_update_bits(cs42l43->regmap, CS42L43_HS2, in cs42l43_clear_jack()
697 snd_soc_jack_report(priv->jack_hp, 0, 0xFFFF); in cs42l43_clear_jack()
704 struct cs42l43 *cs42l43 = priv->core; in cs42l43_tip_sense_work()
706 unsigned int tip, ring; in cs42l43_tip_sense_work() local
709 ret = pm_runtime_resume_and_get(priv->dev); in cs42l43_tip_sense_work()
711 dev_err(priv->dev, "Failed to resume for tip work: %d\n", ret); in cs42l43_tip_sense_work()
715 mutex_lock(&priv->jack_lock); in cs42l43_tip_sense_work()
717 regmap_read(cs42l43->regmap, CS42L43_TIP_RING_SENSE_INTERRUPT_STATUS, &sts); in cs42l43_tip_sense_work()
719 dev_dbg(priv->dev, "Tip sense: 0x%x\n", sts); in cs42l43_tip_sense_work()
722 ring = (sts >> CS42L43_RINGSENSE_PLUG_DB_STS_SHIFT) & CS42L43_JACK_PRESENT; in cs42l43_tip_sense_work()
725 if (cs42l43->sdw && !priv->jack_present) { in cs42l43_tip_sense_work()
726 priv->jack_present = true; in cs42l43_tip_sense_work()
727 pm_runtime_get(priv->dev); in cs42l43_tip_sense_work()
730 if (priv->use_ring_sense && ring == CS42L43_JACK_ABSENT) { in cs42l43_tip_sense_work()
735 dev_err(priv->dev, "Jack detect failed: %d\n", report); in cs42l43_tip_sense_work()
740 snd_soc_jack_report(priv->jack_hp, report, report); in cs42l43_tip_sense_work()
742 priv->jack_override = 0; in cs42l43_tip_sense_work()
746 if (cs42l43->sdw && priv->jack_present) { in cs42l43_tip_sense_work()
747 pm_runtime_put(priv->dev); in cs42l43_tip_sense_work()
748 priv->jack_present = false; in cs42l43_tip_sense_work()
753 mutex_unlock(&priv->jack_lock); in cs42l43_tip_sense_work()
755 pm_runtime_mark_last_busy(priv->dev); in cs42l43_tip_sense_work()
756 pm_runtime_put_autosuspend(priv->dev); in cs42l43_tip_sense_work()
763 cancel_delayed_work(&priv->bias_sense_timeout); in cs42l43_tip_sense()
764 cancel_delayed_work(&priv->tip_sense_work); in cs42l43_tip_sense()
765 cancel_delayed_work(&priv->button_press_work); in cs42l43_tip_sense()
766 cancel_work(&priv->button_release_work); in cs42l43_tip_sense()
768 queue_delayed_work(system_long_wq, &priv->tip_sense_work, in cs42l43_tip_sense()
769 msecs_to_jiffies(priv->tip_debounce_ms)); in cs42l43_tip_sense()
844 "None", "CTIA", "OMTP", "Headphone", "Line-Out",
845 "Line-In", "Microphone", "Optical",
855 mutex_lock(&priv->jack_lock); in cs42l43_jack_get()
856 ucontrol->value.integer.value[0] = priv->jack_override; in cs42l43_jack_get()
857 mutex_unlock(&priv->jack_lock); in cs42l43_jack_get()
866 struct cs42l43 *cs42l43 = priv->core; in cs42l43_jack_put()
867 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; in cs42l43_jack_put()
868 unsigned int override = ucontrol->value.integer.value[0]; in cs42l43_jack_put()
871 ARRAY_SIZE(cs42l43_jack_text) - 1); in cs42l43_jack_put()
873 if (override >= e->items) in cs42l43_jack_put()
874 return -EINVAL; in cs42l43_jack_put()
876 mutex_lock(&priv->jack_lock); in cs42l43_jack_put()
879 mutex_unlock(&priv->jack_lock); in cs42l43_jack_put()
880 return -EBUSY; in cs42l43_jack_put()
883 if (override == priv->jack_override) { in cs42l43_jack_put()
884 mutex_unlock(&priv->jack_lock); in cs42l43_jack_put()
888 priv->jack_override = override; in cs42l43_jack_put()
893 queue_delayed_work(system_long_wq, &priv->tip_sense_work, 0); in cs42l43_jack_put()
895 override--; in cs42l43_jack_put()
897 regmap_update_bits(cs42l43->regmap, CS42L43_HS2, in cs42l43_jack_put()
909 regmap_update_bits(cs42l43->regmap, CS42L43_STEREO_MIC_CTRL, in cs42l43_jack_put()
913 regmap_update_bits(cs42l43->regmap, CS42L43_STEREO_MIC_CLAMP_CTRL, in cs42l43_jack_put()
924 regmap_update_bits(cs42l43->regmap, CS42L43_ADC_B_CTRL1, in cs42l43_jack_put()
927 regmap_update_bits(cs42l43->regmap, CS42L43_ADC_B_CTRL2, in cs42l43_jack_put()
938 snd_soc_jack_report(priv->jack_hp, in cs42l43_jack_put()
943 mutex_unlock(&priv->jack_lock); in cs42l43_jack_put()