diff --git a/arch/x86/configs/i386_greenridge_android_defconfig b/arch/x86/configs/i386_greenridge_android_defconfig
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 7a926c7..27896e5 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -395,6 +396,12 @@ struct azx {
 	int capture_index_offset;
 	int num_streams;
 
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+	unsigned char *running_stream_map;
+	/* count running streams for power down when all paused */
+	unsigned int running_stream_count;
+#endif
+
 	/* pci resources */
 	unsigned long addr;
 	void __iomem *remap_addr;
@@ -855,6 +862,9 @@ static unsigned int azx_get_response(struct hda_bus *bus,
 
 #ifdef CONFIG_SND_HDA_POWER_SAVE
 static void azx_power_notify(struct hda_bus *bus);
+static int azx_update_running_streams(struct azx *chip,
+				      int index,
+				      unsigned char state);
 #endif
 
 /* reset codec link */

@@ -1701,6 +1716,10 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 	struct snd_pcm_substream *s;
 	int rstart = 0, start, nsync = 0, sbits = 0;
 	int nwait, timeout;
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+	struct hda_codec *codec = apcm->codec;
+#endif
 
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
@@ -1727,6 +1747,13 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 		snd_pcm_trigger_done(s, substream);
 	}
 
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+	if (start && !codec->power_on) {
+		azx_init_chip(chip, 1);
+		snd_hda_power_up(codec);
+	}
+#endif
+
 	spin_lock(&chip->reg_lock);
 	if (nsync > 1) {
 		/* first, set SYNC bits of corresponding streams */
@@ -1746,7 +1773,14 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 			azx_stream_stop(chip, azx_dev);
 		}
 		azx_dev->running = start;
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+		azx_update_running_streams(chip, azx_dev->index, start);
+#endif
 	}
 	spin_unlock(&chip->reg_lock);
 	if (start) {
 		if (nsync == 1)
@@ -1789,6 +1823,23 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 		azx_writel(chip, SYNC, azx_readl(chip, SYNC) & ~sbits);
 		spin_unlock(&chip->reg_lock);
 	}
+
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+	if (!start && !chip->running_stream_count)
+		snd_hda_power_down(codec);
+#endif
+
 	return 0;
 }
 
@@ -2119,6 +2172,31 @@ static void azx_stop_chip(struct azx *chip)
 }
 
 #ifdef CONFIG_SND_HDA_POWER_SAVE
+/**
+ * azx_update_running_streams - update state for running streams
+ *
+ * Returns 1 if there's a diff in state.
+ */
+static int azx_update_running_streams(struct azx *chip,
+				      int index,
+				      unsigned char state)
+{
+	unsigned char old_state = chip->running_stream_map[index];
+
+	if (state == old_state)
+		/* nothing changed */
+		return 0;
+
+	chip->running_stream_map[index] = state;
+
+	if (state)
+		chip->running_stream_count++;
+	else
+		chip->running_stream_count--;
+
+	return 1;
+}
+
 /* power-up/down the controller */
 static void azx_power_notify(struct hda_bus *bus)
 {
@@ -2126,16 +2204,41 @@ static void azx_power_notify(struct hda_bus *bus)
 	struct hda_codec *c;
 	int power_on = 0;
+
+	/* Codecs can be powered down if all streams are paused/suspended and
+	 * codec refcount is 1, since pcms are opened.
+	 */
 	list_for_each_entry(c, &bus->codec_list, list) {
+		if (c->power_on) {
+			if (!chip->running_stream_count && (c->power_count <= 1)) {
+				printk("\tpowering down codec:\n");
+				snd_hda_power_down(c);
+			} else {
+				power_on = 1;
+				break;
+			}
+		}
-		if (c->power_on) {
-			power_on = 1;
-			break;
-		}
 	}
 	if (power_on)
 		azx_init_chip(chip, 1);
 	else if (chip->running && power_save_controller &&
 		 !bus->power_keep_link_on)
 		azx_stop_chip(chip);
 }
 #endif /* CONFIG_SND_HDA_POWER_SAVE */
@@ -2269,6 +2372,9 @@ static int azx_free(struct azx *chip)
 		snd_dma_free_pages(&chip->posbuf);
 	pci_release_regions(chip->pci);
 	pci_disable_device(chip->pci);
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+	kfree(chip->running_stream_map);
+#endif
 	kfree(chip->azx_dev);
 	kfree(chip);
 
@@ -2578,6 +2684,17 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
 		goto errout;
 	}
 
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+	chip->running_stream_map = kcalloc(chip->num_streams,
+					   sizeof(*chip->running_stream_map),
+					   GFP_KERNEL);
+	if (!chip->running_stream_map) {
+		snd_printk(KERN_ERR SFX "can't malloc running_stream_map\n");
+		kfree(chip->azx_dev);
+		goto errout;
+	}
+#endif
+
 	for (i = 0; i < chip->num_streams; i++) {
 		/* allocate memory for the BDL for each stream */
 		err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,