All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 01/10] extcon: arizona: Correct clean up if arizona_identify_headphone fails
@ 2019-12-09 11:09 ` Charles Keepax
  2019-12-09 11:09   ` [PATCH 02/10] extcon: arizona: Make rev A register sequences atomic Charles Keepax
                     ` (9 more replies)
  0 siblings, 10 replies; 11+ messages in thread
From: Charles Keepax @ 2019-12-09 11:09 UTC (permalink / raw)
  To: cw00.choi; +Cc: myungjoo.ham, patches, linux-kernel

In the error path of arizona_identify_headphone, neither the clamp nor
the PM runtime are cleaned up. Add calls to clean up both of these.

Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---
 drivers/extcon/extcon-arizona.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c
index e970134c95fab..79e9a24101823 100644
--- a/drivers/extcon/extcon-arizona.c
+++ b/drivers/extcon/extcon-arizona.c
@@ -724,6 +724,9 @@ static void arizona_identify_headphone(struct arizona_extcon_info *info)
 	return;
 
 err:
+	arizona_extcon_hp_clamp(info, false);
+	pm_runtime_put_autosuspend(info->dev);
+
 	regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1,
 			   ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
 
-- 
2.11.0


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

* [PATCH 02/10] extcon: arizona: Make rev A register sequences atomic
  2019-12-09 11:09 ` [PATCH 01/10] extcon: arizona: Correct clean up if arizona_identify_headphone fails Charles Keepax
@ 2019-12-09 11:09   ` Charles Keepax
  2019-12-09 11:09   ` [PATCH 03/10] extcon: arizona: Move pdata extraction to probe Charles Keepax
                     ` (8 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Charles Keepax @ 2019-12-09 11:09 UTC (permalink / raw)
  To: cw00.choi; +Cc: myungjoo.ham, patches, linux-kernel

The special register sequences that are applied for rev A of wm5102
should be applied atomically with respect to any other register writes.
Use regmap_multi_reg_write to ensure all writes happen under the regmap
lock.

Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---
 drivers/extcon/extcon-arizona.c | 20 ++++++++++++++------
 1 file changed, 14 insertions(+), 6 deletions(-)

diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c
index 79e9a24101823..a8b0bc2d4323b 100644
--- a/drivers/extcon/extcon-arizona.c
+++ b/drivers/extcon/extcon-arizona.c
@@ -310,9 +310,13 @@ static void arizona_start_mic(struct arizona_extcon_info *info)
 	}
 
 	if (info->micd_reva) {
-		regmap_write(arizona->regmap, 0x80, 0x3);
-		regmap_write(arizona->regmap, 0x294, 0);
-		regmap_write(arizona->regmap, 0x80, 0x0);
+		const struct reg_sequence reva[] = {
+			{ 0x80,  0x3 },
+			{ 0x294, 0x0 },
+			{ 0x80,  0x0 },
+		};
+
+		regmap_multi_reg_write(arizona->regmap, reva, ARRAY_SIZE(reva));
 	}
 
 	if (info->detecting && arizona->pdata.micd_software_compare)
@@ -361,9 +365,13 @@ static void arizona_stop_mic(struct arizona_extcon_info *info)
 	snd_soc_dapm_sync(dapm);
 
 	if (info->micd_reva) {
-		regmap_write(arizona->regmap, 0x80, 0x3);
-		regmap_write(arizona->regmap, 0x294, 2);
-		regmap_write(arizona->regmap, 0x80, 0x0);
+		const struct reg_sequence reva[] = {
+			{ 0x80,  0x3 },
+			{ 0x294, 0x2 },
+			{ 0x80,  0x0 },
+		};
+
+		regmap_multi_reg_write(arizona->regmap, reva, ARRAY_SIZE(reva));
 	}
 
 	ret = regulator_allow_bypass(info->micvdd, true);
-- 
2.11.0


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

* [PATCH 03/10] extcon: arizona: Move pdata extraction to probe
  2019-12-09 11:09 ` [PATCH 01/10] extcon: arizona: Correct clean up if arizona_identify_headphone fails Charles Keepax
  2019-12-09 11:09   ` [PATCH 02/10] extcon: arizona: Make rev A register sequences atomic Charles Keepax
@ 2019-12-09 11:09   ` Charles Keepax
  2019-12-09 11:09   ` [PATCH 04/10] extcon: arizona: Clear jack status regardless of detection type Charles Keepax
                     ` (7 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Charles Keepax @ 2019-12-09 11:09 UTC (permalink / raw)
  To: cw00.choi; +Cc: myungjoo.ham, patches, linux-kernel

It makes no sense to be extracting values from pdata for the first time
in the jack detection handler function, move this to probe time where it
belongs.

Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---
 drivers/extcon/extcon-arizona.c | 14 +++++---------
 1 file changed, 5 insertions(+), 9 deletions(-)

diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c
index a8b0bc2d4323b..121c417069478 100644
--- a/drivers/extcon/extcon-arizona.c
+++ b/drivers/extcon/extcon-arizona.c
@@ -77,8 +77,6 @@ struct arizona_extcon_info {
 	const struct arizona_micd_range *micd_ranges;
 	int num_micd_ranges;
 
-	int micd_timeout;
-
 	bool micd_reva;
 	bool micd_clamp;
 
@@ -1016,7 +1014,7 @@ static void arizona_micd_detect(struct work_struct *work)
 
 		queue_delayed_work(system_power_efficient_wq,
 				   &info->micd_timeout_work,
-				   msecs_to_jiffies(info->micd_timeout));
+				   msecs_to_jiffies(arizona->pdata.micd_timeout));
 	}
 
 	pm_runtime_mark_last_busy(info->dev);
