ALSA: hda - Implement snd_hda_power_sync() helper function
authorTakashi Iwai <tiwai@suse.de>
Tue, 14 Aug 2012 15:12:47 +0000 (17:12 +0200)
committerTakashi Iwai <tiwai@suse.de>
Mon, 20 Aug 2012 09:46:05 +0000 (11:46 +0200)
Added a new helper function snd_hda_power_sync() to trigger the
power-saving manually.  It's an inline function call to
snd_hda_power_save() helper function.

Together with this addition, snd_hda_power_up*() and
snd_hda_power_down() functions are inlined to a call of the same
snd_hda_power_save() helper function.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_codec.h

index ad0101e2d4ffea059b68723d4cc8d4d977318aa7..5e0bdea6c5c8b99a361c3adb92cc7451c181bf50 100644 (file)
@@ -4411,20 +4411,16 @@ void snd_hda_update_power_acct(struct hda_codec *codec)
 /* Transition to powered up, if wait_power_down then wait for a pending
  * transition to D3 to complete. A pending D3 transition is indicated
  * with power_transition == -1. */
+/* call this with codec->power_lock held! */
 static void __snd_hda_power_up(struct hda_codec *codec, bool wait_power_down)
 {
        struct hda_bus *bus = codec->bus;
 
-       spin_lock(&codec->power_lock);
-       codec->power_count++;
-       trace_hda_power_count(codec);
        /* Return if power_on or transitioning to power_on, unless currently
         * powering down. */
        if ((codec->power_on || codec->power_transition > 0) &&
-           !(wait_power_down && codec->power_transition < 0)) {
-               spin_unlock(&codec->power_lock);
+           !(wait_power_down && codec->power_transition < 0))
                return;
-       }
        spin_unlock(&codec->power_lock);
 
        cancel_delayed_work_sync(&codec->power_work);
@@ -4433,10 +4429,9 @@ static void __snd_hda_power_up(struct hda_codec *codec, bool wait_power_down)
        /* If the power down delayed work was cancelled above before starting,
         * then there is no need to go through power up here.
         */
-       if (codec->power_on) {
-               spin_unlock(&codec->power_lock);
+       if (codec->power_on)
                return;
-       }
+
        trace_hda_power_up(codec);
        snd_hda_update_power_acct(codec);
        codec->power_on = 1;
@@ -4450,66 +4445,45 @@ static void __snd_hda_power_up(struct hda_codec *codec, bool wait_power_down)
 
        spin_lock(&codec->power_lock);
        codec->power_transition = 0;
-       spin_unlock(&codec->power_lock);
 }
 
-/**
- * snd_hda_power_up - Power-up the codec
- * @codec: HD-audio codec
- *
- * Increment the power-up counter and power up the hardware really when
- * not turned on yet.
- */
-void snd_hda_power_up(struct hda_codec *codec)
-{
-       __snd_hda_power_up(codec, false);
-}
-EXPORT_SYMBOL_HDA(snd_hda_power_up);
+#define power_save(codec)      \
+       ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
 
-/**
- * snd_hda_power_up_d3wait - Power-up the codec after waiting for any pending
- *   D3 transition to complete.  This differs from snd_hda_power_up() when
- *   power_transition == -1.  snd_hda_power_up sees this case as a nop,
- *   snd_hda_power_up_d3wait waits for the D3 transition to complete then powers
- *   back up.
- * @codec: HD-audio codec
- *
- * Cancel any power down operation hapenning on the work queue, then power up.
- */
-void snd_hda_power_up_d3wait(struct hda_codec *codec)
+/* Transition to powered down */
+static void __snd_hda_power_down(struct hda_codec *codec)
 {
-       /* This will cancel and wait for pending power_work to complete. */
-       __snd_hda_power_up(codec, true);
-}
-EXPORT_SYMBOL_HDA(snd_hda_power_up_d3wait);
+       if (!codec->power_on || codec->power_count || codec->power_transition)
+               return;
 
-#define power_save(codec)      \
-       ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
+       if (power_save(codec)) {
+               codec->power_transition = -1; /* avoid reentrance */
+               queue_delayed_work(codec->bus->workq, &codec->power_work,
+                               msecs_to_jiffies(power_save(codec) * 1000));
+       }
+}
 
 /**
- * snd_hda_power_down - Power-down the codec
+ * snd_hda_power_save - Power-up/down/sync the codec
  * @codec: HD-audio codec
+ * @delta: the counter delta to change
  *
- * Decrement the power-up counter and schedules the power-off work if
- * the counter rearches to zero.
+ * Change the power-up counter via @delta, and power up or down the hardware
+ * appropriately.  For the power-down, queue to the delayed action.
+ * Passing zero to @delta means to synchronize the power state.
  */
