ALSA: hda - Sync node attributes at resume from widget power saving
authorTakashi Iwai <tiwai@suse.de>
Sat, 4 Apr 2015 10:17:28 +0000 (12:17 +0200)
committerTakashi Iwai <tiwai@suse.de>
Sat, 4 Apr 2015 10:22:52 +0000 (12:22 +0200)
So far we assumed that the node attributes like amp values remain
during the power state transition of the node itself.  While this is
true for IDT/STAC codecs I've tested, but some other codecs don't seem
behaving in that way.

This patch implements a partial sync mechanism specific to the given
widget node.  Now we've merged the regmap support, and it can be
easily written with regcache_sync_region().

Tested-by: Hui Wang <hui.wang@canonical.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
include/sound/hda_regmap.h
sound/pci/hda/hda_generic.c

index 76648ccfbbf89884512db743026d09caec88140d..53a18b3635e24a458700a21566c56a10d0704c56 100644 (file)
@@ -202,4 +202,16 @@ snd_hdac_regmap_update_amp_stereo(struct hdac_device *codec, hda_nid_t nid,
        return snd_hdac_regmap_update_raw(codec, cmd, mask, val);
 }
 
+/**
+ * snd_hdac_regmap_sync_node - sync the widget node attributes
+ * @codec: HD-audio codec
+ * @nid: NID to sync
+ */
+static inline void
+snd_hdac_regmap_sync_node(struct hdac_device *codec, hda_nid_t nid)
+{
+       regcache_mark_dirty(codec->regmap);
+       regcache_sync_region(codec->regmap, nid << 20, ((nid + 1) << 20) - 1);
+}
+
 #endif /* __SOUND_HDA_REGMAP_H */
index f7ccef5559deac7e77d5f5bc7fe1b155d5f17d30..1f2ca7be146860d015608ad6dea1af8938d3a8a1 100644 (file)
@@ -842,10 +842,8 @@ static hda_nid_t path_power_update(struct hda_codec *codec,
                        snd_hda_codec_write(codec, nid, 0,
                                            AC_VERB_SET_POWER_STATE, state);
                        changed = nid;
-                       /* here we assume that widget attributes (e.g. amp,
-                        * pinctl connection) don't change with local power
-                        * state change.  If not, need to sync the cache.
-                        */
+                       if (state == AC_PWRST_D0)
+                               snd_hdac_regmap_sync_node(&codec->core, nid);
                }
        }
        return changed;