aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2015-06-11 04:51:28 -0400
committerTakashi Iwai <tiwai@suse.de>2015-06-11 05:55:48 -0400
commita686ec4c5f28eb1b384e4b87b08543155c970072 (patch)
treed35a87067360948ffad9e2dae8cfeb9d97d5925e
parentbf06848bdbe549175d25d2327ab9f37d4bd556b7 (diff)
ALSA: hda - Re-add the lost fake mute support
Yet another regression by the transition to regmap cache; for better usability, we had the fake mute control using the zero amp value for Conexant codecs, and this was forgotten in the new hda core code. Since the bits 4-7 are unused for the amp registers (as we follow the syntax of AMP_GET verb), the bit 4 is now used to indicate the fake mute. For setting this flag, snd_hda_codec_amp_update() becomes a function from a simple macro. The bonus is that it gained a proper function description. Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--include/sound/hda_regmap.h2
-rw-r--r--sound/hda/hdac_regmap.c5
-rw-r--r--sound/pci/hda/hda_codec.c25
-rw-r--r--sound/pci/hda/hda_local.h4
4 files changed, 34 insertions, 2 deletions
diff --git a/include/sound/hda_regmap.h b/include/sound/hda_regmap.h
index 53a18b3635e2..df705908480a 100644
--- a/include/sound/hda_regmap.h
+++ b/include/sound/hda_regmap.h
@@ -9,6 +9,8 @@
9#include <sound/core.h> 9#include <sound/core.h>
10#include <sound/hdaudio.h> 10#include <sound/hdaudio.h>
11 11
12#define AC_AMP_FAKE_MUTE 0x10 /* fake mute bit set to amp verbs */
13
12int snd_hdac_regmap_init(struct hdac_device *codec); 14int snd_hdac_regmap_init(struct hdac_device *codec);
13void snd_hdac_regmap_exit(struct hdac_device *codec); 15void snd_hdac_regmap_exit(struct hdac_device *codec);
14int snd_hdac_regmap_add_vendor_verb(struct hdac_device *codec, 16int snd_hdac_regmap_add_vendor_verb(struct hdac_device *codec,
diff --git a/sound/hda/hdac_regmap.c b/sound/hda/hdac_regmap.c
index c4f5e61d4404..1eabcdf69457 100644
--- a/sound/hda/hdac_regmap.c
+++ b/sound/hda/hdac_regmap.c
@@ -246,6 +246,9 @@ static int hda_reg_read(void *context, unsigned int reg, unsigned int *val)
246 return hda_reg_read_stereo_amp(codec, reg, val); 246 return hda_reg_read_stereo_amp(codec, reg, val);
247 if (verb == AC_VERB_GET_PROC_COEF) 247 if (verb == AC_VERB_GET_PROC_COEF)
248 return hda_reg_read_coef(codec, reg, val); 248 return hda_reg_read_coef(codec, reg, val);
249 if ((verb & 0x700) == AC_VERB_SET_AMP_GAIN_MUTE)
250 reg &= ~AC_AMP_FAKE_MUTE;
251
249 err = snd_hdac_exec_verb(codec, reg, 0, val); 252 err = snd_hdac_exec_verb(codec, reg, 0, val);
250 if (err < 0) 253 if (err < 0)
251 return err; 254 return err;
@@ -283,6 +286,8 @@ static int hda_reg_write(void *context, unsigned int reg, unsigned int val)
283 286
284 switch (verb & 0xf00) { 287 switch (verb & 0xf00) {
285 case AC_VERB_SET_AMP_GAIN_MUTE: 288 case AC_VERB_SET_AMP_GAIN_MUTE:
289 if ((reg & AC_AMP_FAKE_MUTE) && (val & AC_AMP_MUTE))
290 val = 0;
286 verb = AC_VERB_SET_AMP_GAIN_MUTE; 291 verb = AC_VERB_SET_AMP_GAIN_MUTE;
287 if (reg & AC_AMP_GET_LEFT) 292 if (reg & AC_AMP_GET_LEFT)
288 verb |= AC_AMP_SET_LEFT >> 8; 293 verb |= AC_AMP_SET_LEFT >> 8;
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index b7782212dd64..5645481af3d9 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -1376,6 +1376,31 @@ int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
1376EXPORT_SYMBOL_GPL(snd_hda_override_amp_caps); 1376EXPORT_SYMBOL_GPL(snd_hda_override_amp_caps);
1377 1377
1378/** 1378/**
1379 * snd_hda_codec_amp_update - update the AMP mono value
1380 * @codec: HD-audio codec
1381 * @nid: NID to read the AMP value
1382 * @ch: channel to update (0 or 1)
1383 * @dir: #HDA_INPUT or #HDA_OUTPUT
1384 * @idx: the index value (only for input direction)
1385 * @mask: bit mask to set
1386 * @val: the bits value to set
1387 *
1388 * Update the AMP values for the given channel, direction and index.
1389 */
1390int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid,
1391 int ch, int dir, int idx, int mask, int val)
1392{
1393 unsigned int cmd = snd_hdac_regmap_encode_amp(nid, ch, dir, idx);
1394
1395 /* enable fake mute if no h/w mute but min=mute */
1396 if ((query_amp_caps(codec, nid, dir) &
1397 (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE)) == AC_AMPCAP_MIN_MUTE)
1398 cmd |= AC_AMP_FAKE_MUTE;
1399 return snd_hdac_regmap_update_raw(&codec->core, cmd, mask, val);
1400}
1401EXPORT_SYMBOL_GPL(snd_hda_codec_amp_update);
1402
1403/**
1379 * snd_hda_codec_amp_stereo - update the AMP stereo values 1404 * snd_hda_codec_amp_stereo - update the AMP stereo values
1380 * @codec: HD-audio codec 1405 * @codec: HD-audio codec
1381 * @nid: NID to read the AMP value 1406 * @nid: NID to read the AMP value
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index 3b567f42296b..bed66c314431 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -129,8 +129,8 @@ int snd_hda_mixer_amp_switch_put_beep(struct snd_kcontrol *kcontrol,
129/* lowlevel accessor with caching; use carefully */ 129/* lowlevel accessor with caching; use carefully */
130#define snd_hda_codec_amp_read(codec, nid, ch, dir, idx) \ 130#define snd_hda_codec_amp_read(codec, nid, ch, dir, idx) \
131 snd_hdac_regmap_get_amp(&(codec)->core, nid, ch, dir, idx) 131 snd_hdac_regmap_get_amp(&(codec)->core, nid, ch, dir, idx)
132#define snd_hda_codec_amp_update(codec, nid, ch, dir, idx, mask, val) \ 132int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid,
133 snd_hdac_regmap_update_amp(&(codec)->core, nid, ch, dir, idx, mask, val) 133 int ch, int dir, int idx, int mask, int val);
134int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid, 134int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
135 int dir, int idx, int mask, int val); 135 int dir, int idx, int mask, int val);
136int snd_hda_codec_amp_init(struct hda_codec *codec, hda_nid_t nid, int ch, 136int snd_hda_codec_amp_init(struct hda_codec *codec, hda_nid_t nid, int ch,