All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] ASoC: cs42l42: Implement Manual Type detection as fallback
@ 2021-09-14 16:52 ` Vitaly Rodionov
  0 siblings, 0 replies; 10+ messages in thread
From: Vitaly Rodionov @ 2021-09-14 16:52 UTC (permalink / raw)
  To: James Schulman, David Rhodes, Liam Girdwood, Mark Brown,
	Jaroslav Kysela, Takashi Iwai
  Cc: alsa-devel, patches, linux-kernel

For some headsets CS42L42 autodetect mode is not working correctly. 
They will be detected as unknown types or as headphones. According 
to the CS42L42 datasheet, if the headset autodetect failed,
then the driver should switch to manual mode and perform a manual steps sequence.
These steps were missing in the current driver code. This patch will add manual
mode fallback steps in case autodetect failed. The default behavior is not affected,
manual mode runs only when autodetect failed.

Tested for regression with autodetect with all known headsets - no regression.
Tested with all headsets customers reported as false detected:
Gumdrop DropTech B1 - detected as headset OK
HUAWEI AM115 - detected as headset OK
UGREEN EP103 - detected as headset OK
HONOR AM116 - detected as headset OK

Also, fixes some errors reported by checkpatch.pl script.

Stefan Binding (1):
  ASoC: cs42l42: Implement Manual Type detection as fallback

Vitaly Rodionov (1):
  ASoC: cs42l42: Minor fix all errors reported by checkpatch.pl script

 sound/soc/codecs/cs42l42.c | 114 +++++++++++++++++++++++++++++++------
 sound/soc/codecs/cs42l42.h |  54 ++++++++++++++++++
 2 files changed, 151 insertions(+), 17 deletions(-)

-- 
2.25.1


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 0/2] ASoC: cs42l42: Implement Manual Type detection as fallback
@ 2021-09-14 16:52 ` Vitaly Rodionov
  0 siblings, 0 replies; 10+ messages in thread
From: Vitaly Rodionov @ 2021-09-14 16:52 UTC (permalink / raw)
  To: James Schulman, David Rhodes, Liam Girdwood, Mark Brown,
	Jaroslav Kysela, Takashi Iwai
  Cc: patches, alsa-devel, linux-kernel

For some headsets CS42L42 autodetect mode is not working correctly. 
They will be detected as unknown types or as headphones. According 
to the CS42L42 datasheet, if the headset autodetect failed,
then the driver should switch to manual mode and perform a manual steps sequence.
These steps were missing in the current driver code. This patch will add manual
mode fallback steps in case autodetect failed. The default behavior is not affected,
manual mode runs only when autodetect failed.

Tested for regression with autodetect with all known headsets - no regression.
Tested with all headsets customers reported as false detected:
Gumdrop DropTech B1 - detected as headset OK
HUAWEI AM115 - detected as headset OK
UGREEN EP103 - detected as headset OK
HONOR AM116 - detected as headset OK

Also, fixes some errors reported by checkpatch.pl script.

Stefan Binding (1):
  ASoC: cs42l42: Implement Manual Type detection as fallback

Vitaly Rodionov (1):
  ASoC: cs42l42: Minor fix all errors reported by checkpatch.pl script

 sound/soc/codecs/cs42l42.c | 114 +++++++++++++++++++++++++++++++------
 sound/soc/codecs/cs42l42.h |  54 ++++++++++++++++++
 2 files changed, 151 insertions(+), 17 deletions(-)

-- 
2.25.1


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/2] ASoC: cs42l42: Minor fix all errors reported by checkpatch.pl script
  2021-09-14 16:52 ` Vitaly Rodionov
@ 2021-09-14 16:52   ` Vitaly Rodionov
  -1 siblings, 0 replies; 10+ messages in thread
From: Vitaly Rodionov @ 2021-09-14 16:52 UTC (permalink / raw)
  To: James Schulman, David Rhodes, Liam Girdwood, Mark Brown,
	Jaroslav Kysela, Takashi Iwai
  Cc: alsa-devel, patches, linux-kernel

Signed-off-by: Vitaly Rodionov <vitalyr@opensource.cirrus.com>
---
 sound/soc/codecs/cs42l42.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c
