ASoC: rt5640: Delay requesting IRQ until the machine-drv calls set_jack
authorHans de Goede <hdegoede@redhat.com>
Thu, 19 Aug 2021 19:05:39 +0000 (21:05 +0200)
committerMark Brown <broonie@kernel.org>
Thu, 19 Aug 2021 22:27:56 +0000 (23:27 +0100)
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>
sound/soc/codecs/rt5640.c

index 5439f771eef568bcc5f391e8586d1bbd10d9bf81..d32e9d69231c488a21f80287198a68ff6314b421 100644 (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));