static void cs42l42_manual_hs_type_detect(struct cs42l42_private *cs42l42)
{
unsigned int hs_det_status;
- unsigned int hs_det_comp;
+ unsigned int hs_det_comp1;
+ unsigned int hs_det_comp2;
unsigned int hs_det_sw;
/* Set hs detect to manual, active mode */
(0 << CS42L42_HSBIAS_REF_SHIFT) |
(0 << CS42L42_HSDET_AUTO_TIME_SHIFT));
+ /* Configure HS DET comparator reference levels. */
+ regmap_update_bits(cs42l42->regmap,
+ CS42L42_HSDET_CTL1,
+ CS42L42_HSDET_COMP1_LVL_MASK |
+ CS42L42_HSDET_COMP2_LVL_MASK,
+ (CS42L42_HSDET_COMP1_LVL_VAL << CS42L42_HSDET_COMP1_LVL_SHIFT) |
+ (CS42L42_HSDET_COMP2_LVL_VAL << CS42L42_HSDET_COMP2_LVL_SHIFT));
+
/* Open the SW_HSB_HS3 switch and close SW_HSB_HS4 for a Type 1 headset. */
regmap_write(cs42l42->regmap, CS42L42_HS_SWITCH_CTL, CS42L42_HSDET_SW_COMP1);
+ msleep(100);
+
regmap_read(cs42l42->regmap, CS42L42_HS_DET_STATUS, &hs_det_status);
- hs_det_comp = (hs_det_status & CS42L42_HSDET_COMP1_OUT_MASK) >>
+ hs_det_comp1 = (hs_det_status & CS42L42_HSDET_COMP1_OUT_MASK) >>
CS42L42_HSDET_COMP1_OUT_SHIFT;
+ hs_det_comp2 = (hs_det_status & CS42L42_HSDET_COMP2_OUT_MASK) >>
+ CS42L42_HSDET_COMP2_OUT_SHIFT;
/* Close the SW_HSB_HS3 switch for a Type 2 headset. */
regmap_write(cs42l42->regmap, CS42L42_HS_SWITCH_CTL, CS42L42_HSDET_SW_COMP2);
+ msleep(100);
+
regmap_read(cs42l42->regmap, CS42L42_HS_DET_STATUS, &hs_det_status);
- hs_det_comp |= ((hs_det_status & CS42L42_HSDET_COMP2_OUT_MASK) >>
+ hs_det_comp1 |= ((hs_det_status & CS42L42_HSDET_COMP1_OUT_MASK) >>
+ CS42L42_HSDET_COMP1_OUT_SHIFT) << 1;
+ hs_det_comp2 |= ((hs_det_status & CS42L42_HSDET_COMP2_OUT_MASK) >>
CS42L42_HSDET_COMP2_OUT_SHIFT) << 1;
- switch (hs_det_comp) {
+ /* Use Comparator 1 with 1.25V Threshold. */
+ switch (hs_det_comp1) {
case CS42L42_HSDET_COMP_TYPE1:
cs42l42->hs_type = CS42L42_PLUG_CTIA;
hs_det_sw = CS42L42_HSDET_SW_TYPE1;
cs42l42->hs_type = CS42L42_PLUG_OMTP;
hs_det_sw = CS42L42_HSDET_SW_TYPE2;
break;
- case CS42L42_HSDET_COMP_TYPE3:
- cs42l42->hs_type = CS42L42_PLUG_HEADPHONE;
- hs_det_sw = CS42L42_HSDET_SW_TYPE3;
- break;
default:
- cs42l42->hs_type = CS42L42_PLUG_INVALID;
- hs_det_sw = CS42L42_HSDET_SW_TYPE4;
- break;
+ /* Fallback to Comparator 2 with 1.75V Threshold. */
+ switch (hs_det_comp2) {
+ case CS42L42_HSDET_COMP_TYPE1:
+ cs42l42->hs_type = CS42L42_PLUG_CTIA;
+ hs_det_sw = CS42L42_HSDET_SW_TYPE1;
+ break;
+ case CS42L42_HSDET_COMP_TYPE2:
+ cs42l42->hs_type = CS42L42_PLUG_OMTP;
+ hs_det_sw = CS42L42_HSDET_SW_TYPE2;
+ break;
+ case CS42L42_HSDET_COMP_TYPE3:
+ cs42l42->hs_type = CS42L42_PLUG_HEADPHONE;
+ hs_det_sw = CS42L42_HSDET_SW_TYPE3;
+ break;
+ default:
+ cs42l42->hs_type = CS42L42_PLUG_INVALID;
+ hs_det_sw = CS42L42_HSDET_SW_TYPE4;
+ break;
+ }
}
/* Set Switches */
(0 << CS42L42_HSDET_SET_SHIFT) |
(0 << CS42L42_HSBIAS_REF_SHIFT) |
(0 << CS42L42_HSDET_AUTO_TIME_SHIFT));
+
+ /* Configure HS DET comparator reference levels. */
+ regmap_update_bits(cs42l42->regmap,
+ CS42L42_HSDET_CTL1,
+ CS42L42_HSDET_COMP1_LVL_MASK |
+ CS42L42_HSDET_COMP2_LVL_MASK,
+ (CS42L42_HSDET_COMP1_LVL_DEFAULT << CS42L42_HSDET_COMP1_LVL_SHIFT) |
+ (CS42L42_HSDET_COMP2_LVL_DEFAULT << CS42L42_HSDET_COMP2_LVL_SHIFT));
}
static void cs42l42_process_hs_type_detect(struct cs42l42_private *cs42l42)
cs42l42->hs_type = (hs_det_status & CS42L42_HSDET_TYPE_MASK) >>
CS42L42_HSDET_TYPE_SHIFT;
+ /* Set hs detect to automatic, disabled mode */
+ regmap_update_bits(cs42l42->regmap,
+ CS42L42_HSDET_CTL2,
+ CS42L42_HSDET_CTRL_MASK |
+ CS42L42_HSDET_SET_MASK |
+ CS42L42_HSBIAS_REF_MASK |
+ CS42L42_HSDET_AUTO_TIME_MASK,
+ (2 << CS42L42_HSDET_CTRL_SHIFT) |
+ (2 << CS42L42_HSDET_SET_SHIFT) |
+ (0 << CS42L42_HSBIAS_REF_SHIFT) |
+ (3 << CS42L42_HSDET_AUTO_TIME_SHIFT));
+
/* Run Manual detection if auto detect has not found a headset.
* We Re-Run with Manual Detection if the original detection was invalid or headphones,
* to ensure that a headset mic is detected in all cases.
cs42l42->hs_type == CS42L42_PLUG_HEADPHONE) {
dev_dbg(cs42l42->component->dev, "Running Manual Detection Fallback\n");
cs42l42_manual_hs_type_detect(cs42l42);
- } else {
- /* Set hs detect to automatic, disabled mode */
- regmap_update_bits(cs42l42->regmap,
- CS42L42_HSDET_CTL2,
- CS42L42_HSDET_CTRL_MASK |
- CS42L42_HSDET_SET_MASK |
- CS42L42_HSBIAS_REF_MASK |
- CS42L42_HSDET_AUTO_TIME_MASK,
- (2 << CS42L42_HSDET_CTRL_SHIFT) |
- (2 << CS42L42_HSDET_SET_SHIFT) |
- (0 << CS42L42_HSBIAS_REF_SHIFT) |
- (3 << CS42L42_HSDET_AUTO_TIME_SHIFT));
}
/* Set up button detection */