summaryrefslogtreecommitdiffstats
path: root/sound/pci
diff options
context:
space:
mode:
authorDavid Henningsson <david.henningsson@canonical.com>2013-01-16 15:58:44 +0100
committerTakashi Iwai <tiwai@suse.de>2013-01-16 16:24:00 +0100
commit99a5592d6a897eed447df1fac6b591c06c891858 (patch)
tree4695d3104dcf29f7675aa721ffaf3a5507e7829b /sound/pci
parent02aba550537a666b8d09346f39d6372c78b115a5 (diff)
downloadop-kernel-dev-99a5592d6a897eed447df1fac6b591c06c891858.zip
op-kernel-dev-99a5592d6a897eed447df1fac6b591c06c891858.tar.gz
ALSA: hda - force different capture controls if amp caps differ
Otherwise setting the capture volume for amps will be weird and inconsistent (it will try to set values outside the range of the second amp based on capabilities of the first amp). Signed-off-by: David Henningsson <david.henningsson@canonical.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci')
-rw-r--r--sound/pci/hda/hda_generic.c24
1 files changed, 21 insertions, 3 deletions
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 05dfeb7..171364a 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -484,6 +484,15 @@ static bool check_amp_caps(struct hda_codec *codec, hda_nid_t nid,
return false;
}
+static bool same_amp_caps(struct hda_codec *codec, hda_nid_t nid1,
+ hda_nid_t nid2, int dir)
+{
+ if (!(get_wcaps(codec, nid1) & (1 << (dir + 1))))
+ return !(get_wcaps(codec, nid2) & (1 << (dir + 1)));
+ return (query_amp_caps(codec, nid1, dir) ==
+ query_amp_caps(codec, nid2, dir));
+}
+
#define nid_has_mute(codec, nid, dir) \
check_amp_caps(codec, nid, dir, AC_AMPCAP_MUTE)
#define nid_has_volume(codec, nid, dir) \
@@ -2768,6 +2777,7 @@ static int create_capture_mixers(struct hda_codec *codec)
for (n = 0; n < nums; n++) {
bool multi = false;
+ bool multi_cap_vol = spec->multi_cap_vol;
bool inv_dmic = false;
int vol, sw;
@@ -2780,12 +2790,20 @@ static int create_capture_mixers(struct hda_codec *codec)
parse_capvol_in_path(codec, path);
if (!vol)
vol = path->ctls[NID_PATH_VOL_CTL];
- else if (vol != path->ctls[NID_PATH_VOL_CTL])
+ else if (vol != path->ctls[NID_PATH_VOL_CTL]) {
multi = true;
+ if (!same_amp_caps(codec, vol,
+ path->ctls[NID_PATH_VOL_CTL], HDA_INPUT))
+ multi_cap_vol = true;
+ }
if (!sw)
sw = path->ctls[NID_PATH_MUTE_CTL];
- else if (sw != path->ctls[NID_PATH_MUTE_CTL])
+ else if (sw != path->ctls[NID_PATH_MUTE_CTL]) {
multi = true;
+ if (!same_amp_caps(codec, sw,
+ path->ctls[NID_PATH_MUTE_CTL], HDA_INPUT))
+ multi_cap_vol = true;
+ }
if (is_inv_dmic_pin(codec, spec->imux_pins[i]))
inv_dmic = true;
}
@@ -2793,7 +2811,7 @@ static int create_capture_mixers(struct hda_codec *codec)
if (!multi)
err = create_single_cap_vol_ctl(codec, n, vol, sw,
inv_dmic);
- else if (!spec->multi_cap_vol)
+ else if (!multi_cap_vol)
err = create_bind_cap_vol_ctl(codec, n, vol, sw);
else
err = create_multi_cap_vol_ctl(codec);
OpenPOWER on IntegriCloud