Commit 701d636a authored by Hans de Goede's avatar Hans de Goede Committed by Mark Brown

ASoC: rt5640: Add support for boards with an external jack-detect GPIO

Some boards have the codec IRQ hooked-up as normally, so the driver can
still do things like headset vs headphones and button-press detection,
but instead of using one of the JD pins of the codec, an external GPIO
is used to report the jack-presence switch status of the jack.

Add support for this.
Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
Link: https://lore.kernel.org/r/20220106110128.66049-5-hdegoede@redhat.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent b35a9ab4
...@@ -2160,7 +2160,11 @@ static bool rt5640_jack_inserted(struct snd_soc_component *component) ...@@ -2160,7 +2160,11 @@ static bool rt5640_jack_inserted(struct snd_soc_component *component)
struct rt5640_priv *rt5640 = snd_soc_component_get_drvdata(component); struct rt5640_priv *rt5640 = snd_soc_component_get_drvdata(component);
int val; int val;
val = snd_soc_component_read(component, RT5640_INT_IRQ_ST); if (rt5640->jd_gpio)
val = gpiod_get_value(rt5640->jd_gpio) ? RT5640_JD_STATUS : 0;
else
val = snd_soc_component_read(component, RT5640_INT_IRQ_ST);
dev_dbg(component->dev, "irq status %#04x\n", val); dev_dbg(component->dev, "irq status %#04x\n", val);
if (rt5640->jd_inverted) if (rt5640->jd_inverted)
...@@ -2395,6 +2399,16 @@ static irqreturn_t rt5640_irq(int irq, void *data) ...@@ -2395,6 +2399,16 @@ static irqreturn_t rt5640_irq(int irq, void *data)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static irqreturn_t rt5640_jd_gpio_irq(int irq, void *data)
{
struct rt5640_priv *rt5640 = data;
queue_delayed_work(system_long_wq, &rt5640->jack_work,
msecs_to_jiffies(JACK_SETTLE_TIME));
return IRQ_HANDLED;
}
static void rt5640_cancel_work(void *data) static void rt5640_cancel_work(void *data)
{ {
struct rt5640_priv *rt5640 = data; struct rt5640_priv *rt5640 = data;
...@@ -2439,7 +2453,12 @@ static void rt5640_disable_jack_detect(struct snd_soc_component *component) ...@@ -2439,7 +2453,12 @@ static void rt5640_disable_jack_detect(struct snd_soc_component *component)
if (!rt5640->jack) if (!rt5640->jack)
return; return;
free_irq(rt5640->irq, rt5640); if (rt5640->jd_gpio_irq_requested)
free_irq(rt5640->jd_gpio_irq, rt5640);
if (rt5640->irq_requested)
free_irq(rt5640->irq, rt5640);
rt5640_cancel_work(rt5640); rt5640_cancel_work(rt5640);
if (rt5640->jack->status & SND_JACK_MICROPHONE) { if (rt5640->jack->status & SND_JACK_MICROPHONE) {
...@@ -2448,6 +2467,9 @@ static void rt5640_disable_jack_detect(struct snd_soc_component *component) ...@@ -2448,6 +2467,9 @@ static void rt5640_disable_jack_detect(struct snd_soc_component *component)
snd_soc_jack_report(rt5640->jack, 0, SND_JACK_BTN_0); snd_soc_jack_report(rt5640->jack, 0, SND_JACK_BTN_0);
} }
rt5640->jd_gpio_irq_requested = false;
rt5640->irq_requested = false;
rt5640->jd_gpio = NULL;
rt5640->jack = NULL; rt5640->jack = NULL;
} }
...@@ -2500,16 +2522,31 @@ static void rt5640_enable_jack_detect(struct snd_soc_component *component, ...@@ -2500,16 +2522,31 @@ static void rt5640_enable_jack_detect(struct snd_soc_component *component,
if (jack_data && jack_data->codec_irq_override) if (jack_data && jack_data->codec_irq_override)
rt5640->irq = jack_data->codec_irq_override; rt5640->irq = jack_data->codec_irq_override;
if (jack_data && jack_data->jd_gpio) {
rt5640->jd_gpio = jack_data->jd_gpio;
rt5640->jd_gpio_irq = gpiod_to_irq(rt5640->jd_gpio);
ret = request_irq(rt5640->jd_gpio_irq, rt5640_jd_gpio_irq,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
"rt5640-jd-gpio", rt5640);
if (ret) {
dev_warn(component->dev, "Failed to request jd GPIO IRQ %d: %d\n",
rt5640->jd_gpio_irq, ret);
rt5640_disable_jack_detect(component);
return;
}
rt5640->jd_gpio_irq_requested = true;
}
ret = request_irq(rt5640->irq, rt5640_irq, ret = request_irq(rt5640->irq, rt5640_irq,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
"rt5640", rt5640); "rt5640", rt5640);
if (ret) { if (ret) {
dev_warn(component->dev, "Failed to reguest IRQ %d: %d\n", rt5640->irq, ret); dev_warn(component->dev, "Failed to reguest IRQ %d: %d\n", rt5640->irq, ret);
rt5640->irq = -ENXIO;
/* Undo above settings */
rt5640_disable_jack_detect(component); rt5640_disable_jack_detect(component);
return; return;
} }
rt5640->irq_requested = true;
/* sync initial jack state */ /* sync initial jack state */
queue_delayed_work(system_long_wq, &rt5640->jack_work, 0); queue_delayed_work(system_long_wq, &rt5640->jack_work, 0);
......
...@@ -2124,6 +2124,7 @@ struct rt5640_priv { ...@@ -2124,6 +2124,7 @@ struct rt5640_priv {
int ldo1_en; /* GPIO for LDO1_EN */ int ldo1_en; /* GPIO for LDO1_EN */
int irq; int irq;
int jd_gpio_irq;
int sysclk; int sysclk;
int sysclk_src; int sysclk_src;
int lrck[RT5640_AIFS]; int lrck[RT5640_AIFS];
...@@ -2136,6 +2137,8 @@ struct rt5640_priv { ...@@ -2136,6 +2137,8 @@ struct rt5640_priv {
bool hp_mute; bool hp_mute;
bool asrc_en; bool asrc_en;
bool irq_requested;
bool jd_gpio_irq_requested;
/* Jack and button detect data */ /* Jack and button detect data */
bool ovcd_irq_enabled; bool ovcd_irq_enabled;
...@@ -2147,6 +2150,7 @@ struct rt5640_priv { ...@@ -2147,6 +2150,7 @@ struct rt5640_priv {
struct delayed_work bp_work; struct delayed_work bp_work;
struct delayed_work jack_work; struct delayed_work jack_work;
struct snd_soc_jack *jack; struct snd_soc_jack *jack;
struct gpio_desc *jd_gpio;
unsigned int jd_src; unsigned int jd_src;
bool jd_inverted; bool jd_inverted;
unsigned int ovcd_th; unsigned int ovcd_th;
...@@ -2155,6 +2159,7 @@ struct rt5640_priv { ...@@ -2155,6 +2159,7 @@ struct rt5640_priv {
struct rt5640_set_jack_data { struct rt5640_set_jack_data {
int codec_irq_override; int codec_irq_override;
struct gpio_desc *jd_gpio;
}; };
int rt5640_dmic_enable(struct snd_soc_component *component, int rt5640_dmic_enable(struct snd_soc_component *component,
......
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