ASoC: rt5640: Delay requesting IRQ until the machine-drv calls set_jack

Delay requesting the IRQ until the machine-drv calls set_jack.

The main reason for this is that the codec's IRQ is unused on some boards,
in which case we really should not call request_irq at all.

On some boards there is an IRQ listed at index 0 for the codec, but
this is not connected to the codec, but rather is directly connected
to the jack's jack-detect pin. These special setups will be handled
by the machine-driver, but the machine driver can only request the IRQ
if it is not first requested by the codec driver. Moving the request_irq
to the set_jack callback (which will not get called in this case) avoids
the codec-driver clobbering the IRQ.

Moving the request_irq also removes the need to disable the IRQ immediately
after requesting it, avoiding a small race (this could also have been fixed
by using the new IRQF_NO_AUTOEN flag when requesting the IRQ).

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Acked-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Link: https://lore.kernel.org/r/20210819190543.784415-3-hdegoede@redhat.com
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Hans de Goede 2021-08-19 21:05:39 +02:00 committed by Mark Brown
parent 5caab9f48b
commit 15d54840ec
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0
1 changed files with 13 additions and 17 deletions

View File

@ -2373,7 +2373,7 @@ static void rt5640_disable_jack_detect(struct snd_soc_component *component)
if (!rt5640->jack)
return;
disable_irq(rt5640->irq);
free_irq(rt5640->irq, rt5640);
rt5640_cancel_work(rt5640);
if (rt5640->jack->status & SND_JACK_MICROPHONE) {
@ -2389,6 +2389,7 @@ static void rt5640_enable_jack_detect(struct snd_soc_component *component,
struct snd_soc_jack *jack)
{
struct rt5640_priv *rt5640 = snd_soc_component_get_drvdata(component);
int ret;
/* Select JD-source */
snd_soc_component_update_bits(component, RT5640_JD_CTRL,
@ -2446,7 +2447,17 @@ static void rt5640_enable_jack_detect(struct snd_soc_component *component,
rt5640_enable_micbias1_ovcd_irq(component);
}
enable_irq(rt5640->irq);
ret = request_irq(rt5640->irq, rt5640_irq,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
"rt5640", rt5640);
if (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);
return;
}
/* sync initial jack state */
queue_work(system_long_wq, &rt5640->jack_work);
}
@ -2836,21 +2847,6 @@ static int rt5640_i2c_probe(struct i2c_client *i2c,
if (ret)
return ret;
if (rt5640->irq) {
/* enabled by rt5640_set_jack() */
ret = devm_request_irq(&i2c->dev, rt5640->irq, rt5640_irq,
IRQF_TRIGGER_RISING | IRQF_NO_AUTOEN |
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
"rt5640", rt5640);
if (ret) {
dev_err(&i2c->dev, "Failed to request IRQ %d: %d\n",
rt5640->irq, ret);
return ret;
}
} else {
rt5640->irq = -ENXIO;
}
return devm_snd_soc_register_component(&i2c->dev,
&soc_component_dev_rt5640,
rt5640_dai, ARRAY_SIZE(rt5640_dai));