index fb1e4c33e27d..ca76d907da52 100644
--- a/sound/soc/codecs/cs42l42.c
+++ b/sound/soc/codecs/cs42l42.c
@@ -851,7 +851,7 @@ static int cs42l42_pcm_hw_params(struct snd_pcm_substream *substream,
 	if (params_width(params) == 24)
 		cs42l42->bclk = (cs42l42->bclk / 3) * 4;
 
-	switch(substream->stream) {
+	switch (substream->stream) {
 	case SNDRV_PCM_STREAM_CAPTURE:
 		if (channels == 2) {
 			val |= CS42L42_ASP_TX_CH2_AP_MASK;
@@ -935,7 +935,7 @@ static int cs42l42_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
 						      CS42L42_HP_ANA_BMUTE_MASK);
 
 		cs42l42->stream_use &= ~(1 << stream);
-		if(!cs42l42->stream_use) {
+		if (!cs42l42->stream_use) {
 			/*
 			 * Switch to the internal oscillator.
 			 * SCLK must remain running until after this clock switch.
@@ -1015,7 +1015,7 @@ static int cs42l42_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
 
 #define CS42L42_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
 			 SNDRV_PCM_FMTBIT_S24_LE |\
-			 SNDRV_PCM_FMTBIT_S32_LE )
+			 SNDRV_PCM_FMTBIT_S32_LE)
 
 static const struct snd_soc_dai_ops cs42l42_ops = {
 	.startup	= cs42l42_dai_startup,
@@ -1492,7 +1492,7 @@ static irqreturn_t cs42l42_irq_thread(int irq, void *data)
 	if ((~masks[5]) & irq_params_table[5].mask) {
 		if (stickies[5] & CS42L42_HSDET_AUTO_DONE_MASK) {
 			cs42l42_process_hs_type_detect(cs42l42);
-			switch(cs42l42->hs_type){
+			switch (cs42l42->hs_type) {
 			case CS42L42_PLUG_CTIA:
 			case CS42L42_PLUG_OMTP:
 				snd_soc_jack_report(cs42l42->jack, SND_JACK_HEADSET,
@@ -1524,7 +1524,7 @@ static irqreturn_t cs42l42_irq_thread(int irq, void *data)
 				cs42l42->plug_state = CS42L42_TS_UNPLUG;
 				cs42l42_cancel_hs_type_detect(cs42l42);
 
-				switch(cs42l42->hs_type){
+				switch (cs42l42->hs_type) {
 				case CS42L42_PLUG_CTIA:
 				case CS42L42_PLUG_OMTP:
 					snd_soc_jack_report(cs42l42->jack, 0, SND_JACK_HEADSET);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 1/2] ASoC: cs42l42: Minor fix all errors reported by checkpatch.pl script
@ 2021-09-14 16:52   ` Vitaly Rodionov
  0 siblings, 0 replies; 10+ messages in thread
From: Vitaly Rodionov @ 2021-09-14 16:52 UTC (permalink / raw)
  To: James Schulman, David Rhodes, Liam Girdwood, Mark Brown,
	Jaroslav Kysela, Takashi Iwai
  Cc: patches, alsa-devel, linux-kernel

Signed-off-by: Vitaly Rodionov <vitalyr@opensource.cirrus.com>
---
 sound/soc/codecs/cs42l42.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c
index fb1e4c33e27d..ca76d907da52 100644
--- a/sound/soc/codecs/cs42l42.c
+++ b/sound/soc/codecs/cs42l42.c
@@ -851,7 +851,7 @@ static int cs42l42_pcm_hw_params(struct snd_pcm_substream *substream,
 	if (params_width(params) == 24)
 		cs42l42->bclk = (cs42l42->bclk / 3) * 4;
 
-	switch(substream->stream) {
+	switch (substream->stream) {
 	case SNDRV_PCM_STREAM_CAPTURE:
 		if (channels == 2) {
 			val |= CS42L42_ASP_TX_CH2_AP_MASK;
@@ -935,7 +935,7 @@ static int cs42l42_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
 						      CS42L42_HP_ANA_BMUTE_MASK);
 
 		cs42l42->stream_use &= ~(1 << stream);
-		if(!cs42l42->stream_use) {
+		if (!cs42l42->stream_use) {
 			/*
 			 * Switch to the internal oscillator.
 			 * SCLK must remain running until after this clock switch.
@@ -1015,7 +1015,7 @@ static int cs42l42_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
 
 #define CS42L42_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
 			 SNDRV_PCM_FMTBIT_S24_LE |\
-			 SNDRV_PCM_FMTBIT_S32_LE )
+			 SNDRV_PCM_FMTBIT_S32_LE)
 
 static const struct snd_soc_dai_ops cs42l42_ops = {
 	.startup	= cs42l42_dai_startup,
@@ -1492,7 +1492,7 @@ static irqreturn_t cs42l42_irq_thread(int irq, void *data)
 	if ((~masks[5]) & irq_params_table[5].mask) {
 		if (stickies[5] & CS42L42_HSDET_AUTO_DONE_MASK) {
 			cs42l42_process_hs_type_detect(cs42l42);
-			switch(cs42l42->hs_type){
+			switch (cs42l42->hs_type) {
 			case CS42L42_PLUG_CTIA:
 			case CS42L42_PLUG_OMTP:
 				snd_soc_jack_report(cs42l42->jack, SND_JACK_HEADSET,
@@ -1524,7 +1524,7 @@ static irqreturn_t cs42l42_irq_thread(int irq, void *data)
 				cs42l42->plug_state = CS42L42_TS_UNPLUG;
 				cs42l42_cancel_hs_type_detect(cs42l42);
 
-				switch(cs42l42->hs_type){
+				switch (cs42l42->hs_type) {
 				case CS42L42_PLUG_CTIA:
 				case CS42L42_PLUG_OMTP:
 					snd_soc_jack_report(cs42l42->jack, 0, SND_JACK_HEADSET);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 2/2] ASoC: cs42l42: Implement Manual Type detection as fallback
  2021-09-14 16:52 ` Vitaly Rodionov
@ 2021-09-14 16:52   ` Vitaly Rodionov
  -1 siblings, 0 replies; 10+ messages in thread
From: Vitaly Rodionov @ 2021-09-14 16:52 UTC (permalink / raw)
  To: James Schulman, David Rhodes, Liam Girdwood, Mark Brown,
	Jaroslav Kysela, Takashi Iwai
  Cc: alsa-devel, patches, linux-kernel, Stefan Binding

From: Stefan Binding <sbinding@opensource.cirrus.com>

Some headsets are not detected correctly by Automatic Type Detection
on cs42l42. Instead, Manual Type Detection can be used to give a
more accurate value.

Signed-off-by: Stefan Binding <sbinding@opensource.cirrus.com>
Signed-off-by: Vitaly Rodionov <vitalyr@opensource.cirrus.com>
---
 sound/soc/codecs/cs42l42.c | 104 ++++++++++++++++++++++++++++++++-----
 sound/soc/codecs/cs42l42.h |  54 +++++++++++++++++++
 2 files changed, 146 insertions(+), 12 deletions(-)

diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c
index ca76d907da52..d5e1e5228b5f 100644
--- a/sound/soc/codecs/cs42l42.c
+++ b/sound/soc/codecs/cs42l42.c
@@ -1046,37 +1046,117 @@ static struct snd_soc_dai_driver cs42l42_dai = {
 		.ops = &cs42l42_ops,
 };
 
-static void cs42l42_process_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 int_status;
+	unsigned int hs_det_comp;
+	unsigned int hs_det_sw;
 
-	/* Mask the auto detect interrupt */
+	/* Set hs detect to manual, active mode */
 	regmap_update_bits(cs42l42->regmap,
-		CS42L42_CODEC_INT_MASK,
-		CS42L42_PDN_DONE_MASK |
-		CS42L42_HSDET_AUTO_DONE_MASK,
-		(1 << CS42L42_PDN_DONE_SHIFT) |
-		(1 << CS42L42_HSDET_AUTO_DONE_SHIFT));
+		CS42L42_HSDET_CTL2,
+		CS42L42_HSDET_CTRL_MASK |
+		CS42L42_HSDET_SET_MASK |
+		CS42L42_HSBIAS_REF_MASK |
+		CS42L42_HSDET_AUTO_TIME_MASK,
+		(1 << CS42L42_HSDET_CTRL_SHIFT) |
+		(0 << CS42L42_HSDET_SET_SHIFT) |
+		(0 << CS42L42_HSBIAS_REF_SHIFT) |
+		(0 << CS42L42_HSDET_AUTO_TIME_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);
+
+	regmap_read(cs42l42->regmap, CS42L42_HS_DET_STATUS, &hs_det_status);
+
+	hs_det_comp = (hs_det_status & CS42L42_HSDET_COMP1_OUT_MASK) >>
+			CS42L42_HSDET_COMP1_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);
+
+	regmap_read(cs42l42->regmap, CS42L42_HS_DET_STATUS, &hs_det_status);
+
+	hs_det_comp |= ((hs_det_status & CS42L42_HSDET_COMP2_OUT_MASK) >>
+			CS42L42_HSDET_COMP2_OUT_SHIFT) << 1;
+
+	switch (hs_det_comp) {
+	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 hs detect to automatic, disabled mode */
+	/* Set Switches */
+	regmap_write(cs42l42->regmap, CS42L42_HS_SWITCH_CTL, hs_det_sw);
+
+	/* Set HSDET mode to Manual—Disabled */
 	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_HSDET_CTRL_SHIFT) |
+		(0 << CS42L42_HSDET_SET_SHIFT) |
 		(0 << CS42L42_HSBIAS_REF_SHIFT) |
-		(3 << CS42L42_HSDET_AUTO_TIME_SHIFT));
+		(0 << CS42L42_HSDET_AUTO_TIME_SHIFT));
+}
+
+static void cs42l42_process_hs_type_detect(struct cs42l42_private *cs42l42)
+{
+	unsigned int hs_det_status;
+	unsigned int int_status;
 
 	/* Read and save the hs detection result */
 	regmap_read(cs42l42->regmap, CS42L42_HS_DET_STATUS, &hs_det_status);
 
+	/* Mask the auto detect interrupt */
+	regmap_update_bits(cs42l42->regmap,
+		CS42L42_CODEC_INT_MASK,
+		CS42L42_PDN_DONE_MASK |
+		CS42L42_HSDET_AUTO_DONE_MASK,
+		(1 << CS42L42_PDN_DONE_SHIFT) |
+		(1 << CS42L42_HSDET_AUTO_DONE_SHIFT));
+
+
 	cs42l42->hs_type = (hs_det_status & CS42L42_HSDET_TYPE_MASK) >>
 				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 */
+		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 */
 	if ((cs42l42->hs_type == CS42L42_PLUG_CTIA) ||
 	      (cs42l42->hs_type == CS42L42_PLUG_OMTP)) {
diff --git a/sound/soc/codecs/cs42l42.h b/sound/soc/codecs/cs42l42.h
index 8734f6828f3e..2aeabba73e05 100644
--- a/sound/soc/codecs/cs42l42.h
+++ b/sound/soc/codecs/cs42l42.h
@@ -228,6 +228,60 @@
 #define CS42L42_PLUG_HEADPHONE		2
 #define CS42L42_PLUG_INVALID		3
 
+#define CS42L42_HSDET_SW_COMP1		((0 << CS42L42_SW_GNDHS_HS4_SHIFT) | \
+					 (1 << CS42L42_SW_GNDHS_HS3_SHIFT) | \
+					 (1 << CS42L42_SW_HSB_HS4_SHIFT) | \
+					 (0 << CS42L42_SW_HSB_HS3_SHIFT) | \
+					 (0 << CS42L42_SW_HSB_FILT_HS4_SHIFT) | \
+					 (1 << CS42L42_SW_HSB_FILT_HS3_SHIFT) | \
+					 (0 << CS42L42_SW_REF_HS4_SHIFT) | \
+					 (1 << CS42L42_SW_REF_HS3_SHIFT))
+#define CS42L42_HSDET_SW_COMP2		((1 << CS42L42_SW_GNDHS_HS4_SHIFT) | \
+					 (0 << CS42L42_SW_GNDHS_HS3_SHIFT) | \
+					 (0 << CS42L42_SW_HSB_HS4_SHIFT) | \
+					 (1 << CS42L42_SW_HSB_HS3_SHIFT) | \
+					 (1 << CS42L42_SW_HSB_FILT_HS4_SHIFT) | \
+					 (0 << CS42L42_SW_HSB_FILT_HS3_SHIFT) | \
+					 (1 << CS42L42_SW_REF_HS4_SHIFT) | \
+					 (0 << CS42L42_SW_REF_HS3_SHIFT))
+#define CS42L42_HSDET_SW_TYPE1		((0 << CS42L42_SW_GNDHS_HS4_SHIFT) | \
+					 (1 << CS42L42_SW_GNDHS_HS3_SHIFT) | \
+					 (1 << CS42L42_SW_HSB_HS4_SHIFT) | \
+					 (0 << CS42L42_SW_HSB_HS3_SHIFT) | \
+					 (0 << CS42L42_SW_HSB_FILT_HS4_SHIFT) | \
+					 (1 << CS42L42_SW_HSB_FILT_HS3_SHIFT) | \
+					 (0 << CS42L42_SW_REF_HS4_SHIFT) | \
+					 (1 << CS42L42_SW_REF_HS3_SHIFT))
+#define CS42L42_HSDET_SW_TYPE2		((1 << CS42L42_SW_GNDHS_HS4_SHIFT) | \
+					 (0 << CS42L42_SW_GNDHS_HS3_SHIFT) | \
+					 (0 << CS42L42_SW_HSB_HS4_SHIFT) | \
+					 (1 << CS42L42_SW_HSB_HS3_SHIFT) | \
+					 (1 << CS42L42_SW_HSB_FILT_HS4_SHIFT) | \
+					 (0 << CS42L42_SW_HSB_FILT_HS3_SHIFT) | \
+					 (1 << CS42L42_SW_REF_HS4_SHIFT) | \
+					 (0 << CS42L42_SW_REF_HS3_SHIFT))
+#define CS42L42_HSDET_SW_TYPE3		((1 << CS42L42_SW_GNDHS_HS4_SHIFT) | \
+					 (1 << CS42L42_SW_GNDHS_HS3_SHIFT) | \
+					 (0 << CS42L42_SW_HSB_HS4_SHIFT) | \
+					 (0 << CS42L42_SW_HSB_HS3_SHIFT) | \
+					 (1 << CS42L42_SW_HSB_FILT_HS4_SHIFT) | \
+					 (1 << CS42L42_SW_HSB_FILT_HS3_SHIFT) | \
+					 (1 << CS42L42_SW_REF_HS4_SHIFT) | \
+					 (1 << CS42L42_SW_REF_HS3_SHIFT))
+#define CS42L42_HSDET_SW_TYPE4		((0 << CS42L42_SW_GNDHS_HS4_SHIFT) | \
+					 (1 << CS42L42_SW_GNDHS_HS3_SHIFT) | \
+					 (1 << CS42L42_SW_HSB_HS4_SHIFT) | \
+					 (0 << CS42L42_SW_HSB_HS3_SHIFT) | \
+					 (0 << CS42L42_SW_HSB_FILT_HS4_SHIFT) | \
+					 (1 << CS42L42_SW_HSB_FILT_HS3_SHIFT) | \
+					 (0 << CS42L42_SW_REF_HS4_SHIFT) | \
+					 (1 << CS42L42_SW_REF_HS3_SHIFT))
+
+#define CS42L42_HSDET_COMP_TYPE1	1
+#define CS42L42_HSDET_COMP_TYPE2	2
+#define CS42L42_HSDET_COMP_TYPE3	0
+#define CS42L42_HSDET_COMP_TYPE4	3
+
 #define CS42L42_HS_CLAMP_DISABLE	(CS42L42_PAGE_11 + 0x29)
 #define CS42L42_HS_CLAMP_DISABLE_SHIFT	0
 #define CS42L42_HS_CLAMP_DISABLE_MASK	(1 << CS42L42_HS_CLAMP_DISABLE_SHIFT)
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 2/2] ASoC: cs42l42: Implement Manual Type detection as fallback
@ 2021-09-14 16:52   ` Vitaly Rodionov
  0 siblings, 0 replies; 10+ messages in thread
From: Vitaly Rodionov @ 2021-09-14 16:52 UTC (permalink / raw)
  To: James Schulman, David Rhodes, Liam Girdwood, Mark Brown,
	Jaroslav Kysela, Takashi Iwai
  Cc: patches, alsa-devel, linux-kernel, Stefan Binding

From: Stefan Binding <sbinding@opensource.cirrus.com>

Some headsets are not detected correctly by Automatic Type Detection
on cs42l42. Instead, Manual Type Detection can be used to give a
more accurate value.

Signed-off-by: Stefan Binding <sbinding@opensource.cirrus.com>
Signed-off-by: Vitaly Rodionov <vitalyr@opensource.cirrus.com>
---
 sound/soc/codecs/cs42l42.c | 104 ++++++++++++++++++++++++++++++++-----
 sound/soc/codecs/cs42l42.h |  54 +++++++++++++++++++
 2 files changed, 146 insertions(+), 12 deletions(-)

diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c
index ca76d907da52..d5e1e5228b5f 100644
--- a/sound/soc/codecs/cs42l42.c
+++ b/sound/soc/codecs/cs42l42.c
@@ -1046,37 +1046,117 @@ static struct snd_soc_dai_driver cs42l42_dai = {
 		.ops = &cs42l42_ops,
 };
 
-static void cs42l42_process_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 int_status;
+	unsigned int hs_det_comp;
+	unsigned int hs_det_sw;
 
-	/* Mask the auto detect interrupt */
+	/* Set hs detect to manual, active mode */
 	regmap_update_bits(cs42l42->regmap,
-		CS42L42_CODEC_INT_MASK,
-		CS42L42_PDN_DONE_MASK |
-		CS42L42_HSDET_AUTO_DONE_MASK,
-		(1 << CS42L42_PDN_DONE_SHIFT) |
-		(1 << CS42L42_HSDET_AUTO_DONE_SHIFT));
+		CS42L42_HSDET_CTL2,
+		CS42L42_HSDET_CTRL_MASK |
+		CS42L42_HSDET_SET_MASK |
+		CS42L42_HSBIAS_REF_MASK |
+		CS42L42_HSDET_AUTO_TIME_MASK,
+		(1 << CS42L42_HSDET_CTRL_SHIFT) |
+		(0 << CS42L42_HSDET_SET_SHIFT) |
+		(0 << CS42L42_HSBIAS_REF_SHIFT) |
+		(0 << CS42L42_HSDET_AUTO_TIME_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);
+
+	regmap_read(cs42l42->regmap, CS42L42_HS_DET_STATUS, &hs_det_status);
+
+	hs_det_comp = (hs_det_status & CS42L42_HSDET_COMP1_OUT_MASK) >>
+			CS42L42_HSDET_COMP1_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);
+
+	regmap_read(cs42l42->regmap, CS42L42_HS_DET_STATUS, &hs_det_status);
+
+	hs_det_comp |= ((hs_det_status & CS42L42_HSDET_COMP2_OUT_MASK) >>
+			CS42L42_HSDET_COMP2_OUT_SHIFT) << 1;
+
+	switch (hs_det_comp) {
+	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 hs detect to automatic, disabled mode */
+	/* Set Switches */
+	regmap_write(cs42l42->regmap, CS42L42_HS_SWITCH_CTL, hs_det_sw);
+
+	/* Set HSDET mode to Manual—Disabled */
 	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_HSDET_CTRL_SHIFT) |
+		(0 << CS42L42_HSDET_SET_SHIFT) |
 		(0 << CS42L42_HSBIAS_REF_SHIFT) |
-		(3 << CS42L42_HSDET_AUTO_TIME_SHIFT));
+		(0 << CS42L42_HSDET_AUTO_TIME_SHIFT));
+}
+
+static void cs42l42_process_hs_type_detect(struct cs42l42_private *cs42l42)
+{
+	unsigned int hs_det_status;
+	unsigned int int_status;
 
 	/* Read and save the hs detection result */
 	regmap_read(cs42l42->regmap, CS42L42_HS_DET_STATUS, &hs_det_status);
 
+	/* Mask the auto detect interrupt */
+	regmap_update_bits(cs42l42->regmap,
+		CS42L42_CODEC_INT_MASK,
+		CS42L42_PDN_DONE_MASK |
+		CS42L42_HSDET_AUTO_DONE_MASK,
+		(1 << CS42L42_PDN_DONE_SHIFT) |
+		(1 << CS42L42_HSDET_AUTO_DONE_SHIFT));
+
+
 	cs42l42->hs_type = (hs_det_status & CS42L42_HSDET_TYPE_MASK) >>
 				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 */
+		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 */
 	if ((cs42l42->hs_type == CS42L42_PLUG_CTIA) ||
 	      (cs42l42->hs_type == CS42L42_PLUG_OMTP)) {
diff --git a/sound/soc/codecs/cs42l42.h b/sound/soc/codecs/cs42l42.h
index 8734f6828f3e..2aeabba73e05 100644
--- a/sound/soc/codecs/cs42l42.h
+++ b/sound/soc/codecs/cs42l42.h
@@ -228,6 +228,60 @@
 #define CS42L42_PLUG_HEADPHONE		2
 #define CS42L42_PLUG_INVALID		3
 
+#define CS42L42_HSDET_SW_COMP1		((0 << CS42L42_SW_GNDHS_HS4_SHIFT) | \
+					 (1 << CS42L42_SW_GNDHS_HS3_SHIFT) | \
+					 (1 << CS42L42_SW_HSB_HS4_SHIFT) | \
+					 (0 << CS42L42_SW_HSB_HS3_SHIFT) | \
+					 (0 << CS42L42_SW_HSB_FILT_HS4_SHIFT) | \
+					 (1 << CS42L42_SW_HSB_FILT_HS3_SHIFT) | \
+					 (0 << CS42L42_SW_REF_HS4_SHIFT) | \
+					 (1 << CS42L42_SW_REF_HS3_SHIFT))
+#define CS42L42_HSDET_SW_COMP2		((1 << CS42L42_SW_GNDHS_HS4_SHIFT) | \
+					 (0 << CS42L42_SW_GNDHS_HS3_SHIFT) | \
+					 (0 << CS42L42_SW_HSB_HS4_SHIFT) | \
+					 (1 << CS42L42_SW_HSB_HS3_SHIFT) | \
+					 (1 << CS42L42_SW_HSB_FILT_HS4_SHIFT) | \
+					 (0 << CS42L42_SW_HSB_FILT_HS3_SHIFT) | \
+					 (1 << CS42L42_SW_REF_HS4_SHIFT) | \
+					 (0 << CS42L42_SW_REF_HS3_SHIFT))
+#define CS42L42_HSDET_SW_TYPE1		((0 << CS42L42_SW_GNDHS_HS4_SHIFT) | \
+					 (1 << CS42L42_SW_GNDHS_HS3_SHIFT) | \
+					 (1 << CS42L42_SW_HSB_HS4_SHIFT) | \
+					 (0 << CS42L42_SW_HSB_HS3_SHIFT) | \
+					 (0 << CS42L42_SW_HSB_FILT_HS4_SHIFT) | \
+					 (1 << CS42L42_SW_HSB_FILT_HS3_SHIFT) | \
+					 (0 << CS42L42_SW_REF_HS4_SHIFT) | \
+					 (1 << CS42L42_SW_REF_HS3_SHIFT))
+#define CS42L42_HSDET_SW_TYPE2		((1 << CS42L42_SW_GNDHS_HS4_SHIFT) | \
+					 (0 << CS42L42_SW_GNDHS_HS3_SHIFT) | \
+					 (0 << CS42L42_SW_HSB_HS4_SHIFT) | \
+					 (1 << CS42L42_SW_HSB_HS3_SHIFT) | \
+					 (1 << CS42L42_SW_HSB_FILT_HS4_SHIFT) | \
+					 (0 << CS42L42_SW_HSB_FILT_HS3_SHIFT) | \
+					 (1 << CS42L42_SW_REF_HS4_SHIFT) | \
+					 (0 << CS42L42_SW_REF_HS3_SHIFT))
+#define CS42L42_HSDET_SW_TYPE3		((1 << CS42L42_SW_GNDHS_HS4_SHIFT) | \
+					 (1 << CS42L42_SW_GNDHS_HS3_SHIFT) | \
+					 (0 << CS42L42_SW_HSB_HS4_SHIFT) | \
+					 (0 << CS42L42_SW_HSB_HS3_SHIFT) | \
+					 (1 << CS42L42_SW_HSB_FILT_HS4_SHIFT) | \
+					 (1 << CS42L42_SW_HSB_FILT_HS3_SHIFT) | \
+					 (1 << CS42L42_SW_REF_HS4_SHIFT) | \
+					 (1 << CS42L42_SW_REF_HS3_SHIFT))
+#define CS42L42_HSDET_SW_TYPE4		((0 << CS42L42_SW_GNDHS_HS4_SHIFT) | \
+					 (1 << CS42L42_SW_GNDHS_HS3_SHIFT) | \
+					 (1 << CS42L42_SW_HSB_HS4_SHIFT) | \
+					 (0 << CS42L42_SW_HSB_HS3_SHIFT) | \
+					 (0 << CS42L42_SW_HSB_FILT_HS4_SHIFT) | \
+					 (1 << CS42L42_SW_HSB_FILT_HS3_SHIFT) | \
+					 (0 << CS42L42_SW_REF_HS4_SHIFT) | \
+					 (1 << CS42L42_SW_REF_HS3_SHIFT))
+
+#define CS42L42_HSDET_COMP_TYPE1	1
+#define CS42L42_HSDET_COMP_TYPE2	2
+#define CS42L42_HSDET_COMP_TYPE3	0
+#define CS42L42_HSDET_COMP_TYPE4	3
+
 #define CS42L42_HS_CLAMP_DISABLE	(CS42L42_PAGE_11 + 0x29)
 #define CS42L42_HS_CLAMP_DISABLE_SHIFT	0
 #define CS42L42_HS_CLAMP_DISABLE_MASK	(1 << CS42L42_HS_CLAMP_DISABLE_SHIFT)
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/2] ASoC: cs42l42: Minor fix all errors reported by checkpatch.pl script
  2021-09-14 16:52   ` Vitaly Rodionov
