ASoC: cs42l42: Use two thresholds and increased wait time for manual type detection
Some headsets require very different comparator thresholds for type detection, as well as longer settling times. In order to detect a larger number of headsets, use 2 thresholds to give maximum coverage (1.25V and 1.75V), as well as a longer settling time of 100ms. This will not affect default audotodetect mode and applies to manual mode type detection only. Signed-off-by: Stefan Binding <sbinding@opensource.cirrus.com> Signed-off-by: Vitaly Rodionov <vitalyr@opensource.cirrus.com> Link: https://lore.kernel.org/r/20210927111437.18113-1-vitalyr@opensource.cirrus.com Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
9943ab72fd
commit
edd6dffdc6
|
@ -1049,7 +1049,8 @@ static struct snd_soc_dai_driver cs42l42_dai = {
|
||||||
static void cs42l42_manual_hs_type_detect(struct cs42l42_private *cs42l42)
|
static void cs42l42_manual_hs_type_detect(struct cs42l42_private *cs42l42)
|
||||||
{
|
{
|
||||||
unsigned int hs_det_status;
|
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;
|
unsigned int hs_det_sw;
|
||||||
|
|
||||||
/* Set hs detect to manual, active mode */
|
/* Set hs detect to manual, active mode */
|
||||||
|
@ -1064,23 +1065,51 @@ static void cs42l42_manual_hs_type_detect(struct cs42l42_private *cs42l42)
|
||||||
(0 << CS42L42_HSBIAS_REF_SHIFT) |
|
(0 << CS42L42_HSBIAS_REF_SHIFT) |
|
||||||
(0 << CS42L42_HSDET_AUTO_TIME_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. */
|
/* 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);
|
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);
|
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;
|
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. */
|
/* Close the SW_HSB_HS3 switch for a Type 2 headset. */
|
||||||
regmap_write(cs42l42->regmap, CS42L42_HS_SWITCH_CTL, CS42L42_HSDET_SW_COMP2);
|
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);
|
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;
|
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;
|
||||||
|
break;
|
||||||
|
case CS42L42_HSDET_COMP_TYPE2:
|
||||||
|
cs42l42->hs_type = CS42L42_PLUG_OMTP;
|
||||||
|
hs_det_sw = CS42L42_HSDET_SW_TYPE2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Fallback to Comparator 2 with 1.75V Threshold. */
|
||||||
|
switch (hs_det_comp2) {
|
||||||
case CS42L42_HSDET_COMP_TYPE1:
|
case CS42L42_HSDET_COMP_TYPE1:
|
||||||
cs42l42->hs_type = CS42L42_PLUG_CTIA;
|
cs42l42->hs_type = CS42L42_PLUG_CTIA;
|
||||||
hs_det_sw = CS42L42_HSDET_SW_TYPE1;
|
hs_det_sw = CS42L42_HSDET_SW_TYPE1;
|
||||||
|
@ -1098,6 +1127,7 @@ static void cs42l42_manual_hs_type_detect(struct cs42l42_private *cs42l42)
|
||||||
hs_det_sw = CS42L42_HSDET_SW_TYPE4;
|
hs_det_sw = CS42L42_HSDET_SW_TYPE4;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Set Switches */
|
/* Set Switches */
|
||||||
regmap_write(cs42l42->regmap, CS42L42_HS_SWITCH_CTL, hs_det_sw);
|
regmap_write(cs42l42->regmap, CS42L42_HS_SWITCH_CTL, hs_det_sw);
|
||||||
|
@ -1113,6 +1143,14 @@ static void cs42l42_manual_hs_type_detect(struct cs42l42_private *cs42l42)
|
||||||
(0 << CS42L42_HSDET_SET_SHIFT) |
|
(0 << CS42L42_HSDET_SET_SHIFT) |
|
||||||
(0 << CS42L42_HSBIAS_REF_SHIFT) |
|
(0 << CS42L42_HSBIAS_REF_SHIFT) |
|
||||||
(0 << CS42L42_HSDET_AUTO_TIME_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)
|
static void cs42l42_process_hs_type_detect(struct cs42l42_private *cs42l42)
|
||||||
|
@ -1135,15 +1173,6 @@ static void cs42l42_process_hs_type_detect(struct cs42l42_private *cs42l42)
|
||||||
cs42l42->hs_type = (hs_det_status & CS42L42_HSDET_TYPE_MASK) >>
|
cs42l42->hs_type = (hs_det_status & CS42L42_HSDET_TYPE_MASK) >>
|
||||||
CS42L42_HSDET_TYPE_SHIFT;
|
CS42L42_HSDET_TYPE_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.
|
|
||||||
*/
|
|
||||||
if (cs42l42->hs_type == CS42L42_PLUG_INVALID ||
|
|
||||||
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 */
|
/* Set hs detect to automatic, disabled mode */
|
||||||
regmap_update_bits(cs42l42->regmap,
|
regmap_update_bits(cs42l42->regmap,
|
||||||
CS42L42_HSDET_CTL2,
|
CS42L42_HSDET_CTL2,
|
||||||
|
@ -1155,6 +1184,15 @@ static void cs42l42_process_hs_type_detect(struct cs42l42_private *cs42l42)
|
||||||
(2 << CS42L42_HSDET_SET_SHIFT) |
|
(2 << CS42L42_HSDET_SET_SHIFT) |
|
||||||
(0 << CS42L42_HSBIAS_REF_SHIFT) |
|
(0 << CS42L42_HSBIAS_REF_SHIFT) |
|
||||||
(3 << CS42L42_HSDET_AUTO_TIME_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.
|
||||||
|
*/
|
||||||
|
if (cs42l42->hs_type == CS42L42_PLUG_INVALID ||
|
||||||
|
cs42l42->hs_type == CS42L42_PLUG_HEADPHONE) {
|
||||||
|
dev_dbg(cs42l42->component->dev, "Running Manual Detection Fallback\n");
|
||||||
|
cs42l42_manual_hs_type_detect(cs42l42);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set up button detection */
|
/* Set up button detection */
|
||||||
|
|
|
@ -188,6 +188,11 @@
|
||||||
#define CS42L42_HSDET_COMP2_LVL_SHIFT 4
|
#define CS42L42_HSDET_COMP2_LVL_SHIFT 4
|
||||||
#define CS42L42_HSDET_COMP2_LVL_MASK (15 << CS42L42_HSDET_COMP2_LVL_SHIFT)
|
#define CS42L42_HSDET_COMP2_LVL_MASK (15 << CS42L42_HSDET_COMP2_LVL_SHIFT)
|
||||||
|
|
||||||
|
#define CS42L42_HSDET_COMP1_LVL_VAL 12 /* 1.25V Comparator */
|
||||||
|
#define CS42L42_HSDET_COMP2_LVL_VAL 2 /* 1.75V Comparator */
|
||||||
|
#define CS42L42_HSDET_COMP1_LVL_DEFAULT 7 /* 1V Comparator */
|
||||||
|
#define CS42L42_HSDET_COMP2_LVL_DEFAULT 7 /* 2V Comparator */
|
||||||
|
|
||||||
#define CS42L42_HSDET_CTL2 (CS42L42_PAGE_11 + 0x20)
|
#define CS42L42_HSDET_CTL2 (CS42L42_PAGE_11 + 0x20)
|
||||||
#define CS42L42_HSDET_AUTO_TIME_SHIFT 0
|
#define CS42L42_HSDET_AUTO_TIME_SHIFT 0
|
||||||
#define CS42L42_HSDET_AUTO_TIME_MASK (3 << CS42L42_HSDET_AUTO_TIME_SHIFT)
|
#define CS42L42_HSDET_AUTO_TIME_MASK (3 << CS42L42_HSDET_AUTO_TIME_SHIFT)
|
||||||
|
|
Loading…
Reference in New Issue