#ifdef CONFIG_SND_HDA_POWER_SAVE
        cancel_delayed_work(&codec->power_work);
        codec->power_on = 0;
+       codec->power_transition = 0;
 #endif
 }
 
 void snd_hda_power_up(struct hda_codec *codec)
 {
        codec->power_count++;
-       if (codec->power_on)
+       if (codec->power_on || codec->power_transition)
                return;
 
        codec->power_on = 1;
                codec->bus->ops.pm_notify(codec);
        hda_call_codec_resume(codec);
        cancel_delayed_work(&codec->power_work);
+       codec->power_transition = 0;
 }
 
 void snd_hda_power_down(struct hda_codec *codec)
 {
        --codec->power_count;
-       if (!codec->power_on || codec->power_count)
+       if (!codec->power_on || codec->power_count || codec->power_transition)
                return;
-       if (power_save)
+       if (power_save) {
+               codec->power_transition = 1; /* avoid reentrance */
                schedule_delayed_work(&codec->power_work,
                                      msecs_to_jiffies(power_save * 1000));
+       }
 }
 
 int snd_hda_check_amp_list_power(struct hda_codec *codec,
 
        struct snd_hwdep *hwdep;        /* assigned hwdep device */
 
 #ifdef CONFIG_SND_HDA_POWER_SAVE
-       int power_on;           /* current (global) power-state */
+       unsigned int power_on :1;       /* current (global) power-state */
+       unsigned int power_transition :1; /* power-state in transition */
        int power_count;        /* current (global) power refcount */
        struct delayed_work power_work; /* delayed task for powerdown */
 #endif