@ 2021-09-14 17:05     ` Mark Brown
  -1 siblings, 0 replies; 10+ messages in thread
From: Mark Brown @ 2021-09-14 17:05 UTC (permalink / raw)
  To: Vitaly Rodionov
  Cc: James Schulman, David Rhodes, Liam Girdwood, Jaroslav Kysela,
	Takashi Iwai, alsa-devel, patches, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 337 bytes --]

On Tue, Sep 14, 2021 at 05:52:19PM +0100, Vitaly Rodionov wrote:
> Signed-off-by: Vitaly Rodionov <vitalyr@opensource.cirrus.com>
> ---
>  sound/soc/codecs/cs42l42.c | 10 +++++-----
>  1 file changed, 5 insertions(+), 5 deletions(-)

This sort of minor cleanup should go after any fixes so that there's no
dependency created needlessly.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/2] ASoC: cs42l42: Minor fix all errors reported by checkpatch.pl script
@ 2021-09-14 17:05     ` Mark Brown
  0 siblings, 0 replies; 10+ messages in thread
From: Mark Brown @ 2021-09-14 17:05 UTC (permalink / raw)
  To: Vitaly Rodionov
  Cc: alsa-devel, Liam Girdwood, patches, Takashi Iwai, James Schulman,
	David Rhodes, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 337 bytes --]

