Skip to content

Commit 3868137

Browse files
committed
ALSA: hda - Add a fake mute feature
Some codecs don't supply the mute amp-capabilities although the lowest volume gives the mute. It'd be handy if the parser provides the mute mixers in such a case. This patch adds an extension amp-cap bit (which is used only in the driver) to represent the min volume = mute state. Also modified the amp cache code to support the fake mute feature when this bit is set but the real mute bit is unset. In addition, conexant cx5051 parser uses this new feature to implement the missing mute controls. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=42825 Cc: <[email protected]> Signed-off-by: Takashi Iwai <[email protected]>
1 parent 7bff172 commit 3868137

File tree

3 files changed

+30
-3
lines changed

3 files changed

+30
-3
lines changed

sound/pci/hda/hda_codec.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1759,7 +1759,11 @@ static void put_vol_mute(struct hda_codec *codec, struct hda_amp_info *info,
17591759
parm = ch ? AC_AMP_SET_RIGHT : AC_AMP_SET_LEFT;
17601760
parm |= direction == HDA_OUTPUT ? AC_AMP_SET_OUTPUT : AC_AMP_SET_INPUT;
17611761
parm |= index << AC_AMP_SET_INDEX_SHIFT;
1762-
parm |= val;
1762+
if ((val & HDA_AMP_MUTE) && !(info->amp_caps & AC_AMPCAP_MUTE) &&
1763+
(info->amp_caps & AC_AMPCAP_MIN_MUTE))
1764+
; /* set the zero value as a fake mute */
1765+
else
1766+
parm |= val;
17631767
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, parm);
17641768
info->vol[ch] = val;
17651769
}
@@ -2026,7 +2030,7 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
20262030
val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT);
20272031
val1 += ofs;
20282032
val1 = ((int)val1) * ((int)val2);
2029-
if (min_mute)
2033+
if (min_mute || (caps & AC_AMPCAP_MIN_MUTE))
20302034
val2 |= TLV_DB_SCALE_MUTE;
20312035
if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv))
20322036
return -EFAULT;

sound/pci/hda/hda_codec.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,9 @@ enum {
298298
#define AC_AMPCAP_MUTE (1<<31) /* mute capable */
299299
#define AC_AMPCAP_MUTE_SHIFT 31
300300

301+
/* driver-specific amp-caps: using bits 24-30 */
302+
#define AC_AMPCAP_MIN_MUTE (1 << 30) /* min-volume = mute */
303+
301304
/* Connection list */
302305
#define AC_CLIST_LENGTH (0x7f<<0)
303306
#define AC_CLIST_LONG (1<<7)

sound/pci/hda/patch_conexant.c

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4079,7 +4079,8 @@ static int cx_auto_add_volume_idx(struct hda_codec *codec, const char *basename,
40794079
err = snd_hda_ctl_add(codec, nid, kctl);
40804080
if (err < 0)
40814081
return err;
4082-
if (!(query_amp_caps(codec, nid, hda_dir) & AC_AMPCAP_MUTE))
4082+
if (!(query_amp_caps(codec, nid, hda_dir) &
4083+
(AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE)))
40834084
break;
40844085
}
40854086
return 0;
@@ -4379,6 +4380,22 @@ static const struct snd_pci_quirk cxt_fixups[] = {
43794380
{}
43804381
};
43814382

4383+
/* add "fake" mute amp-caps to DACs on cx5051 so that mixer mute switches
4384+
* can be created (bko#42825)
4385+
*/
4386+
static void add_cx5051_fake_mutes(struct hda_codec *codec)
4387+
{
4388+
static hda_nid_t out_nids[] = {
4389+
0x10, 0x11, 0
4390+
};
4391+
hda_nid_t *p;
4392+
4393+
for (p = out_nids; *p; p++)
4394+
snd_hda_override_amp_caps(codec, *p, HDA_OUTPUT,
4395+
AC_AMPCAP_MIN_MUTE |
4396+
query_amp_caps(codec, *p, HDA_OUTPUT));
4397+
}
4398+
43824399
static int patch_conexant_auto(struct hda_codec *codec)
43834400
{
43844401
struct conexant_spec *spec;
@@ -4397,6 +4414,9 @@ static int patch_conexant_auto(struct hda_codec *codec)
43974414
case 0x14f15045:
43984415
spec->single_adc_amp = 1;
43994416
break;
4417+
case 0x14f15051:
4418+
add_cx5051_fake_mutes(codec);
4419+
break;
44004420
}
44014421

44024422
apply_pin_fixup(codec, cxt_fixups, cxt_pincfg_tbl);

0 commit comments

Comments
 (0)