*/
 static struct hda_amp_info *
 update_amp_hash(struct hda_codec *codec, hda_nid_t nid, int ch,
-               int direction, int index)
+               int direction, int index, bool init_only)
 {
        struct hda_amp_info *info;
        unsigned int parm, val = 0;
                }
                info->vol[ch] = val;
                info->head.val |= INFO_AMP_VOL(ch);
-       }
+       } else if (init_only)
+               return NULL;
        return info;
 }
 
        unsigned int val = 0;
 
        mutex_lock(&codec->hash_mutex);
-       info = update_amp_hash(codec, nid, ch, direction, index);
+       info = update_amp_hash(codec, nid, ch, direction, index, false);
        if (info)
                val = info->vol[ch];
        mutex_unlock(&codec->hash_mutex);
 }
 EXPORT_SYMBOL_HDA(snd_hda_codec_amp_read);
 
-/**
- * snd_hda_codec_amp_update - update the AMP value
- * @codec: HD-audio codec
- * @nid: NID to read the AMP value
- * @ch: channel (left=0 or right=1)
- * @direction: #HDA_INPUT or #HDA_OUTPUT
- * @idx: the index value (only for input direction)
- * @mask: bit mask to set
- * @val: the bits value to set
- *
- * Update the AMP value with a bit mask.
- * Returns 0 if the value is unchanged, 1 if changed.
- */
-int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
-                            int direction, int idx, int mask, int val)
+static int codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
+                           int direction, int idx, int mask, int val,
+                           bool init_only)
 {
        struct hda_amp_info *info;
 
        val &= mask;
 
        mutex_lock(&codec->hash_mutex);
-       info = update_amp_hash(codec, nid, ch, direction, idx);
+       info = update_amp_hash(codec, nid, ch, direction, idx, init_only);
        if (!info) {
                mutex_unlock(&codec->hash_mutex);
                return 0;
                put_vol_mute(codec, info, nid, ch, direction, idx, val);
        return 1;
 }
+
+/**
+ * snd_hda_codec_amp_update - update the AMP value
+ * @codec: HD-audio codec
+ * @nid: NID to read the AMP value
+ * @ch: channel (left=0 or right=1)
+ * @direction: #HDA_INPUT or #HDA_OUTPUT
+ * @idx: the index value (only for input direction)
+ * @mask: bit mask to set
+ * @val: the bits value to set
+ *
+ * Update the AMP value with a bit mask.
+ * Returns 0 if the value is unchanged, 1 if changed.
+ */
+int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
+                            int direction, int idx, int mask, int val)
+{
+       return codec_amp_update(codec, nid, ch, direction, idx, mask, val, false);
+}
 EXPORT_SYMBOL_HDA(snd_hda_codec_amp_update);
 
 /**
 }
 EXPORT_SYMBOL_HDA(snd_hda_codec_amp_stereo);
 
+/* Works like snd_hda_codec_amp_update() but it writes the value only at
+ * the first access.  If the amp was already initialized / updated beforehand,
+ * this does nothing.
+ */
+int snd_hda_codec_amp_init(struct hda_codec *codec, hda_nid_t nid, int ch,
+                          int dir, int idx, int mask, int val)
+{
+       return codec_amp_update(codec, nid, ch, dir, idx, mask, val, true);
+}
+EXPORT_SYMBOL_HDA(snd_hda_codec_amp_init);
+
+int snd_hda_codec_amp_init_stereo(struct hda_codec *codec, hda_nid_t nid,
+                                 int dir, int idx, int mask, int val)
+{
+       int ch, ret = 0;
+
+       if (snd_BUG_ON(mask & ~0xff))
+               mask &= 0xff;
+       for (ch = 0; ch < 2; ch++)
+               ret |= snd_hda_codec_amp_init(codec, nid, ch, dir,
+                                             idx, mask, val);
+       return ret;
+}
+EXPORT_SYMBOL_HDA(snd_hda_codec_amp_init_stereo);
+
 /**
  * snd_hda_codec_resume_amp - Resume all AMP commands from the cache
  * @codec: HD-audio codec