On Tue, Sep 14, 2021 at 05:52:19PM +0100, Vitaly Rodionov wrote:
> Signed-off-by: Vitaly Rodionov <vitalyr@opensource.cirrus.com>
> ---
>  sound/soc/codecs/cs42l42.c | 10 +++++-----
>  1 file changed, 5 insertions(+), 5 deletions(-)

This sort of minor cleanup should go after any fixes so that there's no
dependency created needlessly.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/2] ASoC: cs42l42: Minor fix all errors reported by checkpatch.pl script
  2021-09-14 17:05     ` Mark Brown
@ 2021-09-15  9:36       ` Vitaly Rodionov
  -1 siblings, 0 replies; 10+ messages in thread
From: Vitaly Rodionov @ 2021-09-15  9:36 UTC (permalink / raw)
  To: Mark Brown
  Cc: alsa-devel, Liam Girdwood, patches, Takashi Iwai, James Schulman,
	David Rhodes, linux-kernel

On 14/09/2021 6:05 pm, Mark Brown wrote:
> On Tue, Sep 14, 2021 at 05:52:19PM +0100, Vitaly Rodionov wrote:
>> Signed-off-by: Vitaly Rodionov <vitalyr@opensource.cirrus.com>
>> ---
>>   sound/soc/codecs/cs42l42.c | 10 +++++-----
>>   1 file changed, 5 insertions(+), 5 deletions(-)

