]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - sound/pci/hda/hda_codec.c
ALSA: hda - Use regmap for amp accesses
[karo-tx-linux.git] / sound / pci / hda / hda_codec.c
index 39b5660653f0f48ab161313fd4f798d0f67a7b7a..52962f697825b4297a87447c9e39305b37b7a667 100644 (file)
@@ -1543,139 +1543,6 @@ int snd_hda_override_pin_caps(struct hda_codec *codec, hda_nid_t nid,
 }
 EXPORT_SYMBOL_GPL(snd_hda_override_pin_caps);
 
-/* read or sync the hash value with the current value;
- * call within hash_mutex
- */
-static struct hda_amp_info *
-update_amp_hash(struct hda_codec *codec, hda_nid_t nid, int ch,
-               int direction, int index, bool init_only)
-{
-       struct hda_amp_info *info;
-       unsigned int parm, val = 0;
-       bool val_read = false;
-
- retry:
-       info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, index));
-       if (!info)
-               return NULL;
-       if (!(info->head.val & INFO_AMP_VOL(ch))) {
-               if (!val_read) {
-                       mutex_unlock(&codec->hash_mutex);
-                       parm = ch ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT;
-                       parm |= direction == HDA_OUTPUT ?
-                               AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT;
-                       parm |= index;
-                       val = snd_hda_codec_read(codec, nid, 0,
-                                AC_VERB_GET_AMP_GAIN_MUTE, parm);
-                       val &= 0xff;
-                       val_read = true;
-                       mutex_lock(&codec->hash_mutex);
-                       goto retry;
-               }
-               info->vol[ch] = val;
-               info->head.val |= INFO_AMP_VOL(ch);
-       } else if (init_only)
-               return NULL;
-       return info;
-}
-
-/*
- * write the current volume in info to the h/w
- */
-static void put_vol_mute(struct hda_codec *codec, unsigned int amp_caps,
-                        hda_nid_t nid, int ch, int direction, int index,
-                        int val)
-{
-       u32 parm;
-
-       parm = ch ? AC_AMP_SET_RIGHT : AC_AMP_SET_LEFT;
-       parm |= direction == HDA_OUTPUT ? AC_AMP_SET_OUTPUT : AC_AMP_SET_INPUT;
-       parm |= index << AC_AMP_SET_INDEX_SHIFT;
-       if ((val & HDA_AMP_MUTE) && !(amp_caps & AC_AMPCAP_MUTE) &&
-           (amp_caps & AC_AMPCAP_MIN_MUTE))
-               ; /* set the zero value as a fake mute */
-       else
-               parm |= val;
-       snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, parm);
-}
-
-/**
- * snd_hda_codec_amp_read - Read 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
- * @index: the index value (only for input direction)
- *
- * Read AMP value.  The volume is between 0 to 0x7f, 0x80 = mute bit.
- */
-int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch,
-                          int direction, int index)
-{
-       struct hda_amp_info *info;
-       unsigned int val = 0;
-
-       mutex_lock(&codec->hash_mutex);
-       info = update_amp_hash(codec, nid, ch, direction, index, false);
-       if (info)
-               val = info->vol[ch];
-       mutex_unlock(&codec->hash_mutex);
-       return val;
-}
-EXPORT_SYMBOL_GPL(snd_hda_codec_amp_read);
-
-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, bool cache_only)
-{
-       struct hda_amp_info *info;
-       unsigned int caps;
-
-       if (snd_BUG_ON(mask & ~0xff))
-               mask &= 0xff;
-       val &= mask;
-
-       mutex_lock(&codec->hash_mutex);
-       info = update_amp_hash(codec, nid, ch, direction, idx, init_only);
-       if (!info) {
-               mutex_unlock(&codec->hash_mutex);
-               return 0;
-       }
-       val |= info->vol[ch] & ~mask;
-       if (info->vol[ch] == val) {
-               mutex_unlock(&codec->hash_mutex);
-               return 0;
-       }
-       info->vol[ch] = val;
-       info->head.dirty |= cache_only;
-       caps = info->amp_caps;
-       mutex_unlock(&codec->hash_mutex);
-       if (!cache_only)
-               put_vol_mute(codec, caps, 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, codec->cached_write);
-}
-EXPORT_SYMBOL_GPL(snd_hda_codec_amp_update);
-
 /**
  * snd_hda_codec_amp_stereo - update the AMP stereo values
  * @codec: HD-audio codec
@@ -1719,8 +1586,16 @@ EXPORT_SYMBOL_GPL(snd_hda_codec_amp_stereo);
 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,
-                               codec->cached_write);
+       int orig;
+
+       if (!codec->core.regmap)
+               return -EINVAL;
+       regcache_cache_only(codec->core.regmap, true);
+       orig = snd_hda_codec_amp_read(codec, nid, ch, dir, idx);
+       regcache_cache_only(codec->core.regmap, false);
+       if (orig >= 0)
+               return 0;
+       return snd_hda_codec_amp_update(codec, nid, ch, dir, idx, mask, val);
 }
 EXPORT_SYMBOL_GPL(snd_hda_codec_amp_init);
 
@@ -1749,49 +1624,6 @@ int snd_hda_codec_amp_init_stereo(struct hda_codec *codec, hda_nid_t nid,
 }
 EXPORT_SYMBOL_GPL(snd_hda_codec_amp_init_stereo);
 
-/**
- * snd_hda_codec_resume_amp - Resume all AMP commands from the cache
- * @codec: HD-audio codec
- *
- * Resume the all amp commands from the cache.
- */
-void snd_hda_codec_resume_amp(struct hda_codec *codec)
-{
-       int i;
-
-       mutex_lock(&codec->hash_mutex);
-       codec->cached_write = 0;
-       for (i = 0; i < codec->amp_cache.buf.used; i++) {
-               struct hda_amp_info *buffer;
-               u32 key;
-               hda_nid_t nid;
-               unsigned int idx, dir, ch;
-               struct hda_amp_info info;
-
-               buffer = snd_array_elem(&codec->amp_cache.buf, i);
-               if (!buffer->head.dirty)
-                       continue;
-               buffer->head.dirty = 0;
-               info = *buffer;
-               key = info.head.key;
-               if (!key)
-                       continue;
-               nid = key & 0xff;
-               idx = (key >> 16) & 0xff;
-               dir = (key >> 24) & 0xff;
-               for (ch = 0; ch < 2; ch++) {
-                       if (!(info.head.val & INFO_AMP_VOL(ch)))
-                               continue;
-                       mutex_unlock(&codec->hash_mutex);
-                       put_vol_mute(codec, info.amp_caps, nid, ch, dir, idx,
-                                    info.vol[ch]);
-                       mutex_lock(&codec->hash_mutex);
-               }
-       }
-       mutex_unlock(&codec->hash_mutex);
-}
-EXPORT_SYMBOL_GPL(snd_hda_codec_resume_amp);
-
 static u32 get_amp_max_value(struct hda_codec *codec, hda_nid_t nid, int dir,
                             unsigned int ofs)
 {
@@ -1862,8 +1694,8 @@ update_amp_value(struct hda_codec *codec, hda_nid_t nid,
        maxval = get_amp_max_value(codec, nid, dir, 0);
        if (val > maxval)
                val = maxval;
-       return codec_amp_update(codec, nid, ch, dir, idx, HDA_AMP_VOLMASK, val,
-                               false, !hda_codec_is_power_on(codec));
+       return snd_hda_codec_amp_update(codec, nid, ch, dir, idx,
+                                       HDA_AMP_VOLMASK, val);
 }
 
 /**
@@ -2546,17 +2378,15 @@ int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
        int change = 0;
 
        if (chs & 1) {
-               change = codec_amp_update(codec, nid, 0, dir, idx,
-                                         HDA_AMP_MUTE,
-                                         *valp ? 0 : HDA_AMP_MUTE, false,
-                                         !hda_codec_is_power_on(codec));
+               change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
+                                                 HDA_AMP_MUTE,
+                                                 *valp ? 0 : HDA_AMP_MUTE);
                valp++;
        }
        if (chs & 2)
-               change |= codec_amp_update(codec, nid, 1, dir, idx,
-                                          HDA_AMP_MUTE,
-                                          *valp ? 0 : HDA_AMP_MUTE, false,
-                                          !hda_codec_is_power_on(codec));
+               change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx,
+                                                  HDA_AMP_MUTE,
+                                                  *valp ? 0 : HDA_AMP_MUTE);
        hda_call_check_power_status(codec, nid);
        return change;
 }
@@ -3417,7 +3247,8 @@ EXPORT_SYMBOL_GPL(snd_hda_sequence_write_cache);
  */
 void snd_hda_codec_flush_cache(struct hda_codec *codec)
 {
-       snd_hda_codec_resume_amp(codec);
+       if (codec->core.regmap)
+               regcache_sync(codec->core.regmap);
        snd_hda_codec_resume_cache(codec);
 }
 EXPORT_SYMBOL_GPL(snd_hda_codec_flush_cache);
@@ -3645,6 +3476,9 @@ static void hda_call_codec_resume(struct hda_codec *codec)
 {
        atomic_inc(&codec->core.in_pm);
 
+       if (codec->core.regmap)
+               regcache_mark_dirty(codec->core.regmap);
+
        hda_mark_cmd_cache_dirty(codec);
 
        codec->power_jiffies = jiffies;
@@ -3658,7 +3492,8 @@ static void hda_call_codec_resume(struct hda_codec *codec)
        else {
                if (codec->patch_ops.init)
                        codec->patch_ops.init(codec);
-               snd_hda_codec_resume_amp(codec);
+               if (codec->core.regmap)
+                       regcache_sync(codec->core.regmap);
                snd_hda_codec_resume_cache(codec);
        }