Commit fdd53528 authored by Richard Fitzgerald's avatar Richard Fitzgerald Committed by Mark Brown

ASoC: cs42l42: Report initial jack state

When a jack handler is registered in cs42l42_set_jack() the
initial state should be reported if an attached headphone/headset
has already been detected.

The jack detect sequence takes around 1 second: typically long
enough for the machine driver to probe and register the jack handler
in time to receive the first report from the interrupt handler. So
it is possible on some systems that the correct initial state was seen
simply because of lucky timing. Modular builds were more likely to
miss the reporting of the initial state.
Signed-off-by: default avatarRichard Fitzgerald <rf@opensource.cirrus.com>
Fixes: 4ca239f3 ("ASoC: cs42l42: Always enable TS_PLUG and TS_UNPLUG interrupts")
Link: https://lore.kernel.org/r/20211119124854.58939-1-rf@opensource.cirrus.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent 405e52f4
...@@ -549,8 +549,25 @@ static int cs42l42_set_jack(struct snd_soc_component *component, struct snd_soc_ ...@@ -549,8 +549,25 @@ static int cs42l42_set_jack(struct snd_soc_component *component, struct snd_soc_
{ {
struct cs42l42_private *cs42l42 = snd_soc_component_get_drvdata(component); struct cs42l42_private *cs42l42 = snd_soc_component_get_drvdata(component);
/* Prevent race with interrupt handler */
mutex_lock(&cs42l42->jack_detect_mutex);
cs42l42->jack = jk; cs42l42->jack = jk;
if (jk) {
switch (cs42l42->hs_type) {
case CS42L42_PLUG_CTIA:
case CS42L42_PLUG_OMTP:
snd_soc_jack_report(jk, SND_JACK_HEADSET, SND_JACK_HEADSET);
break;
case CS42L42_PLUG_HEADPHONE:
snd_soc_jack_report(jk, SND_JACK_HEADPHONE, SND_JACK_HEADPHONE);
break;
default:
break;
}
}
mutex_unlock(&cs42l42->jack_detect_mutex);
return 0; return 0;
} }
...@@ -1618,6 +1635,8 @@ static irqreturn_t cs42l42_irq_thread(int irq, void *data) ...@@ -1618,6 +1635,8 @@ static irqreturn_t cs42l42_irq_thread(int irq, void *data)
CS42L42_M_DETECT_FT_MASK | CS42L42_M_DETECT_FT_MASK |
CS42L42_M_HSBIAS_HIZ_MASK); CS42L42_M_HSBIAS_HIZ_MASK);
mutex_lock(&cs42l42->jack_detect_mutex);
/* Check auto-detect status */ /* Check auto-detect status */
if ((~masks[5]) & irq_params_table[5].mask) { if ((~masks[5]) & irq_params_table[5].mask) {
if (stickies[5] & CS42L42_HSDET_AUTO_DONE_MASK) { if (stickies[5] & CS42L42_HSDET_AUTO_DONE_MASK) {
...@@ -1686,6 +1705,8 @@ static irqreturn_t cs42l42_irq_thread(int irq, void *data) ...@@ -1686,6 +1705,8 @@ static irqreturn_t cs42l42_irq_thread(int irq, void *data)
} }
} }
mutex_unlock(&cs42l42->jack_detect_mutex);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -2033,6 +2054,7 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client, ...@@ -2033,6 +2054,7 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client,
cs42l42->dev = &i2c_client->dev; cs42l42->dev = &i2c_client->dev;
i2c_set_clientdata(i2c_client, cs42l42); i2c_set_clientdata(i2c_client, cs42l42);
mutex_init(&cs42l42->jack_detect_mutex);
cs42l42->regmap = devm_regmap_init_i2c(i2c_client, &cs42l42_regmap); cs42l42->regmap = devm_regmap_init_i2c(i2c_client, &cs42l42_regmap);
if (IS_ERR(cs42l42->regmap)) { if (IS_ERR(cs42l42->regmap)) {
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#ifndef __CS42L42_H__ #ifndef __CS42L42_H__
#define __CS42L42_H__ #define __CS42L42_H__
#include <linux/mutex.h>
#include <sound/jack.h> #include <sound/jack.h>
#define CS42L42_PAGE_REGISTER 0x00 /* Page Select Register */ #define CS42L42_PAGE_REGISTER 0x00 /* Page Select Register */
...@@ -841,6 +842,7 @@ struct cs42l42_private { ...@@ -841,6 +842,7 @@ struct cs42l42_private {
struct gpio_desc *reset_gpio; struct gpio_desc *reset_gpio;
struct completion pdn_done; struct completion pdn_done;
struct snd_soc_jack *jack; struct snd_soc_jack *jack;
struct mutex jack_detect_mutex;
int pll_config; int pll_config;
int bclk; int bclk;
u32 sclk; u32 sclk;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment