Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ALSA: hda - Fix invalid multi-io creation on VAIO-Z laptops

VAIO-Z laptops need to use the specific DAC for the speaker output
by some unknown reason although the codec itself supports the flexible
connection. So we implemented a workaround by a new flag,
no_primary_hp, for assigning the speaker pin first.

This worked until 3.8 kernel, but it got broken because the driver
learned for a better multi-io pin mapping, and not it can assign two
mic pins for multi-io. Since the multi-io requires to be the primary
output, the hp and two mic pins are assigned in prior to the speaker
in the end.

Although the machine has two mic pins, one of them is used as a noise-
canceling headphone, thus it's no real retaskable mic jack. Thus, at
best, we can disable the multi-io assignment and make the parser
behavior back to the state before the multi-io.

This patch adds again a new flag, no_multi_io, to indicate that the
device has no multi-io capability, and set it in the fixup for
VAIO-Z. The no_multi_io flag itself can be used generically, added
via a helper line, too.

Reported-by: Tormen <my.nl.abos@gmail.com>
Reported-by: Adam Williamson <awilliam@redhat.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>

+16 -5
+2
Documentation/sound/alsa/HD-Audio.txt
··· 454 454 - need_dac_fix (bool): limits the DACs depending on the channel count 455 455 - primary_hp (bool): probe headphone jacks as the primary outputs; 456 456 default true 457 + - multi_io (bool): try probing multi-I/O config (e.g. shared 458 + line-in/surround, mic/clfe jacks) 457 459 - multi_cap_vol (bool): provide multiple capture volumes 458 460 - inv_dmic_split (bool): provide split internal mic volume/switch for 459 461 phase-inverted digital mics
+10 -4
sound/pci/hda/hda_generic.c
··· 142 142 val = snd_hda_get_bool_hint(codec, "primary_hp"); 143 143 if (val >= 0) 144 144 spec->no_primary_hp = !val; 145 + val = snd_hda_get_bool_hint(codec, "multi_io"); 146 + if (val >= 0) 147 + spec->no_multi_io = !val; 145 148 val = snd_hda_get_bool_hint(codec, "multi_cap_vol"); 146 149 if (val >= 0) 147 150 spec->multi_cap_vol = !!val; ··· 1544 1541 cfg->speaker_pins, 1545 1542 spec->multiout.extra_out_nid, 1546 1543 spec->speaker_paths); 1547 - if (fill_mio_first && cfg->line_outs == 1 && 1544 + if (!spec->no_multi_io && 1545 + fill_mio_first && cfg->line_outs == 1 && 1548 1546 cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { 1549 1547 err = fill_multi_ios(codec, cfg->line_out_pins[0], true); 1550 1548 if (!err) ··· 1558 1554 spec->private_dac_nids, spec->out_paths, 1559 1555 spec->main_out_badness); 1560 1556 1561 - if (fill_mio_first && 1557 + if (!spec->no_multi_io && fill_mio_first && 1562 1558 cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { 1563 1559 /* try to fill multi-io first */ 1564 1560 err = fill_multi_ios(codec, cfg->line_out_pins[0], false); ··· 1586 1582 return err; 1587 1583 badness += err; 1588 1584 } 1589 - if (cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { 1585 + if (!spec->no_multi_io && 1586 + cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { 1590 1587 err = fill_multi_ios(codec, cfg->line_out_pins[0], false); 1591 1588 if (err < 0) 1592 1589 return err; ··· 1605 1600 check_aamix_out_path(codec, spec->speaker_paths[0]); 1606 1601 } 1607 1602 1608 - if (cfg->hp_outs && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) 1603 + if (!spec->no_multi_io && 1604 + cfg->hp_outs && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) 1609 1605 if (count_multiio_pins(codec, cfg->hp_pins[0]) >= 2) 1610 1606 spec->multi_ios = 1; /* give badness */ 1611 1607
+1
sound/pci/hda/hda_generic.h
··· 220 220 unsigned int hp_mic:1; /* Allow HP as a mic-in */ 221 221 unsigned int suppress_hp_mic_detect:1; /* Don't detect HP/mic */ 222 222 unsigned int no_primary_hp:1; /* Don't prefer HP pins to speaker pins */ 223 + unsigned int no_multi_io:1; /* Don't try multi I/O config */ 223 224 unsigned int multi_cap_vol:1; /* allow multiple capture xxx volumes */ 224 225 unsigned int inv_dmic_split:1; /* inverted dmic w/a for conexant */ 225 226 unsigned int own_eapd_ctl:1; /* set EAPD by own function */
+3 -1
sound/pci/hda/patch_realtek.c
··· 1845 1845 const struct hda_fixup *fix, int action) 1846 1846 { 1847 1847 struct alc_spec *spec = codec->spec; 1848 - if (action == HDA_FIXUP_ACT_PRE_PROBE) 1848 + if (action == HDA_FIXUP_ACT_PRE_PROBE) { 1849 1849 spec->gen.no_primary_hp = 1; 1850 + spec->gen.no_multi_io = 1; 1851 + } 1850 1852 } 1851 1853 1852 1854 static const struct hda_fixup alc882_fixups[] = {