scp_sdca_stat2 = rt711->scp_sdca_stat2;
        }
 
+       /*
+        * The critical section below intentionally protects a rather large piece of code.
+        * We don't want to allow the system suspend to disable an interrupt while we are
+        * processing it, which could be problematic given the quirky SoundWire interrupt
+        * scheme. We do want however to prevent new workqueues from being scheduled if
+        * the disable_irq flag was set during system suspend.
+        */
+       mutex_lock(&rt711->disable_irq_lock);
+
        ret = sdw_read_no_pm(rt711->slave, SDW_SCP_SDCA_INT1);
        if (ret < 0)
                goto io_error;
                        "%s scp_sdca_stat1=0x%x, scp_sdca_stat2=0x%x\n", __func__,
                        rt711->scp_sdca_stat1, rt711->scp_sdca_stat2);
 
-       if (status->sdca_cascade)
+       if (status->sdca_cascade && !rt711->disable_irq)
                mod_delayed_work(system_power_efficient_wq,
                        &rt711->jack_detect_work, msecs_to_jiffies(30));
 
+       mutex_unlock(&rt711->disable_irq_lock);
+
        return 0;
 
 io_error:
+       mutex_unlock(&rt711->disable_irq_lock);
        pr_err_ratelimited("IO error in %s, ret %d\n", __func__, ret);
        return ret;
 }
        return 0;
 }
 
+static int __maybe_unused rt711_sdca_dev_system_suspend(struct device *dev)
+{
+       struct rt711_sdca_priv *rt711_sdca = dev_get_drvdata(dev);
+       struct sdw_slave *slave = dev_to_sdw_dev(dev);
+       int ret1, ret2;
+
+       if (!rt711_sdca->hw_init)
+               return 0;
+
+       /*
+        * prevent new interrupts from being handled after the
+        * deferred work completes and before the parent disables
+        * interrupts on the link
+        */
+       mutex_lock(&rt711_sdca->disable_irq_lock);
+       rt711_sdca->disable_irq = true;
+       ret1 = sdw_update_no_pm(slave, SDW_SCP_SDCA_INTMASK1,
+                               SDW_SCP_SDCA_INTMASK_SDCA_0, 0);
+       ret2 = sdw_update_no_pm(slave, SDW_SCP_SDCA_INTMASK2,
+                               SDW_SCP_SDCA_INTMASK_SDCA_8, 0);
+       mutex_unlock(&rt711_sdca->disable_irq_lock);
+
+       if (ret1 < 0 || ret2 < 0) {
+               /* log but don't prevent suspend from happening */
+               dev_dbg(&slave->dev, "%s: could not disable SDCA interrupts\n:", __func__);
+       }
+
+       return rt711_sdca_dev_suspend(dev);
+}
+
 #define RT711_PROBE_TIMEOUT 5000
 
 static int __maybe_unused rt711_sdca_dev_resume(struct device *dev)
 }
 
 static const struct dev_pm_ops rt711_sdca_pm = {
-       SET_SYSTEM_SLEEP_PM_OPS(rt711_sdca_dev_suspend, rt711_sdca_dev_resume)
+       SET_SYSTEM_SLEEP_PM_OPS(rt711_sdca_dev_system_suspend, rt711_sdca_dev_resume)
        SET_RUNTIME_PM_OPS(rt711_sdca_dev_suspend, rt711_sdca_dev_resume, NULL)
 };