diff options
author | Hans de Goede <hdegoede@redhat.com> | 2021-08-19 22:05:39 +0300 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2021-08-20 01:27:56 +0300 |
commit | 15d54840ecf6f00061d03180394a0a21ff8ffa48 (patch) | |
tree | 47581d9ee7dd2c5bf78219db52ac8e1113fd9876 | |
parent | 5caab9f48b96f6998fb23d38a7b57fca91ef1653 (diff) | |
download | linux-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.c | 30 |
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)); |