diff options
author | Takashi Iwai <tiwai@suse.de> | 2015-06-11 04:51:28 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2015-06-11 05:55:48 -0400 |
commit | a686ec4c5f28eb1b384e4b87b08543155c970072 (patch) | |
tree | d35a87067360948ffad9e2dae8cfeb9d97d5925e | |
parent | bf06848bdbe549175d25d2327ab9f37d4bd556b7 (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.h | 2 | ||||
-rw-r--r-- | sound/hda/hdac_regmap.c | 5 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.c | 25 | ||||
-rw-r--r-- | sound/pci/hda/hda_local.h | 4 |
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 | |||
12 | int snd_hdac_regmap_init(struct hdac_device *codec); | 14 | int snd_hdac_regmap_init(struct hdac_device *codec); |
13 | void snd_hdac_regmap_exit(struct hdac_device *codec); | 15 | void snd_hdac_regmap_exit(struct hdac_device *codec); |
14 | int snd_hdac_regmap_add_vendor_verb(struct hdac_device *codec, | 16 | int 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, | |||
1376 | EXPORT_SYMBOL_GPL(snd_hda_override_amp_caps); | 1376 | EXPORT_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 | */ | ||
1390 | int 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 | } | ||
1401 | EXPORT_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) \ | 132 | int 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); |
134 | int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid, | 134 | int 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); |
136 | int snd_hda_codec_amp_init(struct hda_codec *codec, hda_nid_t nid, int ch, | 136 | int snd_hda_codec_amp_init(struct hda_codec *codec, hda_nid_t nid, int ch, |