ALSA: hda - Fix invalid multi-io creation on VAIO-Z laptops
authorTakashi Iwai <tiwai@suse.de>
Mon, 29 Jul 2013 14:54:36 +0000 (16:54 +0200)
committerTakashi Iwai <tiwai@suse.de>
Mon, 29 Jul 2013 14:54:36 +0000 (16:54 +0200)
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>
Documentation/sound/alsa/HD-Audio.txt
sound/pci/hda/hda_generic.c
sound/pci/hda/hda_generic.h
sound/pci/hda/patch_realtek.c

index c3c912d023cc5c184c6f0496344cb1a1a82265eb..42a0a39b77e6a5da339e0f71717a6d3809986c24 100644 (file)
@@ -454,6 +454,8 @@ The generic parser supports the following hints:
 - need_dac_fix (bool): limits the DACs depending on the channel count
 - primary_hp (bool): probe headphone jacks as the primary outputs;
   default true
+- multi_io (bool): try probing multi-I/O config (e.g. shared
+  line-in/surround, mic/clfe jacks)
 - multi_cap_vol (bool): provide multiple capture volumes
 - inv_dmic_split (bool): provide split internal mic volume/switch for
   phase-inverted digital mics
index f5c2d1ff1a0904756a6a444eee7faf3406279d8d..f6c0344258ac579154345f15ca15ff80a97ec144 100644 (file)
@@ -142,6 +142,9 @@ static void parse_user_hints(struct hda_codec *codec)
        val = snd_hda_get_bool_hint(codec, "primary_hp");
        if (val >= 0)
                spec->no_primary_hp = !val;
+       val = snd_hda_get_bool_hint(codec, "multi_io");
+       if (val >= 0)
+               spec->no_multi_io = !val;
        val = snd_hda_get_bool_hint(codec, "multi_cap_vol");
        if (val >= 0)
                spec->multi_cap_vol = !!val;
@@ -1541,7 +1544,8 @@ static int fill_and_eval_dacs(struct hda_codec *codec,
                                              cfg->speaker_pins,
                                              spec->multiout.extra_out_nid,
                                              spec->speaker_paths);
-                       if (fill_mio_first && cfg->line_outs == 1 &&
+                       if (!spec->no_multi_io &&
+                           fill_mio_first && cfg->line_outs == 1 &&
                            cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
                                err = fill_multi_ios(codec, cfg->line_out_pins[0], true);
                                if (!err)
@@ -1554,7 +1558,7 @@ static int fill_and_eval_dacs(struct hda_codec *codec,
                                   spec->private_dac_nids, spec->out_paths,
                                   spec->main_out_badness);
 
-       if (fill_mio_first &&
+       if (!spec->no_multi_io && fill_mio_first &&
            cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
                /* try to fill multi-io first */
                err = fill_multi_ios(codec, cfg->line_out_pins[0], false);
@@ -1582,7 +1586,8 @@ static int fill_and_eval_dacs(struct hda_codec *codec,
                        return err;
                badness += err;
        }
-       if (cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
+       if (!spec->no_multi_io &&
+           cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
                err = fill_multi_ios(codec, cfg->line_out_pins[0], false);
                if (err < 0)
                        return err;
@@ -1600,7 +1605,8 @@ static int fill_and_eval_dacs(struct hda_codec *codec,
                                check_aamix_out_path(codec, spec->speaker_paths[0]);
        }
 
-       if (cfg->hp_outs && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
+       if (!spec->no_multi_io &&
+           cfg->hp_outs && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
                if (count_multiio_pins(codec, cfg->hp_pins[0]) >= 2)
                        spec->multi_ios = 1; /* give badness */
 
index e199a852388b4506148b0cfcbcca7ee380406a52..48d44026705b0f05ac01c51fbdb199215195979f 100644 (file)
@@ -220,6 +220,7 @@ struct hda_gen_spec {
        unsigned int hp_mic:1; /* Allow HP as a mic-in */
        unsigned int suppress_hp_mic_detect:1; /* Don't detect HP/mic */
        unsigned int no_primary_hp:1; /* Don't prefer HP pins to speaker pins */
+       unsigned int no_multi_io:1; /* Don't try multi I/O config */
        unsigned int multi_cap_vol:1; /* allow multiple capture xxx volumes */
        unsigned int inv_dmic_split:1; /* inverted dmic w/a for conexant */
        unsigned int own_eapd_ctl:1; /* set EAPD by own function */
index 04a69e3fca479e282495c7254010d93a26c5cac2..ad7a0985edfe589c8cc85299d1c9b8dac61e5c6b 100644 (file)
@@ -1845,8 +1845,10 @@ static void alc882_fixup_no_primary_hp(struct hda_codec *codec,
                                       const struct hda_fixup *fix, int action)
 {
        struct alc_spec *spec = codec->spec;
-       if (action == HDA_FIXUP_ACT_PRE_PROBE)
+       if (action == HDA_FIXUP_ACT_PRE_PROBE) {
                spec->gen.no_primary_hp = 1;
+               spec->gen.no_multi_io = 1;
+       }
 }
 
 static const struct hda_fixup alc882_fixups[] = {