-void snd_hda_power_down(struct hda_codec *codec)
+void snd_hda_power_save(struct hda_codec *codec, int delta, bool d3wait)
 {
        spin_lock(&codec->power_lock);
-       --codec->power_count;
+       codec->power_count += delta;
        trace_hda_power_count(codec);
-       if (!codec->power_on || codec->power_count || codec->power_transition) {
-               spin_unlock(&codec->power_lock);
-               return;
-       }
-       if (power_save(codec)) {
-               codec->power_transition = -1; /* avoid reentrance */
-               queue_delayed_work(codec->bus->workq, &codec->power_work,
-                               msecs_to_jiffies(power_save(codec) * 1000));
-       }
+       if (delta > 0)
+               __snd_hda_power_up(codec, d3wait);
+       else
+               __snd_hda_power_down(codec);
        spin_unlock(&codec->power_lock);
 }
-EXPORT_SYMBOL_HDA(snd_hda_power_down);
+EXPORT_SYMBOL_HDA(snd_hda_power_save);
 
 /**
  * snd_hda_check_amp_list_power - Check the amp list and update the power
index d772c2521cd9014268a3d2a067c688058b860f1a..1d4dfce631a0f1900d17132db2d7e0f19d32f985 100644 (file)
@@ -1062,16 +1062,64 @@ const char *snd_hda_get_jack_location(u32 cfg);
  * power saving
  */
 #ifdef CONFIG_SND_HDA_POWER_SAVE
-void snd_hda_power_up(struct hda_codec *codec);
-void snd_hda_power_up_d3wait(struct hda_codec *codec);
-void snd_hda_power_down(struct hda_codec *codec);
+void snd_hda_power_save(struct hda_codec *codec, int delta, bool d3wait);
 void snd_hda_update_power_acct(struct hda_codec *codec);
 #else
-static inline void snd_hda_power_up(struct hda_codec *codec) {}
-static inline void snd_hda_power_up_d3wait(struct hda_codec *codec) {}
-static inline void snd_hda_power_down(struct hda_codec *codec) {}
+static inline void snd_hda_power_save(struct hda_codec *codec, int delta,
+                                     bool d3wait) {}
 #endif
 
+/**
+ * snd_hda_power_up - Power-up the codec
+ * @codec: HD-audio codec
+ *
+ * Increment the power-up counter and power up the hardware really when
+ * not turned on yet.
+ */
+static inline void snd_hda_power_up(struct hda_codec *codec)
+{
+       snd_hda_power_save(codec, 1, false);
+}
+
+/**
+ * snd_hda_power_up_d3wait - Power-up the codec after waiting for any pending
+ *   D3 transition to complete.  This differs from snd_hda_power_up() when
+ *   power_transition == -1.  snd_hda_power_up sees this case as a nop,
+ *   snd_hda_power_up_d3wait waits for the D3 transition to complete then powers
+ *   back up.
+ * @codec: HD-audio codec
+ *
+ * Cancel any power down operation hapenning on the work queue, then power up.
+ */
+static inline void snd_hda_power_up_d3wait(struct hda_codec *codec)
+{
+       snd_hda_power_save(codec, 1, true);
+}
+
+/**
+ * snd_hda_power_down - Power-down the codec
+ * @codec: HD-audio codec
+ *
+ * Decrement the power-up counter and schedules the power-off work if
+ * the counter rearches to zero.
+ */
+static inline void snd_hda_power_down(struct hda_codec *codec)
+{
+       snd_hda_power_save(codec, -1, false);
+}
+
+/**
+ * snd_hda_power_sync - Synchronize the power-save status
+ * @codec: HD-audio codec
+ *
+ * Synchronize the actual power state with the power account;
+ * called when power_save parameter is changed
+ */
+static inline void snd_hda_power_sync(struct hda_codec *codec)
+{
+       snd_hda_power_save(codec, 0, false);
+}
+
 #ifdef CONFIG_SND_HDA_PATCH_LOADER
 /*
  * patch firmware