Hi Mark,

Thanks a lot for review. We will fix and push new version.

Thanks,

Vitaly

> This sort of minor cleanup should go after any fixes so that there's no
> dependency created needlessly.



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 1/2] ASoC: cs42l42: Minor fix all errors reported by checkpatch.pl script
@ 2021-09-15  9:36       ` Vitaly Rodionov
  0 siblings, 0 replies; 10+ messages in thread
From: Vitaly Rodionov @ 2021-09-15  9:36 UTC (permalink / raw)
  To: Mark Brown
  Cc: alsa-devel, patches, Takashi Iwai, Liam Girdwood, James Schulman,
	David Rhodes, linux-kernel

On 14/09/2021 6:05 pm, Mark Brown wrote:
> On Tue, Sep 14, 2021 at 05:52:19PM +0100, Vitaly Rodionov wrote:
>> Signed-off-by: Vitaly Rodionov <vitalyr@opensource.cirrus.com>
>> ---
>>   sound/soc/codecs/cs42l42.c | 10 +++++-----
>>   1 file changed, 5 insertions(+), 5 deletions(-)

Hi Mark,

Thanks a lot for review. We will fix and push new version.

Thanks,

Vitaly

> This sort of minor cleanup should go after any fixes so that there's no
> dependency created needlessly.



^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2021-09-15  9:37 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-14 16:52 [PATCH 0/2] ASoC: cs42l42: Implement Manual Type detection as fallback Vitaly Rodionov
2021-09-14 16:52 ` Vitaly Rodionov
2021-09-14 16:52 ` [PATCH 1/2] ASoC: cs42l42: Minor fix all errors reported by checkpatch.pl script Vitaly Rodionov
2021-09-14 16:52   ` Vitaly Rodionov
2021-09-14 17:05   ` Mark Brown
2021-09-14 17:05     ` Mark Brown
2021-09-15  9:36     ` Vitaly Rodionov
2021-09-15  9:36       ` Vitaly Rodionov
2021-09-14 16:52 ` [PATCH 2/2] ASoC: cs42l42: Implement Manual Type detection as fallback Vitaly Rodionov
2021-09-14 16:52   ` Vitaly Rodionov

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.