Merge tag 'for-f2fs-4.1' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk...
[firefly-linux-kernel-4.4.55.git] / sound / hda / hdac_device.c
index d4a0e723af2ca68f8c770ac03748e09e528324d2..f75bf56226878318130be8e383f5b91143e5d4c3 100644 (file)
@@ -494,33 +494,61 @@ EXPORT_SYMBOL_GPL(snd_hdac_get_connections);
 
 #ifdef CONFIG_PM
 /**
- * snd_hdac_power_up - increment the runtime pm counter
+ * snd_hdac_power_up - power up the codec
  * @codec: the codec object
+ *
+ * This function calls the runtime PM helper to power up the given codec.
+ * Unlike snd_hdac_power_up_pm(), you should call this only for the code
+ * path that isn't included in PM path.  Otherwise it gets stuck.
  */
 void snd_hdac_power_up(struct hdac_device *codec)
 {
-       struct device *dev = &codec->dev;
-
-       if (atomic_read(&codec->in_pm))
-               return;
-       pm_runtime_get_sync(dev);
+       pm_runtime_get_sync(&codec->dev);
 }
 EXPORT_SYMBOL_GPL(snd_hdac_power_up);
 
 /**
- * snd_hdac_power_up - decrement the runtime pm counter
+ * snd_hdac_power_down - power down the codec
  * @codec: the codec object
  */
 void snd_hdac_power_down(struct hdac_device *codec)
 {
        struct device *dev = &codec->dev;
 
-       if (atomic_read(&codec->in_pm))
-               return;
        pm_runtime_mark_last_busy(dev);
        pm_runtime_put_autosuspend(dev);
 }
 EXPORT_SYMBOL_GPL(snd_hdac_power_down);
+
+/**
+ * snd_hdac_power_up_pm - power up the codec
+ * @codec: the codec object
+ *
+ * This function can be called in a recursive code path like init code
+ * which may be called by PM suspend/resume again.  OTOH, if a power-up
+ * call must wake up the sleeper (e.g. in a kctl callback), use
+ * snd_hdac_power_up() instead.
+ */
+void snd_hdac_power_up_pm(struct hdac_device *codec)
+{
+       if (!atomic_inc_not_zero(&codec->in_pm))
+               snd_hdac_power_up(codec);
+}
+EXPORT_SYMBOL_GPL(snd_hdac_power_up_pm);
+
+/**
+ * snd_hdac_power_down_pm - power down the codec
+ * @codec: the codec object
+ *
+ * Like snd_hdac_power_up_pm(), this function is used in a recursive
+ * code path like init code which may be called by PM suspend/resume again.
+ */
+void snd_hdac_power_down_pm(struct hdac_device *codec)
+{
+       if (atomic_dec_if_positive(&codec->in_pm) < 0)
+               snd_hdac_power_down(codec);
+}
+EXPORT_SYMBOL_GPL(snd_hdac_power_down_pm);
 #endif
 
 /* codec vendor labels */