@@ -1136,7 +1134,7 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
 					   msecs_to_jiffies(HPDET_DEBOUNCE));
 
 		if (cancelled_mic) {
-			int micd_timeout = info->micd_timeout;
+			int micd_timeout = arizona->pdata.micd_timeout;
 
 			queue_delayed_work(system_power_efficient_wq,
 					   &info->micd_timeout_work,
@@ -1213,11 +1211,6 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
 				   ARIZONA_MICD_CLAMP_DB | ARIZONA_JD1_DB);
 	}
 
-	if (arizona->pdata.micd_timeout)
-		info->micd_timeout = arizona->pdata.micd_timeout;
-	else
-		info->micd_timeout = DEFAULT_MICD_TIMEOUT;
-
 out:
 	/* Clear trig_sts to make sure DCVDD is not forced up */
 	regmap_write(arizona->regmap, ARIZONA_AOD_WKUP_AND_TRIG,
@@ -1446,6 +1439,9 @@ static int arizona_extcon_probe(struct platform_device *pdev)
 	info->input->name = "Headset";
 	info->input->phys = "arizona/extcon";
 
+	if (!pdata->micd_timeout)
+		pdata->micd_timeout = DEFAULT_MICD_TIMEOUT;
+
 	if (pdata->num_micd_configs) {
 		info->micd_modes = pdata->micd_configs;
 		info->micd_num_modes = pdata->num_micd_configs;
-- 
2.11.0


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

* [PATCH 04/10] extcon: arizona: Clear jack status regardless of detection type
  2019-12-09 11:09 ` [PATCH 01/10] extcon: arizona: Correct clean up if arizona_identify_headphone fails Charles Keepax
  2019-12-09 11:09   ` [PATCH 02/10] extcon: arizona: Make rev A register sequences atomic Charles Keepax
  2019-12-09 11:09   ` [PATCH 03/10] extcon: arizona: Move pdata extraction to probe Charles Keepax
@ 2019-12-09 11:09   ` Charles Keepax
  2019-12-09 11:09   ` [PATCH 05/10] extcon: arizona: Tidy up transition from mic to headphone detect Charles Keepax
                     ` (6 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Charles Keepax @ 2019-12-09 11:09 UTC (permalink / raw)
  To: cw00.choi; +Cc: myungjoo.ham, patches, linux-kernel

It makes sense to clear the internal state of the jack detection
regardless of if the headphone detect based accessory detection or
the normal microphone detect based flow is used.

No issues are currently known because of this but the change makes
more logical sense and eases future refactoring of the code.

Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---
 drivers/extcon/extcon-arizona.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c
index 121c417069478..11f1d753aa102 100644
--- a/drivers/extcon/extcon-arizona.c
+++ b/drivers/extcon/extcon-arizona.c
@@ -1154,11 +1154,11 @@ static irqreturn_t arizona_jackdet(int irq, void *data)
 			dev_err(arizona->dev, "Mechanical report failed: %d\n",
 				ret);
 
-		if (!arizona->pdata.hpdet_acc_id) {
-			info->detecting = true;
-			info->mic = false;
-			info->jack_flips = 0;
+		info->detecting = true;
+		info->mic = false;
+		info->jack_flips = 0;
 
+		if (!arizona->pdata.hpdet_acc_id) {
 			arizona_start_mic(info);
 		} else {
 			queue_delayed_work(system_power_efficient_wq,
-- 
2.11.0


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

* [PATCH 05/10] extcon: arizona: Tidy up transition from mic to headphone detect
  2019-12-09 11:09 ` [PATCH 01/10] extcon: arizona: Correct clean up if arizona_identify_headphone fails Charles Keepax
                     ` (2 preceding siblings ...)
  2019-12-09 11:09   ` [PATCH 04/10] extcon: arizona: Clear jack status regardless of detection type Charles Keepax
@ 2019-12-09 11:09   ` Charles Keepax
  2019-12-09 11:09   ` [PATCH 06/10] extcon: arizona: Remove unnecessary sets of ACCDET_MODE Charles Keepax
                     ` (5 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Charles Keepax @ 2019-12-09 11:09 UTC (permalink / raw)
  To: cw00.choi; +Cc: myungjoo.ham, patches, linux-kernel

Moving from microphone detection to headphone detection is done fairly
haphazardly at the moment, sometimes calling arizona_stop_mic at the
call site sometimes relying on a call inside arizona_identify_headphone.
Simplify all this and always call arizona_stop_mic at the top of
arizona_identify_headphone.

Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---
 drivers/extcon/extcon-arizona.c | 9 +--------
 1 file changed, 1 insertion(+), 8 deletions(-)

diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c
index 11f1d753aa102..5ae111ee3d631 100644
--- a/drivers/extcon/extcon-arizona.c
+++ b/drivers/extcon/extcon-arizona.c
@@ -705,8 +705,7 @@ static void arizona_identify_headphone(struct arizona_extcon_info *info)
 
 	info->hpdet_active = true;
 
-	if (info->mic)
-		arizona_stop_mic(info);
+	arizona_stop_mic(info);
 
 	arizona_extcon_hp_clamp(info, true);
 
@@ -815,8 +814,6 @@ static void arizona_micd_timeout_work(struct work_struct *work)
 
 	arizona_identify_headphone(info);
 
-	arizona_stop_mic(info);
-
 	mutex_unlock(&info->lock);
 }
 
@@ -906,7 +903,6 @@ static void arizona_micd_detect(struct work_struct *work)
 	if (!(val & ARIZONA_MICD_STS)) {
 		dev_warn(arizona->dev, "Detected open circuit\n");
 		info->mic = false;
-		arizona_stop_mic(info);
 		info->detecting = false;
 		arizona_identify_headphone(info);
 		goto handled;
@@ -948,8 +944,6 @@ static void arizona_micd_detect(struct work_struct *work)
 			info->detecting = false;
 
 			arizona_identify_headphone(info);
-
-			arizona_stop_mic(info);
 		} else {
 			info->micd_mode++;
 			if (info->micd_mode == info->micd_num_modes)
@@ -988,7 +982,6 @@ static void arizona_micd_detect(struct work_struct *work)
 		} else if (info->detecting) {
 			dev_dbg(arizona->dev, "Headphone detected\n");
 			info->detecting = false;
-			arizona_stop_mic(info);
 
 			arizona_identify_headphone(info);
 		} else {
-- 
2.11.0


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

* [PATCH 06/10] extcon: arizona: Remove unnecessary sets of ACCDET_MODE
  2019-12-09 11:09 ` [PATCH 01/10] extcon: arizona: Correct clean up if arizona_identify_headphone fails Charles Keepax
                     ` (3 preceding siblings ...)
  2019-12-09 11:09   ` [PATCH 05/10] extcon: arizona: Tidy up transition from mic to headphone detect Charles Keepax
@ 2019-12-09 11:09   ` Charles Keepax
  2019-12-09 11:09   ` [PATCH 07/10] extcon: arizona: Remove excessive WARN_ON Charles Keepax
                     ` (4 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Charles Keepax @ 2019-12-09 11:09 UTC (permalink / raw)
  To: cw00.choi; +Cc: myungjoo.ham, patches, linux-kernel

arizona_start_mic sets ACCDET_MODE as required for the microphone
detection as such it is redundant to set this outside of this function.

Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---
 drivers/extcon/extcon-arizona.c | 11 -----------
 1 file changed, 11 deletions(-)

diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c
index 5ae111ee3d631..e7c198e798e27 100644
--- a/drivers/extcon/extcon-arizona.c
+++ b/drivers/extcon/extcon-arizona.c
@@ -668,11 +668,6 @@ static irqreturn_t arizona_hpdet_irq(int irq, void *data)
 	if (id_gpio)
 		gpio_set_value_cansleep(id_gpio, 0);
 
-	/* Revert back to MICDET mode */
-	regmap_update_bits(arizona->regmap,
-			   ARIZONA_ACCESSORY_DETECT_MODE_1,
-			   ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
-
 	/* If we have a mic then reenable MICDET */
 	if (mic || info->mic)
 		arizona_start_mic(info);
@@ -732,9 +727,6 @@ static void arizona_identify_headphone(struct arizona_extcon_info *info)
 	arizona_extcon_hp_clamp(info, false);
 	pm_runtime_put_autosuspend(info->dev);
 
-	regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1,
-			   ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
-
 	/* Just report headphone */
 	ret = extcon_set_state_sync(info->edev, EXTCON_JACK_HEADPHONE, true);
 	if (ret != 0)
@@ -789,9 +781,6 @@ static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info)
 	return;
 
 err:
-	regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1,
-			   ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
-
 	/* Just report headphone */
 	ret = extcon_set_state_sync(info->edev, EXTCON_JACK_HEADPHONE, true);
 	if (ret != 0)
-- 
2.11.0


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

* [PATCH 07/10] extcon: arizona: Remove excessive WARN_ON
  2019-12-09 11:09 ` [PATCH 01/10] extcon: arizona: Correct clean up if arizona_identify_headphone fails Charles Keepax
                     ` (4 preceding siblings ...)
  2019-12-09 11:09   ` [PATCH 06/10] extcon: arizona: Remove unnecessary sets of ACCDET_MODE Charles Keepax
@ 2019-12-09 11:09   ` Charles Keepax
  2019-12-09 11:09   ` [PATCH 08/10] extcon: arizona: Invert logic of check in arizona_hpdet_do_id Charles Keepax
                     ` (3 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Charles Keepax @ 2019-12-09 11:09 UTC (permalink / raw)
  To: cw00.choi; +Cc: myungjoo.ham, patches, linux-kernel

A WARN_ON is very strong for simply finding a button that is out of
range, downgrade this to a simple error message in the log.

Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---
 drivers/extcon/extcon-arizona.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c
index e7c198e798e27..3f7ced35e0b86 100644
--- a/drivers/extcon/extcon-arizona.c
+++ b/drivers/extcon/extcon-arizona.c
@@ -960,14 +960,13 @@ static void arizona_micd_detect(struct work_struct *work)
 				input_report_key(info->input,
 						 info->micd_ranges[i].key, 0);
 
-			WARN_ON(!lvl);
-			WARN_ON(ffs(lvl) - 1 >= info->num_micd_ranges);
 			if (lvl && ffs(lvl) - 1 < info->num_micd_ranges) {
 				key = info->micd_ranges[ffs(lvl) - 1].key;
 				input_report_key(info->input, key, 1);
 				input_sync(info->input);
+			} else {
+				dev_err(arizona->dev, "Button out of range\n");
 			}
-
 		} else if (info->detecting) {
 			dev_dbg(arizona->dev, "Headphone detected\n");
 			info->detecting = false;
-- 
2.11.0


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

* [PATCH 08/10] extcon: arizona: Invert logic of check in arizona_hpdet_do_id
  2019-12-09 11:09 ` [PATCH 01/10] extcon: arizona: Correct clean up if arizona_identify_headphone fails Charles Keepax
                     ` (5 preceding siblings ...)
  2019-12-09 11:09   ` [PATCH 07/10] extcon: arizona: Remove excessive WARN_ON Charles Keepax
@ 2019-12-09 11:09   ` Charles Keepax
  2019-12-09 11:09   ` [PATCH 09/10] extcon: arizona: Factor out microphone impedance into a function Charles Keepax
                     ` (2 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Charles Keepax @ 2019-12-09 11:09 UTC (permalink / raw)
  To: cw00.choi; +Cc: myungjoo.ham, patches, linux-kernel

Invert the check of hpdet_acc_id at the top of arizona_hpdet_do_id to
reduce the identation within the function.

Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---
 drivers/extcon/extcon-arizona.c | 92 ++++++++++++++++++++---------------------
 1 file changed, 45 insertions(+), 47 deletions(-)

diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c
index 3f7ced35e0b86..a0135f44cba1e 100644
--- a/drivers/extcon/extcon-arizona.c
+++ b/drivers/extcon/extcon-arizona.c
@@ -533,67 +533,65 @@ static int arizona_hpdet_do_id(struct arizona_extcon_info *info, int *reading,
 	struct arizona *arizona = info->arizona;
 	int id_gpio = arizona->pdata.hpdet_id_gpio;
 
+	if (!arizona->pdata.hpdet_acc_id)
+		return 0;
+
 	/*
 	 * If we're using HPDET for accessory identification we need
 	 * to take multiple measurements, step through them in sequence.
 	 */
-	if (arizona->pdata.hpdet_acc_id) {
-		info->hpdet_res[info->num_hpdet_res++] = *reading;
+	info->hpdet_res[info->num_hpdet_res++] = *reading;
 
-		/* Only check the mic directly if we didn't already ID it */
-		if (id_gpio && info->num_hpdet_res == 1) {
-			dev_dbg(arizona->dev, "Measuring mic\n");
-
-			regmap_update_bits(arizona->regmap,
-					   ARIZONA_ACCESSORY_DETECT_MODE_1,
-					   ARIZONA_ACCDET_MODE_MASK |
-					   ARIZONA_ACCDET_SRC,
-					   ARIZONA_ACCDET_MODE_HPR |
-					   info->micd_modes[0].src);
+	/* Only check the mic directly if we didn't already ID it */
+	if (id_gpio && info->num_hpdet_res == 1) {
+		dev_dbg(arizona->dev, "Measuring mic\n");
 
-			gpio_set_value_cansleep(id_gpio, 1);
+		regmap_update_bits(arizona->regmap,
+				   ARIZONA_ACCESSORY_DETECT_MODE_1,
+				   ARIZONA_ACCDET_MODE_MASK |
+				   ARIZONA_ACCDET_SRC,
+				   ARIZONA_ACCDET_MODE_HPR |
+				   info->micd_modes[0].src);
 
-			regmap_update_bits(arizona->regmap,
-					   ARIZONA_HEADPHONE_DETECT_1,
-					   ARIZONA_HP_POLL, ARIZONA_HP_POLL);
-			return -EAGAIN;
-		}
+		gpio_set_value_cansleep(id_gpio, 1);
 
-		/* OK, got both.  Now, compare... */
-		dev_dbg(arizona->dev, "HPDET measured %d %d\n",
-			info->hpdet_res[0], info->hpdet_res[1]);
+		regmap_update_bits(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
+				   ARIZONA_HP_POLL, ARIZONA_HP_POLL);
+		return -EAGAIN;
+	}
 
-		/* Take the headphone impedance for the main report */
-		*reading = info->hpdet_res[0];
+	/* OK, got both.  Now, compare... */
+	dev_dbg(arizona->dev, "HPDET measured %d %d\n",
+		info->hpdet_res[0], info->hpdet_res[1]);
 
-		/* Sometimes we get false readings due to slow insert */
-		if (*reading >= ARIZONA_HPDET_MAX && !info->hpdet_retried) {
-			dev_dbg(arizona->dev, "Retrying high impedance\n");
-			info->num_hpdet_res = 0;
-			info->hpdet_retried = true;
-			arizona_start_hpdet_acc_id(info);
-			pm_runtime_put(info->dev);
-			return -EAGAIN;
-		}
+	/* Take the headphone impedance for the main report */
+	*reading = info->hpdet_res[0];
 
-		/*
-		 * If we measure the mic as high impedance
-		 */
-		if (!id_gpio || info->hpdet_res[1] > 50) {
-			dev_dbg(arizona->dev, "Detected mic\n");
-			*mic = true;
-			info->detecting = true;
-		} else {
-			dev_dbg(arizona->dev, "Detected headphone\n");
-		}
+	/* Sometimes we get false readings due to slow insert */
+	if (*reading >= ARIZONA_HPDET_MAX && !info->hpdet_retried) {
+		dev_dbg(arizona->dev, "Retrying high impedance\n");
+		info->num_hpdet_res = 0;
+		info->hpdet_retried = true;
+		arizona_start_hpdet_acc_id(info);
+		pm_runtime_put(info->dev);
+		return -EAGAIN;
+	}
 
-		/* Make sure everything is reset back to the real polarity */
-		regmap_update_bits(arizona->regmap,
-				   ARIZONA_ACCESSORY_DETECT_MODE_1,
-				   ARIZONA_ACCDET_SRC,
-				   info->micd_modes[0].src);
+	/*
+	 * If we measure the mic as high impedance
+	 */
+	if (!id_gpio || info->hpdet_res[1] > 50) {
+		dev_dbg(arizona->dev, "Detected mic\n");
+		*mic = true;
+		info->detecting = true;
+	} else {
+		dev_dbg(arizona->dev, "Detected headphone\n");
 	}
 
+	/* Make sure everything is reset back to the real polarity */
+	regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1,
+			   ARIZONA_ACCDET_SRC, info->micd_modes[0].src);
+
 	return 0;
 }
 
-- 
2.11.0


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

* [PATCH 09/10] extcon: arizona: Factor out microphone impedance into a function
  2019-12-09 11:09 ` [PATCH 01/10] extcon: arizona: Correct clean up if arizona_identify_headphone fails Charles Keepax
                     ` (6 preceding siblings ...)
  2019-12-09 11:09   ` [PATCH 08/10] extcon: arizona: Invert logic of check in arizona_hpdet_do_id Charles Keepax
@ 2019-12-09 11:09   ` Charles Keepax
  2019-12-09 11:09   ` [PATCH 10/10] extcon: arizona: Factor out microphone and button detection Charles Keepax
  2019-12-10  4:47   ` [PATCH 01/10] extcon: arizona: Correct clean up if arizona_identify_headphone fails Chanwoo Choi
  9 siblings, 0 replies; 11+ messages in thread
From: Charles Keepax @ 2019-12-09 11:09 UTC (permalink / raw)
  To: cw00.choi; +Cc: myungjoo.ham, patches, linux-kernel

The microphone detection handler is very long, start breaking it up
by factoring out the actual reading of the impedance value into a
separate functions. Additionally, this also fixes a minor bug and
ensures that the microphone timeout will be rescheduled in all error
cases.

Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---
 drivers/extcon/extcon-arizona.c | 125 +++++++++++++++++++++++-----------------
 1 file changed, 73 insertions(+), 52 deletions(-)

diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c
index a0135f44cba1e..b09a9a8ce98bc 100644
--- a/drivers/extcon/extcon-arizona.c
+++ b/drivers/extcon/extcon-arizona.c
@@ -804,70 +804,55 @@ static void arizona_micd_timeout_work(struct work_struct *work)
 	mutex_unlock(&info->lock);
 }
 
-static void arizona_micd_detect(struct work_struct *work)
+static int arizona_micd_adc_read(struct arizona_extcon_info *info)
 {
-	struct arizona_extcon_info *info = container_of(work,
-						struct arizona_extcon_info,
-						micd_detect_work.work);
 	struct arizona *arizona = info->arizona;
-	unsigned int val = 0, lvl;
-	int ret, i, key;
-
-	cancel_delayed_work_sync(&info->micd_timeout_work);
+	unsigned int val;
+	int ret;
 
-	mutex_lock(&info->lock);
+	/* Must disable MICD before we read the ADCVAL */
+	regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
+			   ARIZONA_MICD_ENA, 0);
 
-	/* If the cable was removed while measuring ignore the result */
-	ret = extcon_get_state(info->edev, EXTCON_MECHANICAL);
-	if (ret < 0) {
-		dev_err(arizona->dev, "Failed to check cable state: %d\n",
-				ret);
-		mutex_unlock(&info->lock);
-		return;
-	} else if (!ret) {
-		dev_dbg(arizona->dev, "Ignoring MICDET for removed cable\n");
-		mutex_unlock(&info->lock);
-		return;
+	ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_4, &val);
+	if (ret != 0) {
+		dev_err(arizona->dev,
+			"Failed to read MICDET_ADCVAL: %d\n", ret);
+		return ret;
 	}
 
-	if (info->detecting && arizona->pdata.micd_software_compare) {
-		/* Must disable MICD before we read the ADCVAL */
-		regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
-				   ARIZONA_MICD_ENA, 0);
-		ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_4, &val);
-		if (ret != 0) {
-			dev_err(arizona->dev,
-				"Failed to read MICDET_ADCVAL: %d\n",
-				ret);
-			mutex_unlock(&info->lock);
-			return;
-		}
+	dev_dbg(arizona->dev, "MICDET_ADCVAL: %x\n", val);
 
-		dev_dbg(arizona->dev, "MICDET_ADCVAL: %x\n", val);
+	val &= ARIZONA_MICDET_ADCVAL_MASK;
+	if (val < ARRAY_SIZE(arizona_micd_levels))
+		val = arizona_micd_levels[val];
+	else
+		val = INT_MAX;
+
+	if (val <= QUICK_HEADPHONE_MAX_OHM)
+		val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_0;
+	else if (val <= MICROPHONE_MIN_OHM)
+		val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_1;
+	else if (val <= MICROPHONE_MAX_OHM)
+		val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_8;
+	else
+		val = ARIZONA_MICD_LVL_8;
 
-		val &= ARIZONA_MICDET_ADCVAL_MASK;
-		if (val < ARRAY_SIZE(arizona_micd_levels))
-			val = arizona_micd_levels[val];
-		else
-			val = INT_MAX;
-
-		if (val <= QUICK_HEADPHONE_MAX_OHM)
-			val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_0;
-		else if (val <= MICROPHONE_MIN_OHM)
-			val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_1;
-		else if (val <= MICROPHONE_MAX_OHM)
-			val = ARIZONA_MICD_STS | ARIZONA_MICD_LVL_8;
-		else
-			val = ARIZONA_MICD_LVL_8;
-	}
+	return val;
+}
+
+static int arizona_micd_read(struct arizona_extcon_info *info)
+{
+	struct arizona *arizona = info->arizona;
+	unsigned int val = 0;
+	int ret, i;
 
 	for (i = 0; i < 10 && !(val & MICD_LVL_0_TO_8); i++) {
 		ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_3, &val);
 		if (ret != 0) {
 			dev_err(arizona->dev,
 				"Failed to read MICDET: %d\n", ret);
-			mutex_unlock(&info->lock);
-			return;
+			return ret;
 		}
 
 		dev_dbg(arizona->dev, "MICDET: %x\n", val);
@@ -875,17 +860,53 @@ static void arizona_micd_detect(struct work_struct *work)
 		if (!(val & ARIZONA_MICD_VALID)) {
 			dev_warn(arizona->dev,
 				 "Microphone detection state invalid\n");
-			mutex_unlock(&info->lock);
-			return;
+			return -EINVAL;
 		}
 	}
 
 	if (i == 10 && !(val & MICD_LVL_0_TO_8)) {
 		dev_err(arizona->dev, "Failed to get valid MICDET value\n");
+		return -EINVAL;
+	}
+
+	return val;
+}
+
+static void arizona_micd_detect(struct work_struct *work)
+{
+	struct arizona_extcon_info *info = container_of(work,
+						struct arizona_extcon_info,
+						micd_detect_work.work);
+	struct arizona *arizona = info->arizona;
+	unsigned int val = 0, lvl;
+	int ret, i, key;
+
+	cancel_delayed_work_sync(&info->micd_timeout_work);
+
+	mutex_lock(&info->lock);
+
+	/* If the cable was removed while measuring ignore the result */
+	ret = extcon_get_state(info->edev, EXTCON_MECHANICAL);
+	if (ret < 0) {
+		dev_err(arizona->dev, "Failed to check cable state: %d\n",
+				ret);
+		mutex_unlock(&info->lock);
+		return;
+	} else if (!ret) {
+		dev_dbg(arizona->dev, "Ignoring MICDET for removed cable\n");
 		mutex_unlock(&info->lock);
 		return;
 	}
 
+	if (info->detecting && arizona->pdata.micd_software_compare)
+		ret = arizona_micd_adc_read(info);
+	else
+		ret = arizona_micd_read(info);
+	if (ret < 0)
+		goto handled;
+
+	val = ret;
+
 	/* Due to jack detect this should never happen */
 	if (!(val & ARIZONA_MICD_STS)) {
 		dev_warn(arizona->dev, "Detected open circuit\n");
-- 
2.11.0


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

* [PATCH 10/10] extcon: arizona: Factor out microphone and button detection
  2019-12-09 11:09 ` [PATCH 01/10] extcon: arizona: Correct clean up if arizona_identify_headphone fails Charles Keepax
                     ` (7 preceding siblings ...)
  2019-12-09 11:09   ` [PATCH 09/10] extcon: arizona: Factor out microphone impedance into a function Charles Keepax
@ 2019-12-09 11:09   ` Charles Keepax
  2019-12-10  4:47   ` [PATCH 01/10] extcon: arizona: Correct clean up if arizona_identify_headphone fails Chanwoo Choi
  9 siblings, 0 replies; 11+ messages in thread
From: Charles Keepax @ 2019-12-09 11:09 UTC (permalink / raw)
  To: cw00.choi; +Cc: myungjoo.ham, patches, linux-kernel

Continue refactoring the microphone detect handling by factoring
out the handling for microphone detection and button detection
into separate functions. This both makes the code a little clearer
and prepares for some planned future refactoring to make the state
handling in the driver more explicit.

Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---
 drivers/extcon/extcon-arizona.c | 115 +++++++++++++++++++++++++---------------
 1 file changed, 71 insertions(+), 44 deletions(-)

diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c
index b09a9a8ce98bc..7401733db08bb 100644
--- a/drivers/extcon/extcon-arizona.c
+++ b/drivers/extcon/extcon-arizona.c
@@ -872,38 +872,18 @@ static int arizona_micd_read(struct arizona_extcon_info *info)
 	return val;
 }
 
-static void arizona_micd_detect(struct work_struct *work)
+static int arizona_micdet_reading(void *priv)
 {
-	struct arizona_extcon_info *info = container_of(work,
-						struct arizona_extcon_info,
-						micd_detect_work.work);
+	struct arizona_extcon_info *info = priv;
 	struct arizona *arizona = info->arizona;
-	unsigned int val = 0, lvl;
-	int ret, i, key;
-
-	cancel_delayed_work_sync(&info->micd_timeout_work);
-
-	mutex_lock(&info->lock);
-
-	/* If the cable was removed while measuring ignore the result */
-	ret = extcon_get_state(info->edev, EXTCON_MECHANICAL);
-	if (ret < 0) {
-		dev_err(arizona->dev, "Failed to check cable state: %d\n",
-				ret);
-		mutex_unlock(&info->lock);
-		return;
-	} else if (!ret) {
-		dev_dbg(arizona->dev, "Ignoring MICDET for removed cable\n");
-		mutex_unlock(&info->lock);
-		return;
-	}
+	int ret, val;
 
 	if (info->detecting && arizona->pdata.micd_software_compare)
 		ret = arizona_micd_adc_read(info);
 	else
 		ret = arizona_micd_read(info);
 	if (ret < 0)
-		goto handled;
+		return ret;
 
 	val = ret;
 
@@ -913,11 +893,11 @@ static void arizona_micd_detect(struct work_struct *work)
 		info->mic = false;
 		info->detecting = false;
 		arizona_identify_headphone(info);
-		goto handled;
+		return 0;
 	}
 
 	/* If we got a high impedence we should have a headset, report it. */
-	if (info->detecting && (val & ARIZONA_MICD_LVL_8)) {
+	if (val & ARIZONA_MICD_LVL_8) {
 		info->mic = true;
 		info->detecting = false;
 
@@ -936,7 +916,7 @@ static void arizona_micd_detect(struct work_struct *work)
 				ret);
 		}
 
-		goto handled;
+		return 0;
 	}
 
 	/* If we detected a lower impedence during initial startup
@@ -945,7 +925,7 @@ static void arizona_micd_detect(struct work_struct *work)
 	 * plain headphones.  If both polarities report a low
 	 * impedence then give up and report headphones.
 	 */
-	if (info->detecting && (val & MICD_LVL_1_TO_7)) {
+	if (val & MICD_LVL_1_TO_7) {
 		if (info->jack_flips >= info->micd_num_modes * 10) {
 			dev_dbg(arizona->dev, "Detected HP/line\n");
 
@@ -959,13 +939,45 @@ static void arizona_micd_detect(struct work_struct *work)
 			arizona_extcon_set_mode(info, info->micd_mode);
 
 			info->jack_flips++;
+
+			if (arizona->pdata.micd_software_compare)
+				regmap_update_bits(arizona->regmap,
+						   ARIZONA_MIC_DETECT_1,
+						   ARIZONA_MICD_ENA,
+						   ARIZONA_MICD_ENA);
+
+			queue_delayed_work(system_power_efficient_wq,
+					   &info->micd_timeout_work,
+					   msecs_to_jiffies(arizona->pdata.micd_timeout));
 		}
 
-		goto handled;
+		return 0;
 	}
 
 	/*
 	 * If we're still detecting and we detect a short then we've
+	 * got a headphone.
+	 */
+	dev_dbg(arizona->dev, "Headphone detected\n");
+	info->detecting = false;
+
+	arizona_identify_headphone(info);
+
+	return 0;
+}
+
+static int arizona_button_reading(void *priv)
+{
+	struct arizona_extcon_info *info = priv;
+	struct arizona *arizona = info->arizona;
+	int val, key, lvl, i;
+
+	val = arizona_micd_read(info);
+	if (val < 0)
+		return val;
+
+	/*
+	 * If we're still detecting and we detect a short then we've
 	 * got a headphone.  Otherwise it's a button press.
 	 */
 	if (val & MICD_LVL_0_TO_7) {
@@ -986,11 +998,6 @@ static void arizona_micd_detect(struct work_struct *work)
 			} else {
 				dev_err(arizona->dev, "Button out of range\n");
 			}
-		} else if (info->detecting) {
-			dev_dbg(arizona->dev, "Headphone detected\n");
-			info->detecting = false;
-
-			arizona_identify_headphone(info);
 		} else {
 			dev_warn(arizona->dev, "Button with no mic: %x\n",
 				 val);
@@ -1004,19 +1011,39 @@ static void arizona_micd_detect(struct work_struct *work)
 		arizona_extcon_pulse_micbias(info);
 	}
 
-handled:
-	if (info->detecting) {
-		if (arizona->pdata.micd_software_compare)
-			regmap_update_bits(arizona->regmap,
-					   ARIZONA_MIC_DETECT_1,
-					   ARIZONA_MICD_ENA,
-					   ARIZONA_MICD_ENA);
+	return 0;
+}
 
-		queue_delayed_work(system_power_efficient_wq,
-				   &info->micd_timeout_work,
-				   msecs_to_jiffies(arizona->pdata.micd_timeout));
+static void arizona_micd_detect(struct work_struct *work)
+{
+	struct arizona_extcon_info *info = container_of(work,
+						struct arizona_extcon_info,
+						micd_detect_work.work);
+	struct arizona *arizona = info->arizona;
+	int ret;
+
+	cancel_delayed_work_sync(&info->micd_timeout_work);
+
+	mutex_lock(&info->lock);
+
+	/* If the cable was removed while measuring ignore the result */
+	ret = extcon_get_state(info->edev, EXTCON_MECHANICAL);
+	if (ret < 0) {
+		dev_err(arizona->dev, "Failed to check cable state: %d\n",
+				ret);
+		mutex_unlock(&info->lock);
+		return;
+	} else if (!ret) {
+		dev_dbg(arizona->dev, "Ignoring MICDET for removed cable\n");
+		mutex_unlock(&info->lock);
+		return;
 	}
 
+	if (info->detecting)
+		arizona_micdet_reading(info);
+	else
+		arizona_button_reading(info);
+
 	pm_runtime_mark_last_busy(info->dev);
 	mutex_unlock(&info->lock);
 }
-- 
2.11.0


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

* Re: [PATCH 01/10] extcon: arizona: Correct clean up if arizona_identify_headphone fails
  2019-12-09 11:09 ` [PATCH 01/10] extcon: arizona: Correct clean up if arizona_identify_headphone fails Charles Keepax
                     ` (8 preceding siblings ...)
  2019-12-09 11:09   ` [PATCH 10/10] extcon: arizona: Factor out microphone and button detection Charles Keepax
@ 2019-12-10  4:47   ` Chanwoo Choi
  9 siblings, 0 replies; 11+ messages in thread
From: Chanwoo Choi @ 2019-12-10  4:47 UTC (permalink / raw)
  To: Charles Keepax; +Cc: myungjoo.ham, patches, linux-kernel

On 12/9/19 8:09 PM, Charles Keepax wrote:
> In the error path of arizona_identify_headphone, neither the clamp nor
> the PM runtime are cleaned up. Add calls to clean up both of these.
> 
> Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
> ---
>  drivers/extcon/extcon-arizona.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c
> index e970134c95fab..79e9a24101823 100644
> --- a/drivers/extcon/extcon-arizona.c
> +++ b/drivers/extcon/extcon-arizona.c
> @@ -724,6 +724,9 @@ static void arizona_identify_headphone(struct arizona_extcon_info *info)
>  	return;
>  
>  err:
> +	arizona_extcon_hp_clamp(info, false);
> +	pm_runtime_put_autosuspend(info->dev);
> +
>  	regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1,
>  			   ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
>  
> 

Applied these patches in this series. Thanks.

-- 
Best Regards,
Chanwoo Choi
Samsung Electronics

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

end of thread, other threads:[~2019-12-10  4:41 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <CGME20191209110925epcas4p3731ec3380f882027824b188439aa3bc9@epcas4p3.samsung.com>
2019-12-09 11:09 ` [PATCH 01/10] extcon: arizona: Correct clean up if arizona_identify_headphone fails Charles Keepax
2019-12-09 11:09   ` [PATCH 02/10] extcon: arizona: Make rev A register sequences atomic Charles Keepax
2019-12-09 11:09   ` [PATCH 03/10] extcon: arizona: Move pdata extraction to probe Charles Keepax
2019-12-09 11:09   ` [PATCH 04/10] extcon: arizona: Clear jack status regardless of detection type Charles Keepax
2019-12-09 11:09   ` [PATCH 05/10] extcon: arizona: Tidy up transition from mic to headphone detect Charles Keepax
2019-12-09 11:09   ` [PATCH 06/10] extcon: arizona: Remove unnecessary sets of ACCDET_MODE Charles Keepax
2019-12-09 11:09   ` [PATCH 07/10] extcon: arizona: Remove excessive WARN_ON Charles Keepax
2019-12-09 11:09   ` [PATCH 08/10] extcon: arizona: Invert logic of check in arizona_hpdet_do_id Charles Keepax
2019-12-09 11:09   ` [PATCH 09/10] extcon: arizona: Factor out microphone impedance into a function Charles Keepax
2019-12-09 11:09   ` [PATCH 10/10] extcon: arizona: Factor out microphone and button detection Charles Keepax
2019-12-10  4:47   ` [PATCH 01/10] extcon: arizona: Correct clean up if arizona_identify_headphone fails Chanwoo Choi

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.