Skip to content

Commit

Permalink
ALSA: hda - Add a fake mute feature
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
tiwai committed Feb 29, 2012
1 parent 7bff172 commit 3868137
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 3 deletions.
8 changes: 6 additions & 2 deletions sound/pci/hda/hda_codec.c
Original file line number Diff line number Diff line change
Expand Up @@ -1759,7 +1759,11 @@ static void put_vol_mute(struct hda_codec *codec, struct hda_amp_info *info,
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;
parm |= val;
if ((val & HDA_AMP_MUTE) && !(info->amp_caps & AC_AMPCAP_MUTE) &&
(info->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);
info->vol[ch] = val;
}
Expand Down Expand Up @@ -2026,7 +2030,7 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT);
val1 += ofs;
val1 = ((int)val1) * ((int)val2);
if (min_mute)
if (min_mute || (caps & AC_AMPCAP_MIN_MUTE))
val2 |= TLV_DB_SCALE_MUTE;
if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv))
return -EFAULT;
Expand Down
3 changes: 3 additions & 0 deletions sound/pci/hda/hda_codec.h
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,9 @@ enum {
#define AC_AMPCAP_MUTE (1<<31) /* mute capable */
#define AC_AMPCAP_MUTE_SHIFT 31

/* driver-specific amp-caps: using bits 24-30 */
#define AC_AMPCAP_MIN_MUTE (1 << 30) /* min-volume = mute */

/* Connection list */
#define AC_CLIST_LENGTH (0x7f<<0)
#define AC_CLIST_LONG (1<<7)
Expand Down
22 changes: 21 additions & 1 deletion sound/pci/hda/patch_conexant.c
Original file line number Diff line number Diff line change
Expand Up @@ -4079,7 +4079,8 @@ static int cx_auto_add_volume_idx(struct hda_codec *codec, const char *basename,
err = snd_hda_ctl_add(codec, nid, kctl);
if (err < 0)
return err;
if (!(query_amp_caps(codec, nid, hda_dir) & AC_AMPCAP_MUTE))
if (!(query_amp_caps(codec, nid, hda_dir) &
(AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE)))
break;
}
return 0;
Expand Down Expand Up @@ -4379,6 +4380,22 @@ static const struct snd_pci_quirk cxt_fixups[] = {
{}
};

/* add "fake" mute amp-caps to DACs on cx5051 so that mixer mute switches
* can be created (bko#42825)
*/
static void add_cx5051_fake_mutes(struct hda_codec *codec)
{
static hda_nid_t out_nids[] = {
0x10, 0x11, 0
};
hda_nid_t *p;

for (p = out_nids; *p; p++)
snd_hda_override_amp_caps(codec, *p, HDA_OUTPUT,
AC_AMPCAP_MIN_MUTE |
query_amp_caps(codec, *p, HDA_OUTPUT));
}

static int patch_conexant_auto(struct hda_codec *codec)
{
struct conexant_spec *spec;
Expand All @@ -4397,6 +4414,9 @@ static int patch_conexant_auto(struct hda_codec *codec)
case 0x14f15045:
spec->single_adc_amp = 1;
break;
case 0x14f15051:
add_cx5051_fake_mutes(codec);
break;
}

apply_pin_fixup(codec, cxt_fixups, cxt_pincfg_tbl);
Expand Down

0 comments on commit 3868137

Please sign in to comment.