X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?p=pandora-kernel.git;a=blobdiff_plain;f=sound%2Fpci%2Fhda%2Fpatch_sigmatel.c;h=9e192529e8077f5bc7c9eeccd299f1e0df96e746;hp=41b5b3a18c1ee3efcdd910643aaea45e12f59ae1;hb=bf677bd8fbd5dc06ead5511cf9fa76d090856c6a;hpb=1475ef0f0367766417f10f82880178ca42922748 diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 41b5b3a18c1e..9e192529e807 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -40,6 +40,7 @@ enum { STAC_INSERT_EVENT, STAC_PWR_EVENT, STAC_HP_EVENT, + STAC_MIC_EVENT, }; enum { @@ -176,6 +177,12 @@ struct sigmatel_jack { struct snd_jack *jack; }; +struct sigmatel_mic_route { + hda_nid_t pin; + unsigned char mux_idx; + unsigned char dmux_idx; +}; + struct sigmatel_spec { struct snd_kcontrol_new *mixers[4]; unsigned int num_mixers; @@ -187,6 +194,7 @@ struct sigmatel_spec { unsigned int hp_detect: 1; unsigned int spdif_mute: 1; unsigned int check_volume_offset:1; + unsigned int auto_mic:1; /* gpio lines */ unsigned int eapd_mask; @@ -238,6 +246,14 @@ struct sigmatel_spec { unsigned int num_dmuxes; hda_nid_t *smux_nids; unsigned int num_smuxes; + + unsigned long *capvols; /* amp-volume attr: HDA_COMPOSE_AMP_VAL() */ + unsigned long *capsws; /* amp-mute attr: HDA_COMPOSE_AMP_VAL() */ + unsigned int num_caps; /* number of capture volume/switch elements */ + + struct sigmatel_mic_route ext_mic; + struct sigmatel_mic_route int_mic; + const char **spdif_labels; hda_nid_t dig_in_nid; @@ -334,6 +350,13 @@ static hda_nid_t stac92hd73xx_smux_nids[2] = { 0x22, 0x23, }; +#define STAC92HD73XX_NUM_CAPS 2 +static unsigned long stac92hd73xx_capvols[] = { + HDA_COMPOSE_AMP_VAL(0x20, 3, 0, HDA_OUTPUT), + HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT), +}; +#define stac92hd73xx_capsws stac92hd73xx_capvols + #define STAC92HD83XXX_NUM_DMICS 2 static hda_nid_t stac92hd83xxx_dmic_nids[STAC92HD83XXX_NUM_DMICS + 1] = { 0x11, 0x12, 0 @@ -365,6 +388,13 @@ static hda_nid_t stac92hd83xxx_amp_nids[1] = { 0xc, }; +#define STAC92HD83XXX_NUM_CAPS 2 +static unsigned long stac92hd83xxx_capvols[] = { + HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_OUTPUT), + HDA_COMPOSE_AMP_VAL(0x18, 3, 0, HDA_OUTPUT), +}; +#define stac92hd83xxx_capsws stac92hd83xxx_capvols + static hda_nid_t stac92hd71bxx_pwr_nids[3] = { 0x0a, 0x0d, 0x0f }; @@ -394,6 +424,13 @@ static hda_nid_t stac92hd71bxx_slave_dig_outs[2] = { 0x22, 0 }; +#define STAC92HD71BXX_NUM_CAPS 2 +static unsigned long stac92hd71bxx_capvols[] = { + HDA_COMPOSE_AMP_VAL(0x1c, 3, 0, HDA_OUTPUT), + HDA_COMPOSE_AMP_VAL(0x1d, 3, 0, HDA_OUTPUT), +}; +#define stac92hd71bxx_capsws stac92hd71bxx_capvols + static hda_nid_t stac925x_adc_nids[1] = { 0x03, }; @@ -415,6 +452,13 @@ static hda_nid_t stac925x_dmux_nids[1] = { 0x14, }; +static unsigned long stac925x_capvols[] = { + HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_OUTPUT), +}; +static unsigned long stac925x_capsws[] = { + HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT), +}; + static hda_nid_t stac922x_adc_nids[2] = { 0x06, 0x07, }; @@ -423,6 +467,13 @@ static hda_nid_t stac922x_mux_nids[2] = { 0x12, 0x13, }; +#define STAC922X_NUM_CAPS 2 +static unsigned long stac922x_capvols[] = { + HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_INPUT), + HDA_COMPOSE_AMP_VAL(0x18, 3, 0, HDA_INPUT), +}; +#define stac922x_capsws stac922x_capvols + static hda_nid_t stac927x_slave_dig_outs[2] = { 0x1f, 0, }; @@ -452,6 +503,18 @@ static hda_nid_t stac927x_dmic_nids[STAC927X_NUM_DMICS + 1] = { 0x13, 0x14, 0 }; +#define STAC927X_NUM_CAPS 3 +static unsigned long stac927x_capvols[] = { + HDA_COMPOSE_AMP_VAL(0x18, 3, 0, HDA_INPUT), + HDA_COMPOSE_AMP_VAL(0x19, 3, 0, HDA_INPUT), + HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_INPUT), +}; +static unsigned long stac927x_capsws[] = { + HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT), + HDA_COMPOSE_AMP_VAL(0x1c, 3, 0, HDA_OUTPUT), + HDA_COMPOSE_AMP_VAL(0x1d, 3, 0, HDA_OUTPUT), +}; + static const char *stac927x_spdif_labels[5] = { "Digital Playback", "ADAT", "Analog Mux 1", "Analog Mux 2", "Analog Mux 3" @@ -478,6 +541,16 @@ static hda_nid_t stac9205_dmic_nids[STAC9205_NUM_DMICS + 1] = { 0x17, 0x18, 0 }; +#define STAC9205_NUM_CAPS 2 +static unsigned long stac9205_capvols[] = { + HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_INPUT), + HDA_COMPOSE_AMP_VAL(0x1c, 3, 0, HDA_INPUT), +}; +static unsigned long stac9205_capsws[] = { + HDA_COMPOSE_AMP_VAL(0x1d, 3, 0, HDA_OUTPUT), + HDA_COMPOSE_AMP_VAL(0x1e, 3, 0, HDA_OUTPUT), +}; + static hda_nid_t stac9200_pin_nids[8] = { 0x08, 0x09, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, @@ -924,19 +997,6 @@ static struct hda_verb stac92hd71bxx_core_init[] = { {} }; -#define HD_DISABLE_PORTF 1 -static struct hda_verb stac92hd71bxx_analog_core_init[] = { - /* start of config #1 */ - - /* connect port 0f to audio mixer */ - { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x2}, - /* start of config #2 */ - - /* set master volume and direct control */ - { 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, - {} -}; - static struct hda_verb stac92hd71bxx_unmute_core_init[] = { /* unmute right and left channels for nodes 0x0f, 0xa, 0x0d */ { 0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, @@ -1069,12 +1129,6 @@ static struct snd_kcontrol_new stac92hd73xx_6ch_mixer[] = { HDA_CODEC_VOLUME("DAC Mixer Capture Volume", 0x1d, 0x3, HDA_INPUT), HDA_CODEC_MUTE("DAC Mixer Capture Switch", 0x1d, 0x3, HDA_INPUT), - HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x20, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x20, 0x0, HDA_OUTPUT), - - HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x21, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x21, 0x0, HDA_OUTPUT), - { } /* end */ }; @@ -1094,12 +1148,6 @@ static struct snd_kcontrol_new stac92hd73xx_10ch_loopback[] = { }; static struct snd_kcontrol_new stac92hd73xx_8ch_mixer[] = { - HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x20, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x20, 0x0, HDA_OUTPUT), - - HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x21, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x21, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Front Mic Mixer Capture Volume", 0x1d, 0, HDA_INPUT), HDA_CODEC_MUTE("Front Mic Mixer Capture Switch", 0x1d, 0, HDA_INPUT), @@ -1118,12 +1166,6 @@ static struct snd_kcontrol_new stac92hd73xx_8ch_mixer[] = { }; static struct snd_kcontrol_new stac92hd73xx_10ch_mixer[] = { - HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x20, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x20, 0x0, HDA_OUTPUT), - - HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x21, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x21, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Front Mic Mixer Capture Volume", 0x1d, 0, HDA_INPUT), HDA_CODEC_MUTE("Front Mic Mixer Capture Switch", 0x1d, 0, HDA_INPUT), @@ -1143,12 +1185,6 @@ static struct snd_kcontrol_new stac92hd73xx_10ch_mixer[] = { static struct snd_kcontrol_new stac92hd83xxx_mixer[] = { - HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x17, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x17, 0x0, HDA_OUTPUT), - - HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x18, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x18, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("DAC0 Capture Volume", 0x1b, 0x3, HDA_INPUT), HDA_CODEC_MUTE("DAC0 Capture Switch", 0x1b, 0x3, HDA_INPUT), @@ -1169,17 +1205,6 @@ static struct snd_kcontrol_new stac92hd83xxx_mixer[] = { }; static struct snd_kcontrol_new stac92hd71bxx_analog_mixer[] = { - HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1c, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1c, 0x0, HDA_OUTPUT), - - HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x1d, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x1d, 0x0, HDA_OUTPUT), - /* analog pc-beep replaced with digital beep support */ - /* - HDA_CODEC_VOLUME("PC Beep Volume", 0x17, 0x2, HDA_INPUT), - HDA_CODEC_MUTE("PC Beep Switch", 0x17, 0x2, HDA_INPUT), - */ - HDA_CODEC_MUTE("Import0 Mux Capture Switch", 0x17, 0x0, HDA_INPUT), HDA_CODEC_VOLUME("Import0 Mux Capture Volume", 0x17, 0x0, HDA_INPUT), @@ -1198,29 +1223,9 @@ static struct snd_kcontrol_new stac92hd71bxx_loopback[] = { STAC_ANALOG_LOOPBACK(0xFA0, 0x7A0, 2) }; -static struct snd_kcontrol_new stac92hd71bxx_mixer[] = { - HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1c, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1c, 0x0, HDA_OUTPUT), - - HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x1d, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x1d, 0x0, HDA_OUTPUT), - { } /* end */ -}; - static struct snd_kcontrol_new stac925x_mixer[] = { HDA_CODEC_VOLUME("Master Playback Volume", 0x0e, 0, HDA_OUTPUT), HDA_CODEC_MUTE("Master Playback Switch", 0x0e, 0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_OUTPUT), - HDA_CODEC_MUTE("Capture Switch", 0x14, 0, HDA_OUTPUT), - { } /* end */ -}; - -static struct snd_kcontrol_new stac9205_mixer[] = { - HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x1b, 0x0, HDA_INPUT), - HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1d, 0x0, HDA_OUTPUT), - - HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x1c, 0x0, HDA_INPUT), - HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x1e, 0x0, HDA_OUTPUT), { } /* end */ }; @@ -1229,29 +1234,6 @@ static struct snd_kcontrol_new stac9205_loopback[] = { {} }; -/* This needs to be generated dynamically based on sequence */ -static struct snd_kcontrol_new stac922x_mixer[] = { - HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x17, 0x0, HDA_INPUT), - HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x17, 0x0, HDA_INPUT), - - HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x18, 0x0, HDA_INPUT), - HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x18, 0x0, HDA_INPUT), - { } /* end */ -}; - - -static struct snd_kcontrol_new stac927x_mixer[] = { - HDA_CODEC_VOLUME_IDX("Capture Volume", 0x0, 0x18, 0x0, HDA_INPUT), - HDA_CODEC_MUTE_IDX("Capture Switch", 0x0, 0x1b, 0x0, HDA_OUTPUT), - - HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x19, 0x0, HDA_INPUT), - HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x1c, 0x0, HDA_OUTPUT), - - HDA_CODEC_VOLUME_IDX("Capture Volume", 0x2, 0x1A, 0x0, HDA_INPUT), - HDA_CODEC_MUTE_IDX("Capture Switch", 0x2, 0x1d, 0x0, HDA_OUTPUT), - { } /* end */ -}; - static struct snd_kcontrol_new stac927x_loopback[] = { STAC_ANALOG_LOOPBACK(0xFEB, 0x7EB, 1), {} @@ -1309,16 +1291,18 @@ static int stac92xx_build_controls(struct hda_codec *codec) int err; int i; - err = snd_hda_add_new_ctls(codec, spec->mixer); - if (err < 0) - return err; + if (spec->mixer) { + err = snd_hda_add_new_ctls(codec, spec->mixer); + if (err < 0) + return err; + } for (i = 0; i < spec->num_mixers; i++) { err = snd_hda_add_new_ctls(codec, spec->mixers[i]); if (err < 0) return err; } - if (spec->num_dmuxes > 0) { + if (!spec->auto_mic && spec->num_dmuxes > 0) { stac_dmux_mixer.count = spec->num_dmuxes; err = snd_hda_ctl_add(codec, snd_ctl_new1(&stac_dmux_mixer, codec)); @@ -2378,6 +2362,7 @@ static struct snd_pci_quirk stac9205_cfg_tbl[] = { SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0228, "Dell Vostro 1500", STAC_9205_DELL_M42), /* Gateway */ + SND_PCI_QUIRK(0x107b, 0x0560, "Gateway T6834c", STAC_9205_EAPD), SND_PCI_QUIRK(0x107b, 0x0565, "Gateway T1616", STAC_9205_EAPD), {} /* terminator */ }; @@ -2633,8 +2618,7 @@ static int stac92xx_hp_switch_get(struct snd_kcontrol *kcontrol, return 0; } -static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid, - unsigned char type); +static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid); static int stac92xx_hp_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) @@ -2648,7 +2632,7 @@ static int stac92xx_hp_switch_put(struct snd_kcontrol *kcontrol, /* check to be sure that the ports are upto date with * switch changes */ - stac_issue_unsol_event(codec, nid, STAC_HP_EVENT); + stac_issue_unsol_event(codec, nid); return 1; } @@ -2781,7 +2765,7 @@ static int stac92xx_io_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ * appropriately according to the pin direction */ if (spec->hp_detect) - stac_issue_unsol_event(codec, nid, STAC_HP_EVENT); + stac_issue_unsol_event(codec, nid); return 1; } @@ -2964,6 +2948,8 @@ static int stac92xx_add_input_source(struct sigmatel_spec *spec) struct snd_kcontrol_new *knew; struct hda_input_mux *imux = &spec->private_imux; + if (spec->auto_mic) + return 0; /* no need for input source */ if (!spec->num_adcs || imux->num_items <= 1) return 0; /* no need for input source control */ knew = stac_control_new(spec, &stac_input_src_temp, @@ -3057,7 +3043,7 @@ static hda_nid_t get_unassigned_dac(struct hda_codec *codec, hda_nid_t nid) HDA_MAX_CONNECTIONS); for (j = 0; j < conn_len; j++) { wcaps = get_wcaps(codec, conn[j]); - wtype = (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; + wtype = get_wcaps_type(wcaps); /* we check only analog outputs */ if (wtype != AC_WID_AUD_OUT || (wcaps & AC_WCAP_DIGITAL)) continue; @@ -3316,6 +3302,21 @@ static int create_multi_out_ctls(struct hda_codec *codec, int num_outs, return 0; } +static int stac92xx_add_capvol_ctls(struct hda_codec *codec, unsigned long vol, + unsigned long sw, int idx) +{ + int err; + err = stac92xx_add_control_idx(codec->spec, STAC_CTL_WIDGET_VOL, idx, + "Capture Volume", vol); + if (err < 0) + return err; + err = stac92xx_add_control_idx(codec->spec, STAC_CTL_WIDGET_MUTE, idx, + "Capture Switch", sw); + if (err < 0) + return err; + return 0; +} + /* add playback controls from the parsed DAC table */ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec, const struct auto_pin_cfg *cfg) @@ -3389,7 +3390,7 @@ static int stac92xx_auto_create_mono_output_ctls(struct hda_codec *codec) spec->mono_nid, con_lst, HDA_MAX_NUM_INPUTS); - if (!num_cons || num_cons > ARRAY_SIZE(stac92xx_mono_labels)) + if (num_cons <= 0 || num_cons > ARRAY_SIZE(stac92xx_mono_labels)) return -EINVAL; for (i = 0; i < num_cons; i++) { @@ -3535,7 +3536,7 @@ static int stac92xx_auto_create_spdif_mux_ctls(struct hda_codec *codec) spec->smux_nids[0], con_lst, HDA_MAX_NUM_INPUTS); - if (!num_cons) + if (num_cons <= 0) return -EINVAL; if (!labels) @@ -3556,14 +3557,26 @@ static const char *stac92xx_dmic_labels[5] = { "Digital Mic 3", "Digital Mic 4" }; +static int get_connection_index(struct hda_codec *codec, hda_nid_t mux, + hda_nid_t nid) +{ + hda_nid_t conn[HDA_MAX_NUM_INPUTS]; + int i, nums; + + nums = snd_hda_get_connections(codec, mux, conn, ARRAY_SIZE(conn)); + for (i = 0; i < nums; i++) + if (conn[i] == nid) + return i; + return -1; +} + /* create playback/capture controls for input pins on dmic capable codecs */ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec, const struct auto_pin_cfg *cfg) { struct sigmatel_spec *spec = codec->spec; struct hda_input_mux *dimux = &spec->private_dimux; - hda_nid_t con_lst[HDA_MAX_NUM_INPUTS]; - int err, i, j; + int err, i; char name[32]; dimux->items[dimux->num_items].label = stac92xx_dmic_labels[0]; @@ -3573,7 +3586,6 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec, for (i = 0; i < spec->num_dmics; i++) { hda_nid_t nid; int index; - int num_cons; unsigned int wcaps; unsigned int def_conf; @@ -3582,17 +3594,10 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec, continue; nid = spec->dmic_nids[i]; - num_cons = snd_hda_get_connections(codec, - spec->dmux_nids[0], - con_lst, - HDA_MAX_NUM_INPUTS); - for (j = 0; j < num_cons; j++) - if (con_lst[j] == nid) { - index = j; - goto found; - } - continue; -found: + index = get_connection_index(codec, spec->dmux_nids[0], nid); + if (index < 0) + continue; + wcaps = get_wcaps(codec, nid) & (AC_WCAP_OUT_AMP | AC_WCAP_IN_AMP); @@ -3619,6 +3624,88 @@ found: return 0; } +static int check_mic_pin(struct hda_codec *codec, hda_nid_t nid, + hda_nid_t *fixed, hda_nid_t *ext) +{ + unsigned int cfg; + + if (!nid) + return 0; + cfg = snd_hda_codec_get_pincfg(codec, nid); + switch (get_defcfg_connect(cfg)) { + case AC_JACK_PORT_FIXED: + if (*fixed) + return 1; /* already occupied */ + *fixed = nid; + break; + case AC_JACK_PORT_COMPLEX: + if (*ext) + return 1; /* already occupied */ + *ext = nid; + break; + } + return 0; +} + +static int set_mic_route(struct hda_codec *codec, + struct sigmatel_mic_route *mic, + hda_nid_t pin) +{ + struct sigmatel_spec *spec = codec->spec; + struct auto_pin_cfg *cfg = &spec->autocfg; + int i; + + mic->pin = pin; + for (i = AUTO_PIN_MIC; i <= AUTO_PIN_FRONT_MIC; i++) + if (pin == cfg->input_pins[i]) + break; + if (i <= AUTO_PIN_FRONT_MIC) { + /* analog pin */ + mic->dmux_idx = 0; + i = get_connection_index(codec, spec->mux_nids[0], pin); + if (i < 0) + return -1; + mic->mux_idx = i; + } else { + /* digital pin */ + mic->mux_idx = 0; + i = get_connection_index(codec, spec->dmux_nids[0], pin); + if (i < 0) + return -1; + mic->dmux_idx = i; + } + return 0; +} + +/* return non-zero if the device is for automatic mic switch */ +static int stac_check_auto_mic(struct hda_codec *codec) +{ + struct sigmatel_spec *spec = codec->spec; + struct auto_pin_cfg *cfg = &spec->autocfg; + hda_nid_t fixed, ext; + int i; + + for (i = AUTO_PIN_LINE; i < AUTO_PIN_LAST; i++) { + if (cfg->input_pins[i]) + return 0; /* must be exclusively mics */ + } + fixed = ext = 0; + for (i = AUTO_PIN_MIC; i <= AUTO_PIN_FRONT_MIC; i++) + if (check_mic_pin(codec, cfg->input_pins[i], &fixed, &ext)) + return 0; + for (i = 0; i < spec->num_dmics; i++) + if (check_mic_pin(codec, spec->dmic_nids[i], &fixed, &ext)) + return 0; + if (!fixed || !ext) + return 0; + if (!(get_wcaps(codec, ext) & AC_WCAP_UNSOL_CAP)) + return 0; /* no unsol support */ + if (set_mic_route(codec, &spec->ext_mic, ext) || + set_mic_route(codec, &spec->int_mic, fixed)) + return 0; /* something is wrong */ + return 1; +} + /* create playback/capture controls for input pins */ static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const struct auto_pin_cfg *cfg) { @@ -3702,7 +3789,7 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out { struct sigmatel_spec *spec = codec->spec; int hp_swap = 0; - int err; + int i, err; if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, @@ -3742,11 +3829,10 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out if (snd_hda_get_connections(codec, spec->autocfg.mono_out_pin, conn_list, 1) && snd_hda_get_connections(codec, conn_list[0], - conn_list, 1)) { + conn_list, 1) > 0) { int wcaps = get_wcaps(codec, conn_list[0]); - int wid_type = (wcaps & AC_WCAP_TYPE) - >> AC_WCAP_TYPE_SHIFT; + int wid_type = get_wcaps_type(wcaps); /* LR swap check, some stac925x have a mux that * changes the DACs output path instead of the * mono-mux path. @@ -3837,6 +3923,21 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out spec->autocfg.line_outs = 0; } + if (stac_check_auto_mic(codec)) { + spec->auto_mic = 1; + /* only one capture for auto-mic */ + spec->num_adcs = 1; + spec->num_caps = 1; + spec->num_muxes = 1; + } + + for (i = 0; i < spec->num_caps; i++) { + err = stac92xx_add_capvol_ctls(codec, spec->capvols[i], + spec->capsws[i], i); + if (err < 0) + return err; + } + err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg); if (err < 0) return err; @@ -4065,7 +4166,7 @@ static int stac92xx_add_jack(struct hda_codec *codec, jack->nid = nid; jack->type = type; - sprintf(name, "%s at %s %s Jack", + snprintf(name, sizeof(name), "%s at %s %s Jack", snd_hda_get_jack_type(def_conf), snd_hda_get_jack_connectivity(def_conf), snd_hda_get_jack_location(def_conf)); @@ -4099,14 +4200,14 @@ static int stac_add_event(struct sigmatel_spec *spec, hda_nid_t nid, } static struct sigmatel_event *stac_get_event(struct hda_codec *codec, - hda_nid_t nid, unsigned char type) + hda_nid_t nid) { struct sigmatel_spec *spec = codec->spec; struct sigmatel_event *event = spec->events.list; int i; for (i = 0; i < spec->events.used; i++, event++) { - if (event->nid == nid && event->type == type) + if (event->nid == nid) return event; } return NULL; @@ -4126,24 +4227,32 @@ static struct sigmatel_event *stac_get_event_from_tag(struct hda_codec *codec, return NULL; } -static void enable_pin_detect(struct hda_codec *codec, hda_nid_t nid, - unsigned int type) +/* check if given nid is a valid pin and no other events are assigned + * to it. If OK, assign the event, set the unsol flag, and returns 1. + * Otherwise, returns zero. + */ +static int enable_pin_detect(struct hda_codec *codec, hda_nid_t nid, + unsigned int type) { struct sigmatel_event *event; int tag; if (!(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP)) - return; - event = stac_get_event(codec, nid, type); - if (event) + return 0; + event = stac_get_event(codec, nid); + if (event) { + if (event->type != type) + return 0; tag = event->tag; - else + } else { tag = stac_add_event(codec->spec, nid, type, 0); - if (tag < 0) - return; + if (tag < 0) + return 0; + } snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | tag); + return 1; } static int is_nid_hp_pin(struct auto_pin_cfg *cfg, hda_nid_t nid) @@ -4242,14 +4351,20 @@ static int stac92xx_init(struct hda_codec *codec) stac92xx_auto_set_pinctl(codec, spec->autocfg.line_out_pins[0], AC_PINCTL_OUT_EN); /* fake event to set up pins */ - stac_issue_unsol_event(codec, spec->autocfg.hp_pins[0], - STAC_HP_EVENT); + stac_issue_unsol_event(codec, spec->autocfg.hp_pins[0]); } else { stac92xx_auto_init_multi_out(codec); stac92xx_auto_init_hp_out(codec); for (i = 0; i < cfg->hp_outs; i++) stac_toggle_power_map(codec, cfg->hp_pins[i], 1); } + if (spec->auto_mic) { + /* initialize connection to analog input */ + snd_hda_codec_write_cache(codec, spec->dmux_nids[0], 0, + AC_VERB_SET_CONNECT_SEL, 0); + if (enable_pin_detect(codec, spec->ext_mic.pin, STAC_MIC_EVENT)) + stac_issue_unsol_event(codec, spec->ext_mic.pin); + } for (i = 0; i < AUTO_PIN_LAST; i++) { hda_nid_t nid = cfg->input_pins[i]; if (nid) { @@ -4276,10 +4391,9 @@ static int stac92xx_init(struct hda_codec *codec) } conf = snd_hda_codec_get_pincfg(codec, nid); if (get_defcfg_connect(conf) != AC_JACK_PORT_FIXED) { - enable_pin_detect(codec, nid, - STAC_INSERT_EVENT); - stac_issue_unsol_event(codec, nid, - STAC_INSERT_EVENT); + if (enable_pin_detect(codec, nid, + STAC_INSERT_EVENT)) + stac_issue_unsol_event(codec, nid); } } } @@ -4324,10 +4438,8 @@ static int stac92xx_init(struct hda_codec *codec) stac_toggle_power_map(codec, nid, 1); continue; } - if (!stac_get_event(codec, nid, STAC_INSERT_EVENT)) { - enable_pin_detect(codec, nid, STAC_PWR_EVENT); - stac_issue_unsol_event(codec, nid, STAC_PWR_EVENT); - } + if (enable_pin_detect(codec, nid, STAC_PWR_EVENT)) + stac_issue_unsol_event(codec, nid); } if (spec->dac_list) stac92xx_power_down(codec); @@ -4590,10 +4702,28 @@ static void stac92xx_report_jack(struct hda_codec *codec, hda_nid_t nid) } } -static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid, - unsigned char type) +static void stac92xx_mic_detect(struct hda_codec *codec) { - struct sigmatel_event *event = stac_get_event(codec, nid, type); + struct sigmatel_spec *spec = codec->spec; + struct sigmatel_mic_route *mic; + + if (get_pin_presence(codec, spec->ext_mic.pin)) + mic = &spec->ext_mic; + else + mic = &spec->int_mic; + if (mic->dmux_idx) + snd_hda_codec_write_cache(codec, spec->dmux_nids[0], 0, + AC_VERB_SET_CONNECT_SEL, + mic->dmux_idx); + else + snd_hda_codec_write_cache(codec, spec->mux_nids[0], 0, + AC_VERB_SET_CONNECT_SEL, + mic->mux_idx); +} + +static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid) +{ + struct sigmatel_event *event = stac_get_event(codec, nid); if (!event) return; codec->patch_ops.unsol_event(codec, (unsigned)event->tag << 26); @@ -4613,7 +4743,15 @@ static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) switch (event->type) { case STAC_HP_EVENT: stac92xx_hp_detect(codec); - /* fallthru */ + break; + case STAC_MIC_EVENT: + stac92xx_mic_detect(codec); + break; + } + + switch (event->type) { + case STAC_HP_EVENT: + case STAC_MIC_EVENT: case STAC_INSERT_EVENT: case STAC_PWR_EVENT: if (spec->num_pwrs > 0) @@ -4704,8 +4842,7 @@ static int stac92xx_resume(struct hda_codec *codec) snd_hda_codec_resume_cache(codec); /* fake event to set up pins again to override cached values */ if (spec->hp_detect) - stac_issue_unsol_event(codec, spec->autocfg.hp_pins[0], - STAC_HP_EVENT); + stac_issue_unsol_event(codec, spec->autocfg.hp_pins[0]); return 0; } @@ -4745,6 +4882,19 @@ static int stac92xx_hp_check_power_status(struct hda_codec *codec, static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state) { struct sigmatel_spec *spec = codec->spec; + int i; + hda_nid_t nid; + + /* reset each pin before powering down DAC/ADC to avoid click noise */ + nid = codec->start_nid; + for (i = 0; i < codec->num_nodes; i++, nid++) { + unsigned int wcaps = get_wcaps(codec, nid); + unsigned int wid_type = get_wcaps_type(wcaps); + if (wid_type == AC_WID_PIN) + snd_hda_codec_read(codec, nid, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, 0); + } + if (spec->eapd_mask) stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, spec->gpio_data & @@ -4781,7 +4931,8 @@ static int patch_stac9200(struct hda_codec *codec) stac9200_models, stac9200_cfg_tbl); if (spec->board_config < 0) - snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9200, using BIOS defaults\n"); + snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", + codec->chip_name); else stac92xx_set_config_regs(codec, stac9200_brd_tbl[spec->board_config]); @@ -4853,8 +5004,8 @@ static int patch_stac925x(struct hda_codec *codec) stac925x_cfg_tbl); again: if (spec->board_config < 0) - snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC925x," - "using BIOS defaults\n"); + snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", + codec->chip_name); else stac92xx_set_config_regs(codec, stac925x_brd_tbl[spec->board_config]); @@ -4884,6 +5035,9 @@ static int patch_stac925x(struct hda_codec *codec) spec->init = stac925x_core_init; spec->mixer = stac925x_mixer; + spec->num_caps = 1; + spec->capvols = stac925x_capvols; + spec->capsws = stac925x_capsws; err = stac92xx_parse_auto_config(codec, 0x8, 0x7); if (!err) { @@ -4936,8 +5090,8 @@ static int patch_stac92hd73xx(struct hda_codec *codec) stac92hd73xx_cfg_tbl); again: if (spec->board_config < 0) - snd_printdd(KERN_INFO "hda_codec: Unknown model for" - " STAC92HD73XX, using BIOS defaults\n"); + snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", + codec->chip_name); else stac92xx_set_config_regs(codec, stac92hd73xx_brd_tbl[spec->board_config]); @@ -4987,6 +5141,10 @@ again: memcpy(&spec->private_dimux, &stac92hd73xx_dmux, sizeof(stac92hd73xx_dmux)); + spec->num_caps = STAC92HD73XX_NUM_CAPS; + spec->capvols = stac92hd73xx_capvols; + spec->capsws = stac92hd73xx_capsws; + switch (spec->board_config) { case STAC_DELL_EQ: spec->init = dell_eq_core_init; @@ -5106,14 +5264,18 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) spec->num_dmics = STAC92HD83XXX_NUM_DMICS; spec->dinput_mux = &stac92hd83xxx_dmux; spec->pin_nids = stac92hd83xxx_pin_nids; + spec->num_caps = STAC92HD83XXX_NUM_CAPS; + spec->capvols = stac92hd83xxx_capvols; + spec->capsws = stac92hd83xxx_capsws; + spec->board_config = snd_hda_check_board_config(codec, STAC_92HD83XXX_MODELS, stac92hd83xxx_models, stac92hd83xxx_cfg_tbl); again: if (spec->board_config < 0) - snd_printdd(KERN_INFO "hda_codec: Unknown model for" - " STAC92HD83XXX, using BIOS defaults\n"); + snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", + codec->chip_name); else stac92xx_set_config_regs(codec, stac92hd83xxx_brd_tbl[spec->board_config]); @@ -5155,6 +5317,8 @@ again: num_dacs = snd_hda_get_connections(codec, nid, conn, STAC92HD83_DAC_COUNT + 1) - 1; + if (num_dacs < 0) + num_dacs = STAC92HD83_DAC_COUNT; /* set port X to select the last DAC */ @@ -5276,8 +5440,8 @@ static int patch_stac92hd71bxx(struct hda_codec *codec) stac92hd71bxx_cfg_tbl); again: if (spec->board_config < 0) - snd_printdd(KERN_INFO "hda_codec: Unknown model for" - " STAC92HD71BXX, using BIOS defaults\n"); + snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", + codec->chip_name); else stac92xx_set_config_regs(codec, stac92hd71bxx_brd_tbl[spec->board_config]); @@ -5292,6 +5456,10 @@ again: spec->dmic_nids = stac92hd71bxx_dmic_nids; spec->dmux_nids = stac92hd71bxx_dmux_nids; + spec->num_caps = STAC92HD71BXX_NUM_CAPS; + spec->capvols = stac92hd71bxx_capvols; + spec->capsws = stac92hd71bxx_capsws; + switch (codec->vendor_id) { case 0x111d76b6: /* 4 Port without Analog Mixer */ case 0x111d76b7: @@ -5301,7 +5469,6 @@ again: case 0x111d76b5: memcpy(&spec->private_dimux, &stac92hd71bxx_dmux_nomixer, sizeof(stac92hd71bxx_dmux_nomixer)); - spec->mixer = stac92hd71bxx_mixer; spec->init = stac92hd71bxx_core_init; codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs; spec->num_dmics = stac92hd71bxx_connected_ports(codec, @@ -5314,8 +5481,6 @@ again: } break; case 0x111d7608: /* 5 Port with Analog Mixer */ - memcpy(&spec->private_dimux, &stac92hd71bxx_dmux_amixer, - sizeof(stac92hd71bxx_dmux_amixer)); spec->private_dimux.num_items--; switch (spec->board_config) { case STAC_HP_M4: @@ -5338,11 +5503,17 @@ again: /* no output amps */ spec->num_pwrs = 0; - spec->mixer = stac92hd71bxx_analog_mixer; - spec->dinput_mux = &spec->private_dimux; - + if (snd_hda_get_bool_hint(codec, "analog_mixer") == 1) { + spec->mixer = stac92hd71bxx_analog_mixer; + memcpy(&spec->private_dimux, &stac92hd71bxx_dmux_amixer, + sizeof(stac92hd71bxx_dmux_amixer)); + } else { + memcpy(&spec->private_dimux, + &stac92hd71bxx_dmux_nomixer, + sizeof(stac92hd71bxx_dmux_nomixer)); + } /* disable VSW */ - spec->init = &stac92hd71bxx_analog_core_init[HD_DISABLE_PORTF]; + spec->init = stac92hd71bxx_core_init; unmute_init++; snd_hda_codec_set_pincfg(codec, 0x0f, 0x40f000f0); snd_hda_codec_set_pincfg(codec, 0x19, 0x40f000f3); @@ -5350,8 +5521,11 @@ again: spec->num_dmics = stac92hd71bxx_connected_ports(codec, stac92hd71bxx_dmic_nids, STAC92HD71BXX_NUM_DMICS - 1); - spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids); - ndmic_nids = ARRAY_SIZE(stac92hd71bxx_dmic_nids) - 2; + if (spec->num_dmics) { + spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids); + spec->dinput_mux = &spec->private_dimux; + ndmic_nids = ARRAY_SIZE(stac92hd71bxx_dmic_nids) - 2; + } break; case 0x111d7603: /* 6 Port with Analog Mixer */ if ((codec->revision_id & 0xf) == 1) @@ -5361,17 +5535,25 @@ again: spec->num_pwrs = 0; /* fallthru */ default: - memcpy(&spec->private_dimux, &stac92hd71bxx_dmux_amixer, - sizeof(stac92hd71bxx_dmux_amixer)); - spec->dinput_mux = &spec->private_dimux; - spec->mixer = stac92hd71bxx_analog_mixer; - spec->init = stac92hd71bxx_analog_core_init; + if (snd_hda_get_bool_hint(codec, "analog_mixer") == 1) { + spec->mixer = stac92hd71bxx_analog_mixer; + memcpy(&spec->private_dimux, &stac92hd71bxx_dmux_amixer, + sizeof(stac92hd71bxx_dmux_amixer)); + } else { + memcpy(&spec->private_dimux, + &stac92hd71bxx_dmux_nomixer, + sizeof(stac92hd71bxx_dmux_nomixer)); + } + spec->init = stac92hd71bxx_core_init; codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs; spec->num_dmics = stac92hd71bxx_connected_ports(codec, stac92hd71bxx_dmic_nids, STAC92HD71BXX_NUM_DMICS); - spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids); - ndmic_nids = ARRAY_SIZE(stac92hd71bxx_dmic_nids) - 1; + if (spec->num_dmics) { + spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids); + spec->dinput_mux = &spec->private_dimux; + ndmic_nids = ARRAY_SIZE(stac92hd71bxx_dmic_nids) - 1; + } } if (get_wcaps(codec, 0xa) & AC_WCAP_IN_AMP) @@ -5532,8 +5714,8 @@ static int patch_stac922x(struct hda_codec *codec) again: if (spec->board_config < 0) - snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC922x, " - "using BIOS defaults\n"); + snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", + codec->chip_name); else stac92xx_set_config_regs(codec, stac922x_brd_tbl[spec->board_config]); @@ -5546,7 +5728,10 @@ static int patch_stac922x(struct hda_codec *codec) spec->num_pwrs = 0; spec->init = stac922x_core_init; - spec->mixer = stac922x_mixer; + + spec->num_caps = STAC922X_NUM_CAPS; + spec->capvols = stac922x_capvols; + spec->capsws = stac922x_capsws; spec->multiout.dac_nids = spec->dac_nids; @@ -5595,8 +5780,8 @@ static int patch_stac927x(struct hda_codec *codec) stac927x_cfg_tbl); again: if (spec->board_config < 0) - snd_printdd(KERN_INFO "hda_codec: Unknown model for" - "STAC927x, using BIOS defaults\n"); + snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", + codec->chip_name); else stac92xx_set_config_regs(codec, stac927x_brd_tbl[spec->board_config]); @@ -5621,7 +5806,6 @@ static int patch_stac927x(struct hda_codec *codec) spec->num_dmics = 0; spec->init = d965_core_init; - spec->mixer = stac927x_mixer; break; case STAC_DELL_BIOS: switch (codec->subsystem_id) { @@ -5646,7 +5830,6 @@ static int patch_stac927x(struct hda_codec *codec) spec->num_dmics = STAC927X_NUM_DMICS; spec->init = d965_core_init; - spec->mixer = stac927x_mixer; spec->dmux_nids = stac927x_dmux_nids; spec->num_dmuxes = ARRAY_SIZE(stac927x_dmux_nids); break; @@ -5659,9 +5842,12 @@ static int patch_stac927x(struct hda_codec *codec) spec->num_dmics = 0; spec->init = stac927x_core_init; - spec->mixer = stac927x_mixer; } + spec->num_caps = STAC927X_NUM_CAPS; + spec->capvols = stac927x_capvols; + spec->capsws = stac927x_capsws; + spec->num_pwrs = 0; spec->aloopback_ctl = stac927x_loopback; spec->aloopback_mask = 0x40; @@ -5723,7 +5909,8 @@ static int patch_stac9205(struct hda_codec *codec) stac9205_cfg_tbl); again: if (spec->board_config < 0) - snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9205, using BIOS defaults\n"); + snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", + codec->chip_name); else stac92xx_set_config_regs(codec, stac9205_brd_tbl[spec->board_config]); @@ -5742,9 +5929,12 @@ static int patch_stac9205(struct hda_codec *codec) spec->num_pwrs = 0; spec->init = stac9205_core_init; - spec->mixer = stac9205_mixer; spec->aloopback_ctl = stac9205_loopback; + spec->num_caps = STAC9205_NUM_CAPS; + spec->capvols = stac9205_capvols; + spec->capsws = stac9205_capsws; + spec->aloopback_mask = 0x40; spec->aloopback_shift = 0; /* Turn on/off EAPD per HP plugging */ @@ -5819,12 +6009,6 @@ static struct hda_verb stac9872_core_init[] = { {} }; -static struct snd_kcontrol_new stac9872_mixer[] = { - HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT), - HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT), - { } /* end */ -}; - static hda_nid_t stac9872_pin_nids[] = { 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x11, 0x13, 0x14, @@ -5838,6 +6022,11 @@ static hda_nid_t stac9872_mux_nids[] = { 0x15 }; +static unsigned long stac9872_capvols[] = { + HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_INPUT), +}; +#define stac9872_capsws stac9872_capvols + static unsigned int stac9872_vaio_pin_configs[9] = { 0x03211020, 0x411111f0, 0x411111f0, 0x03a15030, 0x411111f0, 0x90170110, 0x411111f0, 0x411111f0, @@ -5854,6 +6043,8 @@ static unsigned int *stac9872_brd_tbl[STAC_9872_MODELS] = { }; static struct snd_pci_quirk stac9872_cfg_tbl[] = { + SND_PCI_QUIRK_MASK(0x104d, 0xfff0, 0x81e0, + "Sony VAIO F/S", STAC_9872_VAIO), {} /* terminator */ }; @@ -5866,26 +6057,28 @@ static int patch_stac9872(struct hda_codec *codec) if (spec == NULL) return -ENOMEM; codec->spec = spec; + spec->num_pins = ARRAY_SIZE(stac9872_pin_nids); + spec->pin_nids = stac9872_pin_nids; spec->board_config = snd_hda_check_board_config(codec, STAC_9872_MODELS, stac9872_models, stac9872_cfg_tbl); if (spec->board_config < 0) - snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9872, " - "using BIOS defaults\n"); + snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n", + codec->chip_name); else stac92xx_set_config_regs(codec, stac9872_brd_tbl[spec->board_config]); - spec->num_pins = ARRAY_SIZE(stac9872_pin_nids); - spec->pin_nids = stac9872_pin_nids; spec->multiout.dac_nids = spec->dac_nids; spec->num_adcs = ARRAY_SIZE(stac9872_adc_nids); spec->adc_nids = stac9872_adc_nids; spec->num_muxes = ARRAY_SIZE(stac9872_mux_nids); spec->mux_nids = stac9872_mux_nids; - spec->mixer = stac9872_mixer; spec->init = stac9872_core_init; + spec->num_caps = 1; + spec->capvols = stac9872_capvols; + spec->capsws = stac9872_capsws; err = stac92xx_parse_auto_config(codec, 0x10, 0x12); if (err < 0) {