[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20210927111437.18113-1-vitalyr@opensource.cirrus.com>
Date: Mon, 27 Sep 2021 12:14:37 +0100
From: Vitaly Rodionov <vitalyr@...nsource.cirrus.com>
To: James Schulman <james.schulman@...rus.com>,
David Rhodes <david.rhodes@...rus.com>,
Liam Girdwood <lgirdwood@...il.com>,
Mark Brown <broonie@...nel.org>,
Jaroslav Kysela <perex@...ex.cz>, Takashi Iwai <tiwai@...e.com>
CC: <alsa-devel@...a-project.org>, <patches@...nsource.cirrus.com>,
<linux-kernel@...r.kernel.org>,
Stefan Binding <sbinding@...nsource.cirrus.com>
Subject: [PATCH] ASoC: cs42l42: Use two thresholds and increased wait time for manual type detection
From: Stefan Binding <sbinding@...nsource.cirrus.com>
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@...nsource.cirrus.com>
Signed-off-by: Vitaly Rodionov <vitalyr@...nsource.cirrus.com>
---
sound/soc/codecs/cs42l42.c | 84 +++++++++++++++++++++++++++-----------
sound/soc/codecs/cs42l42.h | 5 +++
2 files changed, 66 insertions(+), 23 deletions(-)
diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c
index 78f8c89410b6..3f202acd4a8e 100644
--- a/sound/soc/codecs/cs42l42.c
+++ b/sound/soc/codecs/cs42l42.c
@@ -1048,7 +1048,8 @@ static struct snd_soc_dai_driver cs42l42_dai = {
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 */
@@ -1063,23 +1064,40 @@ static void cs42l42_manual_hs_type_detect(struct cs42l42_private *cs42l42)
(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;
@@ -1088,14 +1106,26 @@ static void cs42l42_manual_hs_type_detect(struct cs42l42_private *cs42l42)
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 */
@@ -1112,6 +1142,14 @@ static void cs42l42_manual_hs_type_detect(struct cs42l42_private *cs42l42)
(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)
@@ -1134,6 +1172,18 @@ 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.
@@ -1142,18 +1192,6 @@ static void cs42l42_process_hs_type_detect(struct cs42l42_private *cs42l42)
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 */
diff --git a/sound/soc/codecs/cs42l42.h b/sound/soc/codecs/cs42l42.h
index 2aeabba73e05..0704c902475f 100644
--- a/sound/soc/codecs/cs42l42.h
+++ b/sound/soc/codecs/cs42l42.h
@@ -188,6 +188,11 @@
#define CS42L42_HSDET_COMP2_LVL_SHIFT 4
#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_AUTO_TIME_SHIFT 0
#define CS42L42_HSDET_AUTO_TIME_MASK (3 << CS42L42_HSDET_AUTO_TIME_SHIFT)
--
2.25.1
Powered by blists - more mailing lists