Merge branch 'for-5.5' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie...
[platform/kernel/linux-rpi.git] / sound / soc / codecs / max98090.c
index be1fc8a..da23810 100644 (file)
@@ -2294,28 +2294,42 @@ static void max98090_pll_det_disable_work(struct work_struct *work)
                            M98090_IULK_MASK, 0);
 }
 
-static void max98090_pll_work(struct work_struct *work)
+static void max98090_pll_work(struct max98090_priv *max98090)
 {
-       struct max98090_priv *max98090 =
-               container_of(work, struct max98090_priv, pll_work);
        struct snd_soc_component *component = max98090->component;
+       unsigned int pll;
+       int i;
 
        if (!snd_soc_component_is_active(component))
                return;
 
        dev_info_ratelimited(component->dev, "PLL unlocked\n");
 
+       /*
+        * As the datasheet suggested, the maximum PLL lock time should be
+        * 7 msec.  The workaround resets the codec softly by toggling SHDN
+        * off and on if PLL failed to lock for 10 msec.  Notably, there is
+        * no suggested hold time for SHDN off.
+        */
+
        /* Toggle shutdown OFF then ON */
        mutex_lock(&component->card->dapm_mutex);
        snd_soc_component_update_bits(component, M98090_REG_DEVICE_SHUTDOWN,
                            M98090_SHDNN_MASK, 0);
-       msleep(10);
        snd_soc_component_update_bits(component, M98090_REG_DEVICE_SHUTDOWN,
                            M98090_SHDNN_MASK, M98090_SHDNN_MASK);
        mutex_unlock(&component->card->dapm_mutex);
 
-       /* Give PLL time to lock */
-       msleep(10);
+       for (i = 0; i < 10; ++i) {
+               /* Give PLL time to lock */
+               usleep_range(1000, 1200);
+
+               /* Check lock status */
+               pll = snd_soc_component_read32(
+                               component, M98090_REG_DEVICE_STATUS);
+               if (!(pll & M98090_ULK_MASK))
+                       break;
+       }
 }
 
 static void max98090_jack_work(struct work_struct *work)
@@ -2452,7 +2466,7 @@ static irqreturn_t max98090_interrupt(int irq, void *data)
 
        if (active & M98090_ULK_MASK) {
                dev_dbg(component->dev, "M98090_ULK_MASK\n");
-               schedule_work(&max98090->pll_work);
+               max98090_pll_work(max98090);
        }
 
        if (active & M98090_JDET_MASK) {
@@ -2615,7 +2629,6 @@ static int max98090_probe(struct snd_soc_component *component)
                          max98090_pll_det_enable_work);
        INIT_WORK(&max98090->pll_det_disable_work,
                  max98090_pll_det_disable_work);
-       INIT_WORK(&max98090->pll_work, max98090_pll_work);
 
        /* Enable jack detection */
        snd_soc_component_write(component, M98090_REG_JACK_DETECT,
@@ -2678,7 +2691,6 @@ static void max98090_remove(struct snd_soc_component *component)
        cancel_delayed_work_sync(&max98090->jack_work);
        cancel_delayed_work_sync(&max98090->pll_det_enable_work);
        cancel_work_sync(&max98090->pll_det_disable_work);
-       cancel_work_sync(&max98090->pll_work);
        max98090->component = NULL;
 }