diff options
author | Takashi Iwai <tiwai@suse.de> | 2006-03-21 11:24:42 +0100 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2006-03-22 10:40:14 +0100 |
commit | 82bc955f6379135e6ce35ff90c7ac411fd412c4c (patch) | |
tree | 314610afb5a469ac6a5a9f4d5e947436bb2c0538 /sound | |
parent | [ALSA] Fixes typos in Audiophile-USB.txt (diff) | |
download | linux-82bc955f6379135e6ce35ff90c7ac411fd412c4c.tar.xz linux-82bc955f6379135e6ce35ff90c7ac411fd412c4c.zip |
[ALSA] hda-codec - Fix BIOS auto-configuration
Modules: HDA Codec driver,HDA generic driver
- Fix autoconfig speaker/hp detection
Now it allows multiple speaker pins (e.g. Dell laptops have such config)
- Use speaker or hp pins if no line-outs are available
This fixes the silence output on recent Dell laptops with STAC9200
(ALSA bug#1843)
- Fix analog/realtek/sigmatel autoconfig parser
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 77 | ||||
-rw-r--r-- | sound/pci/hda/hda_local.h | 4 | ||||
-rw-r--r-- | sound/pci/hda/patch_analog.c | 23 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 47 | ||||
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 84 |
5 files changed, 160 insertions, 75 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index fc91256e42eb..b42dff7ceed0 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -1899,6 +1899,13 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_o if (mout->hp_nid) /* headphone out will just decode front left/right (stereo) */ snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag, 0, format); + /* extra outputs copied from front */ + for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++) + if (mout->extra_out_nid[i]) + snd_hda_codec_setup_stream(codec, + mout->extra_out_nid[i], + stream_tag, 0, format); + /* surrounds */ for (i = 1; i < mout->num_dacs; i++) { if (chs >= (i + 1) * 2) /* independent out */ @@ -1923,6 +1930,11 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, struct hda_multi_o snd_hda_codec_setup_stream(codec, nids[i], 0, 0, 0); if (mout->hp_nid) snd_hda_codec_setup_stream(codec, mout->hp_nid, 0, 0, 0); + for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++) + if (mout->extra_out_nid[i]) + snd_hda_codec_setup_stream(codec, + mout->extra_out_nid[i], + 0, 0, 0); mutex_lock(&codec->spdif_mutex); if (mout->dig_out_nid && mout->dig_out_used == HDA_DIG_ANALOG_DUP) { snd_hda_codec_setup_stream(codec, mout->dig_out_nid, 0, 0, 0); @@ -1944,13 +1956,29 @@ static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list) return 0; } -/* parse all pin widgets and store the useful pin nids to cfg */ +/* + * Parse all pin widgets and store the useful pin nids to cfg + * + * The number of line-outs or any primary output is stored in line_outs, + * and the corresponding output pins are assigned to line_out_pins[], + * in the order of front, rear, CLFE, side, ... + * + * If more extra outputs (speaker and headphone) are found, the pins are + * assisnged to hp_pin and speaker_pins[], respectively. If no line-out jack + * is detected, one of speaker of HP pins is assigned as the primary + * output, i.e. to line_out_pins[0]. So, line_outs is always positive + * if any analog output exists. + * + * The analog input pins are assigned to input_pins array. + * The digital input/output pins are assigned to dig_in_pin and dig_out_pin, + * respectively. + */ int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *cfg, hda_nid_t *ignore_nids) { hda_nid_t nid, nid_start; int i, j, nodes; - short seq, sequences[4], assoc_line_out; + short seq, assoc_line_out, sequences[ARRAY_SIZE(cfg->line_out_pins)]; memset(cfg, 0, sizeof(*cfg)); @@ -1992,7 +2020,10 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *c cfg->line_outs++; break; case AC_JACK_SPEAKER: - cfg->speaker_pin = nid; + if (cfg->speaker_outs >= ARRAY_SIZE(cfg->speaker_pins)) + continue; + cfg->speaker_pins[cfg->speaker_outs] = nid; + cfg->speaker_outs++; break; case AC_JACK_HP_OUT: cfg->hp_pin = nid; @@ -2057,6 +2088,46 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *c break; } + /* + * debug prints of the parsed results + */ + snd_printd("autoconfig: line_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n", + cfg->line_outs, cfg->line_out_pins[0], cfg->line_out_pins[1], + cfg->line_out_pins[2], cfg->line_out_pins[3], + cfg->line_out_pins[4]); + snd_printd(" speaker_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n", + cfg->speaker_outs, cfg->speaker_pins[0], + cfg->speaker_pins[1], cfg->speaker_pins[2], + cfg->speaker_pins[3], cfg->speaker_pins[4]); + snd_printd(" hp=0x%x, dig_out=0x%x, din_in=0x%x\n", + cfg->hp_pin, cfg->dig_out_pin, cfg->dig_in_pin); + snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x," + " cd=0x%x, aux=0x%x\n", + cfg->input_pins[AUTO_PIN_MIC], + cfg->input_pins[AUTO_PIN_FRONT_MIC], + cfg->input_pins[AUTO_PIN_LINE], + cfg->input_pins[AUTO_PIN_FRONT_LINE], + cfg->input_pins[AUTO_PIN_CD], + cfg->input_pins[AUTO_PIN_AUX]); + + /* + * FIX-UP: if no line-outs are detected, try to use speaker or HP pin + * as a primary output + */ + if (! cfg->line_outs) { + if (cfg->speaker_outs) { + cfg->line_outs = cfg->speaker_outs; + memcpy(cfg->line_out_pins, cfg->speaker_pins, + sizeof(cfg->speaker_pins)); + cfg->speaker_outs = 0; + memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins)); + } else if (cfg->hp_pin) { + cfg->line_outs = 1; + cfg->line_out_pins[0] = cfg->hp_pin; + cfg->hp_pin = 0; + } + } + return 0; } diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 548a8b698487..14e8aa2806ed 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h @@ -135,6 +135,7 @@ struct hda_multi_out { int num_dacs; /* # of DACs, must be more than 1 */ hda_nid_t *dac_nids; /* DAC list */ hda_nid_t hp_nid; /* optional DAC for HP, 0 when not exists */ + hda_nid_t extra_out_nid[3]; /* optional DACs, 0 when not exists */ hda_nid_t dig_out_nid; /* digital out audio widget */ int max_channels; /* currently supported analog channels */ int dig_out_used; /* current usage of digital out (HDA_DIG_XXX) */ @@ -221,7 +222,8 @@ extern const char *auto_pin_cfg_labels[AUTO_PIN_LAST]; struct auto_pin_cfg { int line_outs; hda_nid_t line_out_pins[5]; /* sorted in the order of Front/Surr/CLFE/Side */ - hda_nid_t speaker_pin; + int speaker_outs; + hda_nid_t speaker_pins[5]; hda_nid_t hp_pin; hda_nid_t input_pins[AUTO_PIN_LAST]; hda_nid_t dig_out_pin; diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 2b14fa74a8fd..7fbe71e69cfc 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -786,6 +786,8 @@ enum { AD1986A_6STACK, AD1986A_3STACK, AD1986A_LAPTOP, AD1986A_LAPTOP_EAPD }; static struct hda_board_config ad1986a_cfg_tbl[] = { { .modelname = "6stack", .config = AD1986A_6STACK }, { .modelname = "3stack", .config = AD1986A_3STACK }, + { .pci_subvendor = 0x10de, .pci_subdevice = 0xcb84, + .config = AD1986A_3STACK }, /* ASUS A8N-VM CSM */ { .modelname = "laptop", .config = AD1986A_LAPTOP }, { .pci_subvendor = 0x144d, .pci_subdevice = 0xc01e, .config = AD1986A_LAPTOP }, /* FSC V2060 */ @@ -2253,14 +2255,11 @@ static int ad1988_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin, idx = ad1988_pin_idx(pin); nid = ad1988_idx_to_dac(codec, idx); - if (! spec->multiout.dac_nids[0]) { - /* use this as the primary output */ - spec->multiout.dac_nids[0] = nid; - if (! spec->multiout.num_dacs) - spec->multiout.num_dacs = 1; - } else - /* specify the DAC as the extra output */ + /* specify the DAC as the extra output */ + if (! spec->multiout.hp_nid) spec->multiout.hp_nid = nid; + else + spec->multiout.extra_out_nid[0] = nid; /* control HP volume/switch on the output mixer amp */ sprintf(name, "%s Playback Volume", pfx); if ((err = add_control(spec, AD_CTL_WIDGET_VOL, name, @@ -2379,7 +2378,7 @@ static void ad1988_auto_init_extra_out(struct hda_codec *codec) struct ad198x_spec *spec = codec->spec; hda_nid_t pin; - pin = spec->autocfg.speaker_pin; + pin = spec->autocfg.speaker_pins[0]; if (pin) /* connect to front */ ad1988_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); pin = spec->autocfg.hp_pin; @@ -2428,13 +2427,13 @@ static int ad1988_parse_auto_config(struct hda_codec *codec) return err; if ((err = ad1988_auto_fill_dac_nids(codec, &spec->autocfg)) < 0) return err; - if (! spec->autocfg.line_outs && ! spec->autocfg.speaker_pin && - ! spec->autocfg.hp_pin) + if (! spec->autocfg.line_outs) return 0; /* can't find valid BIOS pin config */ if ((err = ad1988_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || - (err = ad1988_auto_create_extra_out(codec, spec->autocfg.speaker_pin, + (err = ad1988_auto_create_extra_out(codec, + spec->autocfg.speaker_pins[0], "Speaker")) < 0 || - (err = ad1988_auto_create_extra_out(codec, spec->autocfg.speaker_pin, + (err = ad1988_auto_create_extra_out(codec, spec->autocfg.hp_pin, "Headphone")) < 0 || (err = ad1988_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) return err; diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 1607a1fab568..de145d102d9f 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -2431,14 +2431,11 @@ static int alc880_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin, if (alc880_is_fixed_pin(pin)) { nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin)); - if (! spec->multiout.dac_nids[0]) { - /* use this as the primary output */ - spec->multiout.dac_nids[0] = nid; - if (! spec->multiout.num_dacs) - spec->multiout.num_dacs = 1; - } else - /* specify the DAC as the extra output */ + /* specify the DAC as the extra output */ + if (! spec->multiout.hp_nid) spec->multiout.hp_nid = nid; + else + spec->multiout.extra_out_nid[0] = nid; /* control HP volume/switch on the output mixer amp */ nid = alc880_idx_to_mixer(alc880_fixed_pin_idx(pin)); sprintf(name, "%s Playback Volume", pfx); @@ -2451,12 +2448,6 @@ static int alc880_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin, return err; } else if (alc880_is_multi_pin(pin)) { /* set manual connection */ - if (! spec->multiout.dac_nids[0]) { - /* use this as the primary output */ - spec->multiout.dac_nids[0] = alc880_idx_to_dac(alc880_multi_pin_idx(pin)); - if (! spec->multiout.num_dacs) - spec->multiout.num_dacs = 1; - } /* we have only a switch on HP-out PIN */ sprintf(name, "%s Playback Switch", pfx); if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, @@ -2540,7 +2531,7 @@ static void alc880_auto_init_extra_out(struct hda_codec *codec) struct alc_spec *spec = codec->spec; hda_nid_t pin; - pin = spec->autocfg.speaker_pin; + pin = spec->autocfg.speaker_pins[0]; if (pin) /* connect to front */ alc880_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); pin = spec->autocfg.hp_pin; @@ -2576,15 +2567,15 @@ static int alc880_parse_auto_config(struct hda_codec *codec) if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, alc880_ignore)) < 0) return err; - if (! spec->autocfg.line_outs && ! spec->autocfg.speaker_pin && - ! spec->autocfg.hp_pin) + if (! spec->autocfg.line_outs) return 0; /* can't find valid BIOS pin config */ if ((err = alc880_auto_fill_dac_nids(spec, &spec->autocfg)) < 0 || (err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || - (err = alc880_auto_create_extra_out(spec, spec->autocfg.speaker_pin, + (err = alc880_auto_create_extra_out(spec, + spec->autocfg.speaker_pins[0], "Speaker")) < 0 || - (err = alc880_auto_create_extra_out(spec, spec->autocfg.speaker_pin, + (err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pin, "Headphone")) < 0 || (err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) return err; @@ -3445,7 +3436,7 @@ static int alc260_auto_create_multi_out_ctls(struct alc_spec *spec, return err; } - nid = cfg->speaker_pin; + nid = cfg->speaker_pins[0]; if (nid) { err = alc260_add_playback_controls(spec, nid, "Speaker"); if (err < 0) @@ -3518,7 +3509,7 @@ static void alc260_auto_init_multi_out(struct hda_codec *codec) if (nid) alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0); - nid = spec->autocfg.speaker_pin; + nid = spec->autocfg.speaker_pins[0]; if (nid) alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0); @@ -4602,7 +4593,7 @@ static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, const struct return err; } - nid = cfg->speaker_pin; + nid = cfg->speaker_pins[0]; if (nid) { if (nid == 0x16) { if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Speaker Playback Volume", @@ -4612,10 +4603,6 @@ static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, const struct HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0) return err; } else { - if (! cfg->line_out_pins[0]) - if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Speaker Playback Volume", - HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT))) < 0) - return err; if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Speaker Playback Switch", HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) return err; @@ -4632,10 +4619,6 @@ static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, const struct HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0) return err; } else { - if (! cfg->line_out_pins[0]) - if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Headphone Playback Volume", - HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT))) < 0) - return err; if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Headphone Playback Switch", HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) return err; @@ -4729,8 +4712,7 @@ static int alc262_parse_auto_config(struct hda_codec *codec) if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, alc262_ignore)) < 0) return err; - if (! spec->autocfg.line_outs && ! spec->autocfg.speaker_pin && - ! spec->autocfg.hp_pin) + if (! spec->autocfg.line_outs) return 0; /* can't find valid BIOS pin config */ if ((err = alc262_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || (err = alc262_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) @@ -5404,8 +5386,7 @@ static int alc861_parse_auto_config(struct hda_codec *codec) if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, alc861_ignore)) < 0) return err; - if (! spec->autocfg.line_outs && ! spec->autocfg.speaker_pin && - ! spec->autocfg.hp_pin) + if (! spec->autocfg.line_outs) return 0; /* can't find valid BIOS pin config */ if ((err = alc861_auto_fill_dac_nids(spec, &spec->autocfg)) < 0 || diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 240958df26ce..b56ca4019392 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -51,6 +51,7 @@ struct sigmatel_spec { unsigned int line_switch: 1; unsigned int mic_switch: 1; unsigned int alt_switch: 1; + unsigned int hp_detect: 1; /* playback */ struct hda_multi_out multiout; @@ -697,13 +698,7 @@ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec, const struct aut AC_VERB_GET_CONNECT_LIST, 0) & 0xff; } - if (cfg->line_outs) - spec->multiout.num_dacs = cfg->line_outs; - else if (cfg->hp_pin) { - spec->multiout.dac_nids[0] = snd_hda_codec_read(codec, cfg->hp_pin, 0, - AC_VERB_GET_CONNECT_LIST, 0) & 0xff; - spec->multiout.num_dacs = 1; - } + spec->multiout.num_dacs = cfg->line_outs; return 0; } @@ -772,11 +767,13 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec, struct auto_pin return 0; wid_caps = get_wcaps(codec, pin); - if (wid_caps & AC_WCAP_UNSOL_CAP) + if (wid_caps & AC_WCAP_UNSOL_CAP) { /* Enable unsolicited responses on the HP widget */ snd_hda_codec_write(codec, pin, 0, AC_VERB_SET_UNSOLICITED_ENABLE, STAC_UNSOL_ENABLE); + spec->hp_detect = 1; + } nid = snd_hda_codec_read(codec, pin, 0, AC_VERB_GET_CONNECT_LIST, 0) & 0xff; for (i = 0; i < cfg->line_outs; i++) { @@ -810,9 +807,6 @@ static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const for (i = 0; i < AUTO_PIN_LAST; i++) { int index = -1; if (cfg->input_pins[i]) { - /* Enable active pin widget as an input */ - stac92xx_auto_set_pinctl(codec, cfg->input_pins[i], AC_PINCTL_IN_EN); - imux->items[imux->num_items].label = auto_pin_cfg_labels[i]; for (j=0; j<spec->num_muxes; j++) { @@ -861,10 +855,8 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL)) < 0) return err; - if (! spec->autocfg.line_outs && ! spec->autocfg.hp_pin) + if (! spec->autocfg.line_outs) return 0; /* can't find valid pin config */ - stac92xx_auto_init_multi_out(codec); - stac92xx_auto_init_hp_out(codec); if ((err = stac92xx_add_dyn_out_pins(codec, &spec->autocfg)) < 0) return err; if ((err = stac92xx_auto_fill_dac_nids(codec, &spec->autocfg)) < 0) @@ -879,14 +871,10 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out if (spec->multiout.max_channels > 2) spec->surr_switch = 1; - if (spec->autocfg.dig_out_pin) { + if (spec->autocfg.dig_out_pin) spec->multiout.dig_out_nid = dig_out; - stac92xx_auto_set_pinctl(codec, spec->autocfg.dig_out_pin, AC_PINCTL_OUT_EN); - } - if (spec->autocfg.dig_in_pin) { + if (spec->autocfg.dig_in_pin) spec->dig_in_nid = dig_in; - stac92xx_auto_set_pinctl(codec, spec->autocfg.dig_in_pin, AC_PINCTL_IN_EN); - } if (spec->kctl_alloc) spec->mixers[spec->num_mixers++] = spec->kctl_alloc; @@ -896,6 +884,29 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out return 1; } +/* add playback controls for HP output */ +static int stac9200_auto_create_hp_ctls(struct hda_codec *codec, + struct auto_pin_cfg *cfg) +{ + struct sigmatel_spec *spec = codec->spec; + hda_nid_t pin = cfg->hp_pin; + unsigned int wid_caps; + + if (! pin) + return 0; + + wid_caps = get_wcaps(codec, pin); + if (wid_caps & AC_WCAP_UNSOL_CAP) { + /* Enable unsolicited responses on the HP widget */ + snd_hda_codec_write(codec, pin, 0, + AC_VERB_SET_UNSOLICITED_ENABLE, + STAC_UNSOL_ENABLE); + spec->hp_detect = 1; + } + + return 0; +} + static int stac9200_parse_auto_config(struct hda_codec *codec) { struct sigmatel_spec *spec = codec->spec; @@ -907,14 +918,13 @@ static int stac9200_parse_auto_config(struct hda_codec *codec) if ((err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg)) < 0) return err; - if (spec->autocfg.dig_out_pin) { + if ((err = stac9200_auto_create_hp_ctls(codec, &spec->autocfg)) < 0) + return err; + + if (spec->autocfg.dig_out_pin) spec->multiout.dig_out_nid = 0x05; - stac92xx_auto_set_pinctl(codec, spec->autocfg.dig_out_pin, AC_PINCTL_OUT_EN); - } - if (spec->autocfg.dig_in_pin) { + if (spec->autocfg.dig_in_pin) spec->dig_in_nid = 0x04; - stac92xx_auto_set_pinctl(codec, spec->autocfg.dig_in_pin, AC_PINCTL_IN_EN); - } if (spec->kctl_alloc) spec->mixers[spec->num_mixers++] = spec->kctl_alloc; @@ -927,9 +937,31 @@ static int stac9200_parse_auto_config(struct hda_codec *codec) static int stac92xx_init(struct hda_codec *codec) { struct sigmatel_spec *spec = codec->spec; + struct auto_pin_cfg *cfg = &spec->autocfg; + int i; snd_hda_sequence_write(codec, spec->init); + /* set up pins */ + if (spec->hp_detect) { + /* fake event to set up pins */ + codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); + } else { + stac92xx_auto_init_multi_out(codec); + stac92xx_auto_init_hp_out(codec); + } + for (i = 0; i < AUTO_PIN_LAST; i++) { + if (cfg->input_pins[i]) + stac92xx_auto_set_pinctl(codec, cfg->input_pins[i], + AC_PINCTL_IN_EN); + } + if (cfg->dig_out_pin) + stac92xx_auto_set_pinctl(codec, cfg->dig_out_pin, + AC_PINCTL_OUT_EN); + if (cfg->dig_in_pin) + stac92xx_auto_set_pinctl(codec, cfg->dig_in_pin, + AC_PINCTL_IN_EN); + return 0; } |