fix bug: when system suspended, we shouldn't access TAS2557
authorPeter Li <a0220410@ti.com>
Tue, 16 May 2017 14:01:20 +0000 (22:01 +0800)
committerPeter Li <a0220410@ti.com>
Tue, 16 May 2017 14:01:20 +0000 (22:01 +0800)
tas2557-codec.c
tas2557-regmap.c
tas2557.h

index 1cec7976fcc9263fe5a49dcf5333b9c31fe0fe9c..0fa00f04f0643ea9842885fa8a391bab1d58f776 100755 (executable)
@@ -84,6 +84,34 @@ static int tas2557_codec_write(struct snd_soc_codec *pCodec, unsigned int nRegis
        return ret;
 }
 
+static int tas2557_codec_suspend(struct snd_soc_codec *pCodec)
+{
+       struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(pCodec);
+       int ret = 0;
+
+       mutex_lock(&pTAS2557->codec_lock);
+
+       dev_dbg(pTAS2557->dev, "%s\n", __func__);
+       pTAS2557->runtime_suspend(pTAS2557);
+
+       mutex_unlock(&pTAS2557->codec_lock);
+       return ret;
+}
+
+static int tas2557_codec_resume(struct snd_soc_codec *pCodec)
+{
+       struct tas2557_priv *pTAS2557 = snd_soc_codec_get_drvdata(pCodec);
+       int ret = 0;
+
+       mutex_lock(&pTAS2557->codec_lock);
+
+       dev_dbg(pTAS2557->dev, "%s\n", __func__);
+       pTAS2557->runtime_resume(pTAS2557);
+
+       mutex_unlock(&pTAS2557->codec_lock);
+       return ret;
+}
+
 static const struct snd_soc_dapm_widget tas2557_dapm_widgets[] = {
        SND_SOC_DAPM_AIF_IN("ASI1", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0),
        SND_SOC_DAPM_AIF_IN("ASI2", "ASI2 Playback", 0, SND_SOC_NOPM, 0, 0),
@@ -459,6 +487,8 @@ static struct snd_soc_codec_driver soc_codec_driver_tas2557 = {
        .remove = tas2557_codec_remove,
        .read = tas2557_codec_read,
        .write = tas2557_codec_write,
+       .suspend = tas2557_codec_suspend,
+       .resume = tas2557_codec_resume,
        .set_bias_level = tas2557_set_bias_level,
        .idle_bias_off = true,
        .controls = tas2557_snd_controls,
index 75be7319e7aab4156f66342ea4221373aca50e71..e3c23fd486ee4ffd375892b5fa7a23eecc113436 100755 (executable)
@@ -389,8 +389,15 @@ static void irq_work_routine(struct work_struct *work)
        mutex_lock(&pTAS2557->file_lock);
 #endif
 
-       if (!pTAS2557->mbPowerUp)
+       if (pTAS2557->mbRuntimeSuspend) {
+               dev_info(pTAS2557->dev, "%s, Runtime Suspended\n", __func__);
                goto end;
+       }
+
+       if (!pTAS2557->mbPowerUp) {
+               dev_info(pTAS2557->dev, "%s, device not powered\n", __func__);
+               goto end;
+       }
 
        if ((!pTAS2557->mpFirmware->mnConfigurations)
                || (!pTAS2557->mpFirmware->mnPrograms)) {
@@ -542,6 +549,11 @@ static void timer_work_routine(struct work_struct *work)
        mutex_lock(&pTAS2557->file_lock);
 #endif
 
+       if (pTAS2557->mbRuntimeSuspend) {
+               dev_info(pTAS2557->dev, "%s, Runtime Suspended\n", __func__);
+               goto end;
+       }
+
        if (!pTAS2557->mpFirmware->mnConfigurations) {
                dev_info(pTAS2557->dev, "%s, firmware not loaded\n", __func__);
                goto end;
@@ -604,23 +616,30 @@ end:
 #endif
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int tas2557_suspend(struct device *dev)
+static int tas2557_runtime_suspend(struct tas2557_priv *pTAS2557)
 {
-       struct tas2557_priv *pTAS2557 = dev_get_drvdata(dev);
-
        dev_dbg(pTAS2557->dev, "%s\n", __func__);
+
+       pTAS2557->mbRuntimeSuspend = true;
+
        if (hrtimer_active(&pTAS2557->mtimer)) {
                dev_dbg(pTAS2557->dev, "cancel die temp timer\n");
                hrtimer_cancel(&pTAS2557->mtimer);
        }
+       if (work_pending(&pTAS2557->mtimerwork)) {
+               dev_dbg(pTAS2557->dev, "cancel timer work\n");
+               cancel_work_sync(&pTAS2557->mtimerwork);
+       }
+       if (delayed_work_pending(&pTAS2557->irq_work)) {
+               dev_dbg(pTAS2557->dev, "cancel IRQ work\n");
+               cancel_delayed_work_sync(&pTAS2557->irq_work);
+       }
 
        return 0;
 }
 
-static int tas2557_resume(struct device *dev)
+static int tas2557_runtime_resume(struct tas2557_priv *pTAS2557)
 {
-       struct tas2557_priv *pTAS2557 = dev_get_drvdata(dev);
        struct TProgram *pProgram;
 
        dev_dbg(pTAS2557->dev, "%s\n", __func__);
@@ -629,7 +648,7 @@ static int tas2557_resume(struct device *dev)
                goto end;
        }
 
-       if (pTAS2557->mnCurrentProgram >= pTAS2557->mpCalFirmware->mnPrograms) {
+       if (pTAS2557->mnCurrentProgram >= pTAS2557->mpFirmware->mnPrograms) {
                dev_err(pTAS2557->dev, "%s, firmware corrupted\n", __func__);
                goto end;
        }
@@ -644,11 +663,11 @@ static int tas2557_resume(struct device *dev)
                }
        }
 
+       pTAS2557->mbRuntimeSuspend = false;
 end:
 
        return 0;
 }
-#endif
 
 static bool tas2557_volatile(struct device *pDev, unsigned int nRegister)
 {
@@ -724,6 +743,8 @@ static int tas2557_i2c_probe(struct i2c_client *pClient,
        pTAS2557->set_config = tas2557_set_config;
        pTAS2557->set_calibration = tas2557_set_calibration;
        pTAS2557->hw_reset = tas2557_hw_reset;
+       pTAS2557->runtime_suspend = tas2557_runtime_suspend;
+       pTAS2557->runtime_resume = tas2557_runtime_resume;
 
        mutex_init(&pTAS2557->dev_lock);
 
@@ -847,19 +868,10 @@ static const struct of_device_id tas2557_of_match[] = {
 MODULE_DEVICE_TABLE(of, tas2557_of_match);
 #endif
 
-#ifdef CONFIG_PM_SLEEP
-static const struct dev_pm_ops tas2557_pm_ops = {
-       SET_SYSTEM_SLEEP_PM_OPS(tas2557_suspend, tas2557_resume)
-};
-#endif
-
 static struct i2c_driver tas2557_i2c_driver = {
        .driver = {
                        .name = "tas2557",
                        .owner = THIS_MODULE,
-#ifdef CONFIG_PM_SLEEP
-                       .pm = &tas2557_pm_ops,
-#endif
 #if defined(CONFIG_OF)
                        .of_match_table = of_match_ptr(tas2557_of_match),
 #endif
index 5cd4f7af6b79e9e52399120c6c1fa03dac8742ac..cd781024f4d8a4c5deff32e67b686963eb9a7f35 100755 (executable)
--- a/tas2557.h
+++ b/tas2557.h
@@ -438,6 +438,9 @@ struct tas2557_priv {
        void (*clearIRQ)(struct tas2557_priv *pTAS2557);
        void (*enableIRQ)(struct tas2557_priv *pTAS2557, bool enable);
        void (*hw_reset)(struct tas2557_priv *pTAS2557);
+       /* device is working, but system is suspended */
+       int (*runtime_suspend)(struct tas2557_priv *pTAS2557);
+       int (*runtime_resume)(struct tas2557_priv *pTAS2557);
 
        int mnGpioINT;
        struct delayed_work irq_work;
@@ -453,6 +456,9 @@ struct tas2557_priv {
        struct hrtimer mtimer;
        struct work_struct mtimerwork;
 
+       /* device is working, but system is suspended */
+       bool mbRuntimeSuspend;
+
        unsigned int mnErrCode;
 #ifdef CONFIG_TAS2557_CODEC
        struct mutex codec_lock;