summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2021-08-19 22:05:39 +0300
committerMark Brown <broonie@kernel.org>2021-08-20 01:27:56 +0300
commit15d54840ecf6f00061d03180394a0a21ff8ffa48 (patch)
tree47581d9ee7dd2c5bf78219db52ac8e1113fd9876
parent5caab9f48b96f6998fb23d38a7b57fca91ef1653 (diff)
downloadlinux-15d54840ecf6f00061d03180394a0a21ff8ffa48.tar.xz
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>
-rw-r--r--sound/soc/codecs/rt5640.c30
1 files changed, 13 insertions, 17 deletions
diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
index 5439f771eef5..d32e9d69231c 100644
--- a/sound/soc/codecs/rt5640.c
+++ b/sound/soc/codecs/rt5640.c
@@ -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));