diff options
Diffstat (limited to 'sound/pci/hda')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 70 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.h | 1 | ||||
-rw-r--r-- | sound/pci/hda/hda_eld.c | 41 | ||||
-rw-r--r-- | sound/pci/hda/hda_intel.c | 1 | ||||
-rw-r--r-- | sound/pci/hda/hda_local.h | 19 | ||||
-rw-r--r-- | sound/pci/hda/patch_cirrus.c | 55 | ||||
-rw-r--r-- | sound/pci/hda/patch_conexant.c | 1 | ||||
-rw-r--r-- | sound/pci/hda/patch_hdmi.c | 59 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 51 | ||||
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 113 | ||||
-rw-r--r-- | sound/pci/hda/patch_via.c | 76 |
11 files changed, 285 insertions, 202 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 916a1863af7..4562e9de6a1 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -2331,6 +2331,39 @@ int snd_hda_codec_reset(struct hda_codec *codec) return 0; } +typedef int (*map_slave_func_t)(void *, struct snd_kcontrol *); + +/* apply the function to all matching slave ctls in the mixer list */ +static int map_slaves(struct hda_codec *codec, const char * const *slaves, + map_slave_func_t func, void *data) +{ + struct hda_nid_item *items; + const char * const *s; + int i, err; + + items = codec->mixers.list; + for (i = 0; i < codec->mixers.used; i++) { + struct snd_kcontrol *sctl = items[i].kctl; + if (!sctl || !sctl->id.name || + sctl->id.iface != SNDRV_CTL_ELEM_IFACE_MIXER) + continue; + for (s = slaves; *s; s++) { + if (!strcmp(sctl->id.name, *s)) { + err = func(data, sctl); + if (err) + return err; + break; + } + } + } + return 0; +} + +static int check_slave_present(void *data, struct snd_kcontrol *sctl) +{ + return 1; +} + /** * snd_hda_add_vmaster - create a virtual master control and add slaves * @codec: HD-audio codec @@ -2351,12 +2384,10 @@ int snd_hda_add_vmaster(struct hda_codec *codec, char *name, unsigned int *tlv, const char * const *slaves) { struct snd_kcontrol *kctl; - const char * const *s; int err; - for (s = slaves; *s && !snd_hda_find_mixer_ctl(codec, *s); s++) - ; - if (!*s) { + err = map_slaves(codec, slaves, check_slave_present, NULL); + if (err != 1) { snd_printdd("No slave found for %s\n", name); return 0; } @@ -2367,23 +2398,10 @@ int snd_hda_add_vmaster(struct hda_codec *codec, char *name, if (err < 0) return err; - for (s = slaves; *s; s++) { - struct snd_kcontrol *sctl; - int i = 0; - for (;;) { - sctl = _snd_hda_find_mixer_ctl(codec, *s, i); - if (!sctl) { - if (!i) - snd_printdd("Cannot find slave %s, " - "skipped\n", *s); - break; - } - err = snd_ctl_add_slave(kctl, sctl); - if (err < 0) - return err; - i++; - } - } + err = map_slaves(codec, slaves, (map_slave_func_t)snd_ctl_add_slave, + kctl); + if (err < 0) + return err; return 0; } EXPORT_SYMBOL_HDA(snd_hda_add_vmaster); @@ -4028,9 +4046,9 @@ int snd_hda_check_board_codec_sid_config(struct hda_codec *codec, /* Search for codec ID */ for (q = tbl; q->subvendor; q++) { - unsigned long vendorid = (q->subdevice) | (q->subvendor << 16); - - if (vendorid == codec->subsystem_id) + unsigned int mask = 0xffff0000 | q->subdevice_mask; + unsigned int id = (q->subdevice | (q->subvendor << 16)) & mask; + if ((codec->subsystem_id & mask) == id) break; } @@ -4752,6 +4770,7 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec, memset(sequences_hp, 0, sizeof(sequences_hp)); assoc_line_out = 0; + codec->ignore_misc_bit = true; end_nid = codec->start_nid + codec->num_nodes; for (nid = codec->start_nid; nid < end_nid; nid++) { unsigned int wid_caps = get_wcaps(codec, nid); @@ -4767,6 +4786,9 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec, continue; def_conf = snd_hda_codec_get_pincfg(codec, nid); + if (!(get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid)) & + AC_DEFCFG_MISC_NO_PRESENCE)) + codec->ignore_misc_bit = false; conn = get_defcfg_connect(def_conf); if (conn == AC_JACK_PORT_NONE) continue; diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 755f2b0f9d8..564471169ca 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h @@ -854,6 +854,7 @@ struct hda_codec { unsigned int no_sticky_stream:1; /* no sticky-PCM stream assignment */ unsigned int pins_shutup:1; /* pins are shut up */ unsigned int no_trigger_sense:1; /* don't trigger at pin-sensing */ + unsigned int ignore_misc_bit:1; /* ignore MISC_NO_PRESENCE bit */ #ifdef CONFIG_SND_HDA_POWER_SAVE unsigned int power_on :1; /* current (global) power-state */ unsigned int power_transition :1; /* power-state in transition */ diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c index 1c8ddf547a2..c1da422e085 100644 --- a/sound/pci/hda/hda_eld.c +++ b/sound/pci/hda/hda_eld.c @@ -297,10 +297,18 @@ static int hdmi_update_eld(struct hdmi_eld *e, buf + ELD_FIXED_BYTES + mnl + 3 * i); } + /* + * HDMI sink's ELD info cannot always be retrieved for now, e.g. + * in console or for audio devices. Assume the highest speakers + * configuration, to _not_ prohibit multi-channel audio playback. + */ + if (!e->spk_alloc) + e->spk_alloc = 0xffff; + + e->eld_valid = true; return 0; out_fail: - e->eld_ver = 0; return -EINVAL; } @@ -323,9 +331,6 @@ int snd_hdmi_get_eld(struct hdmi_eld *eld, * ELD is valid, actual eld_size is assigned in hdmi_update_eld() */ - if (!eld->eld_valid) - return -ENOENT; - size = snd_hdmi_get_eld_size(codec, nid); if (size == 0) { /* wfg: workaround for ASUS P5E-VM HDMI board */ @@ -342,18 +347,28 @@ int snd_hdmi_get_eld(struct hdmi_eld *eld, for (i = 0; i < size; i++) { unsigned int val = hdmi_get_eld_data(codec, nid, i); + /* + * Graphics driver might be writing to ELD buffer right now. + * Just abort. The caller will repoll after a while. + */ if (!(val & AC_ELDD_ELD_VALID)) { - if (!i) { - snd_printd(KERN_INFO - "HDMI: invalid ELD data\n"); - ret = -EINVAL; - goto error; - } snd_printd(KERN_INFO "HDMI: invalid ELD data byte %d\n", i); - val = 0; - } else - val &= AC_ELDD_ELD_DATA; + ret = -EINVAL; + goto error; + } + val &= AC_ELDD_ELD_DATA; + /* + * The first byte cannot be zero. This can happen on some DVI + * connections. Some Intel chips may also need some 250ms delay + * to return non-zero ELD data, even when the graphics driver + * correctly writes ELD content before setting ELD_valid bit. + */ + if (!val && !i) { + snd_printdd(KERN_INFO "HDMI: 0 ELD data\n"); + ret = -EINVAL; + goto error; + } buf[i] = val; } diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 096507d2ca9..7d98240def0 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2508,7 +2508,6 @@ static struct snd_pci_quirk position_fix_list[] __devinitdata = { SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS", POS_FIX_LPIB), SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS M2V", POS_FIX_LPIB), SND_PCI_QUIRK(0x104d, 0x9069, "Sony VPCS11V9E", POS_FIX_LPIB), - SND_PCI_QUIRK(0x1106, 0x3288, "ASUS M2V-MX SE", POS_FIX_LPIB), SND_PCI_QUIRK(0x1297, 0x3166, "Shuttle", POS_FIX_LPIB), SND_PCI_QUIRK(0x1458, 0xa022, "ga-ma770-ud3", POS_FIX_LPIB), SND_PCI_QUIRK(0x1462, 0x1002, "MSI Wind U115", POS_FIX_LPIB), diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index dcbea0da0fa..618ddad1723 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h @@ -510,13 +510,15 @@ int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid); static inline bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid) { - return (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_PRES_DETECT) && - /* disable MISC_NO_PRESENCE check because it may break too - * many devices - */ - /*(get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid) & - AC_DEFCFG_MISC_NO_PRESENCE)) &&*/ - (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP); + if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_PRES_DETECT)) + return false; + if (!codec->ignore_misc_bit && + (get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid)) & + AC_DEFCFG_MISC_NO_PRESENCE)) + return false; + if (!(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP)) + return false; + return true; } /* flags for hda_nid_item */ @@ -651,6 +653,9 @@ struct hdmi_eld { int spk_alloc; int sad_count; struct cea_sad sad[ELD_MAX_SAD]; + /* + * all fields above eld_buffer will be cleared before updating ELD + */ char eld_buffer[ELD_MAX_SIZE]; #ifdef CONFIG_PROC_FS struct snd_info_entry *proc_entry; diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 2a2d8645ba0..70a7abda7e2 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c @@ -58,6 +58,8 @@ struct cs_spec { unsigned int gpio_mask; unsigned int gpio_dir; unsigned int gpio_data; + unsigned int gpio_eapd_hp; /* EAPD GPIO bit for headphones */ + unsigned int gpio_eapd_speaker; /* EAPD GPIO bit for speakers */ struct hda_pcm pcm_rec[2]; /* PCM information */ @@ -76,6 +78,7 @@ enum { CS420X_MBP53, CS420X_MBP55, CS420X_IMAC27, + CS420X_APPLE, CS420X_AUTO, CS420X_MODELS }; @@ -237,6 +240,15 @@ static int cs_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout); } +static void cs_update_input_select(struct hda_codec *codec) +{ + struct cs_spec *spec = codec->spec; + if (spec->cur_adc) + snd_hda_codec_write(codec, spec->cur_adc, 0, + AC_VERB_SET_CONNECT_SEL, + spec->adc_idx[spec->cur_input]); +} + /* * Analog capture */ @@ -250,6 +262,7 @@ static int cs_capture_pcm_prepare(struct hda_pcm_stream *hinfo, spec->cur_adc = spec->adc_nid[spec->cur_input]; spec->cur_adc_stream_tag = stream_tag; spec->cur_adc_format = format; + cs_update_input_select(codec); snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format); return 0; } @@ -689,10 +702,8 @@ static int change_cur_input(struct hda_codec *codec, unsigned int idx, spec->cur_adc_stream_tag, 0, spec->cur_adc_format); } - snd_hda_codec_write(codec, spec->cur_adc, 0, - AC_VERB_SET_CONNECT_SEL, - spec->adc_idx[idx]); spec->cur_input = idx; + cs_update_input_select(codec); return 1; } @@ -920,10 +931,9 @@ static void cs_automute(struct hda_codec *codec) spdif_present ? 0 : PIN_OUT); } } - if (spec->board_config == CS420X_MBP53 || - spec->board_config == CS420X_MBP55 || - spec->board_config == CS420X_IMAC27) { - unsigned int gpio = hp_present ? 0x02 : 0x08; + if (spec->gpio_eapd_hp) { + unsigned int gpio = hp_present ? + spec->gpio_eapd_hp : spec->gpio_eapd_speaker; snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, gpio); } @@ -973,10 +983,7 @@ static void cs_automic(struct hda_codec *codec) } else { spec->cur_input = spec->last_input; } - - snd_hda_codec_write_cache(codec, spec->cur_adc, 0, - AC_VERB_SET_CONNECT_SEL, - spec->adc_idx[spec->cur_input]); + cs_update_input_select(codec); } else { if (present) change_cur_input(codec, spec->automic_idx, 0); @@ -1073,9 +1080,7 @@ static void init_input(struct hda_codec *codec) cs_automic(codec); else { spec->cur_adc = spec->adc_nid[spec->cur_input]; - snd_hda_codec_write(codec, spec->cur_adc, 0, - AC_VERB_SET_CONNECT_SEL, - spec->adc_idx[spec->cur_input]); + cs_update_input_select(codec); } } else { change_cur_input(codec, spec->cur_input, 1); @@ -1273,6 +1278,7 @@ static const char * const cs420x_models[CS420X_MODELS] = { [CS420X_MBP53] = "mbp53", [CS420X_MBP55] = "mbp55", [CS420X_IMAC27] = "imac27", + [CS420X_APPLE] = "apple", [CS420X_AUTO] = "auto", }; @@ -1282,7 +1288,13 @@ static const struct snd_pci_quirk cs420x_cfg_tbl[] = { SND_PCI_QUIRK(0x10de, 0x0d94, "MacBookAir 3,1(2)", CS420X_MBP55), SND_PCI_QUIRK(0x10de, 0xcb79, "MacBookPro 5,5", CS420X_MBP55), SND_PCI_QUIRK(0x10de, 0xcb89, "MacBookPro 7,1", CS420X_MBP55), - SND_PCI_QUIRK(0x8086, 0x7270, "IMac 27 Inch", CS420X_IMAC27), + /* this conflicts with too many other models */ + /*SND_PCI_QUIRK(0x8086, 0x7270, "IMac 27 Inch", CS420X_IMAC27),*/ + {} /* terminator */ +}; + +static const struct snd_pci_quirk cs420x_codec_cfg_tbl[] = { + SND_PCI_QUIRK_VENDOR(0x106b, "Apple", CS420X_APPLE), {} /* terminator */ }; @@ -1364,6 +1376,10 @@ static int patch_cs420x(struct hda_codec *codec) spec->board_config = snd_hda_check_board_config(codec, CS420X_MODELS, cs420x_models, cs420x_cfg_tbl); + if (spec->board_config < 0) + spec->board_config = + snd_hda_check_board_codec_sid_config(codec, + CS420X_MODELS, NULL, cs420x_codec_cfg_tbl); if (spec->board_config >= 0) fix_pincfg(codec, spec->board_config, cs_pincfgs); @@ -1371,10 +1387,11 @@ static int patch_cs420x(struct hda_codec *codec) case CS420X_IMAC27: case CS420X_MBP53: case CS420X_MBP55: - /* GPIO1 = headphones */ - /* GPIO3 = speakers */ - spec->gpio_mask = 0x0a; - spec->gpio_dir = 0x0a; + case CS420X_APPLE: + spec->gpio_eapd_hp = 2; /* GPIO1 = headphones */ + spec->gpio_eapd_speaker = 8; /* GPIO3 = speakers */ + spec->gpio_mask = spec->gpio_dir = + spec->gpio_eapd_hp | spec->gpio_eapd_speaker; break; } diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 5e706e4d173..0de21193a2b 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -3062,7 +3062,6 @@ static const struct snd_pci_quirk cxt5066_cfg_tbl[] = { SND_PCI_QUIRK(0x1043, 0x1993, "Asus U50F", CXT5066_ASUS), SND_PCI_QUIRK(0x1179, 0xff1e, "Toshiba Satellite C650D", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba Satellite P500-PSPGSC-01800T", CXT5066_OLPC_XO_1_5), - SND_PCI_QUIRK(0x1179, 0xffe0, "Toshiba Satellite Pro T130-15F", CXT5066_OLPC_XO_1_5), SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board", CXT5066_LAPTOP), SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5), diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 81b7b791b3c..c505fd5d338 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -65,7 +65,11 @@ struct hdmi_spec_per_pin { hda_nid_t pin_nid; int num_mux_nids; hda_nid_t mux_nids[HDA_MAX_CONNECTIONS]; + + struct hda_codec *codec; struct hdmi_eld sink_eld; + struct delayed_work work; + int repoll_count; }; struct hdmi_spec { @@ -745,8 +749,7 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, int pin_idx, * Unsolicited events */ -static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid, - struct hdmi_eld *eld); +static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll); static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) { @@ -755,7 +758,6 @@ static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) int pd = !!(res & AC_UNSOL_RES_PD); int eldv = !!(res & AC_UNSOL_RES_ELDV); int pin_idx; - struct hdmi_eld *eld; printk(KERN_INFO "HDMI hot plug event: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n", @@ -764,17 +766,8 @@ static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) pin_idx = pin_nid_to_pin_index(spec, pin_nid); if (pin_idx < 0) return; - eld = &spec->pins[pin_idx].sink_eld; - - hdmi_present_sense(codec, pin_nid, eld); - /* - * HDMI sink's ELD info cannot always be retrieved for now, e.g. - * in console or for audio devices. Assume the highest speakers - * configuration, to _not_ prohibit multi-channel audio playback. - */ - if (!eld->spk_alloc) - eld->spk_alloc = 0xffff; + hdmi_present_sense(&spec->pins[pin_idx], 1); } static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res) @@ -968,9 +961,11 @@ static int hdmi_read_pin_conn(struct hda_codec *codec, int pin_idx) return 0; } -static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid, - struct hdmi_eld *eld) +static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll) { + struct hda_codec *codec = per_pin->codec; + struct hdmi_eld *eld = &per_pin->sink_eld; + hda_nid_t pin_nid = per_pin->pin_nid; /* * Always execute a GetPinSense verb here, even when called from * hdmi_intrinsic_event; for some NVIDIA HW, the unsolicited @@ -980,26 +975,42 @@ static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid, * the unsolicited response to avoid custom WARs. */ int present = snd_hda_pin_sense(codec, pin_nid); + bool eld_valid = false; - memset(eld, 0, sizeof(*eld)); + memset(eld, 0, offsetof(struct hdmi_eld, eld_buffer)); eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE); if (eld->monitor_present) - eld->eld_valid = !!(present & AC_PINSENSE_ELDV); - else - eld->eld_valid = 0; + eld_valid = !!(present & AC_PINSENSE_ELDV); printk(KERN_INFO "HDMI status: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n", - codec->addr, pin_nid, eld->monitor_present, eld->eld_valid); + codec->addr, pin_nid, eld->monitor_present, eld_valid); - if (eld->eld_valid) + if (eld_valid) { if (!snd_hdmi_get_eld(eld, codec, pin_nid)) snd_hdmi_show_eld(eld); + else if (repoll) { + queue_delayed_work(codec->bus->workq, + &per_pin->work, + msecs_to_jiffies(300)); + } + } snd_hda_input_jack_report(codec, pin_nid); } +static void hdmi_repoll_eld(struct work_struct *work) +{ + struct hdmi_spec_per_pin *per_pin = + container_of(to_delayed_work(work), struct hdmi_spec_per_pin, work); + + if (per_pin->repoll_count++ > 6) + per_pin->repoll_count = 0; + + hdmi_present_sense(per_pin, per_pin->repoll_count); +} + static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) { struct hdmi_spec *spec = codec->spec; @@ -1228,7 +1239,7 @@ static int generic_hdmi_build_jack(struct hda_codec *codec, int pin_idx) if (err < 0) return err; - hdmi_present_sense(codec, per_pin->pin_nid, &per_pin->sink_eld); + hdmi_present_sense(per_pin, 0); return 0; } @@ -1279,6 +1290,8 @@ static int generic_hdmi_init(struct hda_codec *codec) AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | pin_nid); + per_pin->codec = codec; + INIT_DELAYED_WORK(&per_pin->work, hdmi_repoll_eld); snd_hda_eld_proc_new(codec, eld, pin_idx); } return 0; @@ -1293,10 +1306,12 @@ static void generic_hdmi_free(struct hda_codec *codec) struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; struct hdmi_eld *eld = &per_pin->sink_eld; + cancel_delayed_work(&per_pin->work); snd_hda_eld_proc_free(codec, eld); } snd_hda_input_jack_free(codec); + flush_workqueue(codec->bus->workq); kfree(spec); } diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index a24e068a021..a7d1bc4e0d0 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -277,6 +277,12 @@ static bool alc_dyn_adc_pcm_resetup(struct hda_codec *codec, int cur) return false; } +static inline hda_nid_t get_capsrc(struct alc_spec *spec, int idx) +{ + return spec->capsrc_nids ? + spec->capsrc_nids[idx] : spec->adc_nids[idx]; +} + /* select the given imux item; either unmute exclusively or select the route */ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx, unsigned int idx, bool force) @@ -284,13 +290,15 @@ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx, struct alc_spec *spec = codec->spec; const struct hda_input_mux *imux; unsigned int mux_idx; - int i, type; + int i, type, num_conns; hda_nid_t nid; mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx; imux = &spec->input_mux[mux_idx]; if (!imux->num_items && mux_idx > 0) imux = &spec->input_mux[0]; + if (!imux->num_items) + return 0; if (idx >= imux->num_items) idx = imux->num_items - 1; @@ -303,20 +311,20 @@ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx, adc_idx = spec->dyn_adc_idx[idx]; } - nid = spec->capsrc_nids ? - spec->capsrc_nids[adc_idx] : spec->adc_nids[adc_idx]; + nid = get_capsrc(spec, adc_idx); /* no selection? */ - if (snd_hda_get_conn_list(codec, nid, NULL) <= 1) + num_conns = snd_hda_get_conn_list(codec, nid, NULL); + if (num_conns <= 1) return 1; type = get_wcaps_type(get_wcaps(codec, nid)); if (type == AC_WID_AUD_MIX) { /* Matrix-mixer style (e.g. ALC882) */ - for (i = 0; i < imux->num_items; i++) { - unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE; - snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, - imux->items[i].index, + int active = imux->items[idx].index; + for (i = 0; i < num_conns; i++) { + unsigned int v = (i == active) ? 0 : HDA_AMP_MUTE; + snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, i, HDA_AMP_MUTE, v); } } else { @@ -1053,8 +1061,19 @@ static bool alc_rebuild_imux_for_auto_mic(struct hda_codec *codec) spec->imux_pins[2] = spec->dock_mic_pin; for (i = 0; i < 3; i++) { strcpy(imux->items[i].label, texts[i]); - if (spec->imux_pins[i]) + if (spec->imux_pins[i]) { + hda_nid_t pin = spec->imux_pins[i]; + int c; + for (c = 0; c < spec->num_adc_nids; c++) { + hda_nid_t cap = get_capsrc(spec, c); + int idx = get_connection_index(codec, cap, pin); + if (idx >= 0) { + imux->items[i].index = idx; + break; + } + } imux->num_items = i + 1; + } } spec->num_mux_defs = 1; spec->input_mux = imux; @@ -1451,7 +1470,7 @@ static void alc_apply_fixup(struct hda_codec *codec, int action) switch (fix->type) { case ALC_FIXUP_SKU: if (action != ALC_FIXUP_ACT_PRE_PROBE || !fix->v.sku) - break;; + break; snd_printdd(KERN_INFO "hda_codec: %s: " "Apply sku override for %s\n", codec->chip_name, modelname); @@ -1956,10 +1975,8 @@ static int alc_build_controls(struct hda_codec *codec) if (!kctl) kctl = snd_hda_find_mixer_ctl(codec, "Input Source"); for (i = 0; kctl && i < kctl->count; i++) { - const hda_nid_t *nids = spec->capsrc_nids; - if (!nids) - nids = spec->adc_nids; - err = snd_hda_add_nid(codec, kctl, i, nids[i]); + err = snd_hda_add_nid(codec, kctl, i, + get_capsrc(spec, i)); if (err < 0) return err; } @@ -2746,8 +2763,7 @@ static int alc_auto_create_input_ctls(struct hda_codec *codec) } for (c = 0; c < num_adcs; c++) { - hda_nid_t cap = spec->capsrc_nids ? - spec->capsrc_nids[c] : spec->adc_nids[c]; + hda_nid_t cap = get_capsrc(spec, c); idx = get_connection_index(codec, cap, pin); if (idx >= 0) { spec->imux_pins[imux->num_items] = pin; @@ -3693,8 +3709,7 @@ static int init_capsrc_for_pin(struct hda_codec *codec, hda_nid_t pin) if (!pin) return 0; for (i = 0; i < spec->num_adc_nids; i++) { - hda_nid_t cap = spec->capsrc_nids ? - spec->capsrc_nids[i] : spec->adc_nids[i]; + hda_nid_t cap = get_capsrc(spec, i); int idx; idx = get_connection_index(codec, cap, pin); diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 4e715fefebe..eeb25d529e3 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -95,6 +95,7 @@ enum { STAC_92HD83XXX_REF, STAC_92HD83XXX_PWR_REF, STAC_DELL_S14, + STAC_DELL_VOSTRO_3500, STAC_92HD83XXX_HP, STAC_92HD83XXX_HP_cNB11_INTQUAD, STAC_HP_DV7_4000, @@ -214,6 +215,7 @@ struct sigmatel_spec { unsigned int gpio_mute; unsigned int gpio_led; unsigned int gpio_led_polarity; + unsigned int vref_mute_led_nid; /* pin NID for mute-LED vref control */ unsigned int vref_led; /* stream */ @@ -226,7 +228,6 @@ struct sigmatel_spec { /* power management */ unsigned int num_pwrs; - const unsigned int *pwr_mapping; const hda_nid_t *pwr_nids; const hda_nid_t *dac_list; @@ -373,18 +374,15 @@ static const unsigned long stac92hd73xx_capvols[] = { #define STAC92HD83_DAC_COUNT 3 -static const hda_nid_t stac92hd83xxx_pwr_nids[4] = { - 0xa, 0xb, 0xd, 0xe, +static const hda_nid_t stac92hd83xxx_pwr_nids[7] = { + 0x0a, 0x0b, 0x0c, 0xd, 0x0e, + 0x0f, 0x10 }; static const hda_nid_t stac92hd83xxx_slave_dig_outs[2] = { 0x1e, 0, }; -static const unsigned int stac92hd83xxx_pwr_mapping[4] = { - 0x03, 0x0c, 0x20, 0x40, -}; - static const hda_nid_t stac92hd83xxx_dmic_nids[] = { 0x11, 0x20, }; @@ -1644,6 +1642,8 @@ static const struct snd_pci_quirk stac92hd73xx_codec_id_cfg_tbl[] = { "Alienware M17x", STAC_ALIENWARE_M17X), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x043a, "Alienware M17x", STAC_ALIENWARE_M17X), + SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0490, + "Alienware M17x", STAC_ALIENWARE_M17X), {} /* terminator */ }; @@ -1659,6 +1659,12 @@ static const unsigned int dell_s14_pin_configs[10] = { 0x40f000f0, 0x40f000f0, }; +static const unsigned int dell_vostro_3500_pin_configs[10] = { + 0x02a11020, 0x0221101f, 0x400000f0, 0x90170110, + 0x400000f1, 0x400000f2, 0x400000f3, 0x90a60160, + 0x400000f4, 0x400000f5, +}; + static const unsigned int hp_dv7_4000_pin_configs[10] = { 0x03a12050, 0x0321201f, 0x40f000f0, 0x90170110, 0x40f000f0, 0x40f000f0, 0x90170110, 0xd5a30140, @@ -1675,6 +1681,7 @@ static const unsigned int *stac92hd83xxx_brd_tbl[STAC_92HD83XXX_MODELS] = { [STAC_92HD83XXX_REF] = ref92hd83xxx_pin_configs, [STAC_92HD83XXX_PWR_REF] = ref92hd83xxx_pin_configs, [STAC_DELL_S14] = dell_s14_pin_configs, + [STAC_DELL_VOSTRO_3500] = dell_vostro_3500_pin_configs, [STAC_92HD83XXX_HP_cNB11_INTQUAD] = hp_cNB11_intquad_pin_configs, [STAC_HP_DV7_4000] = hp_dv7_4000_pin_configs, }; @@ -1684,6 +1691,7 @@ static const char * const stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = { [STAC_92HD83XXX_REF] = "ref", [STAC_92HD83XXX_PWR_REF] = "mic-ref", [STAC_DELL_S14] = "dell-s14", + [STAC_DELL_VOSTRO_3500] = "dell-vostro-3500", [STAC_92HD83XXX_HP] = "hp", [STAC_92HD83XXX_HP_cNB11_INTQUAD] = "hp_cNB11_intquad", [STAC_HP_DV7_4000] = "hp-dv7-4000", @@ -1697,6 +1705,8 @@ static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { "DFI LanParty", STAC_92HD83XXX_REF), SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ba, "unknown Dell", STAC_DELL_S14), + SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x1028, + "Dell Vostro 3500", STAC_DELL_VOSTRO_3500), SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xff00, 0x3600, "HP", STAC_92HD83XXX_HP), SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1656, @@ -4309,12 +4319,10 @@ static void stac_store_hints(struct hda_codec *codec) spec->eapd_switch = val; get_int_hint(codec, "gpio_led_polarity", &spec->gpio_led_polarity); if (get_int_hint(codec, "gpio_led", &spec->gpio_led)) { - if (spec->gpio_led <= 8) { - spec->gpio_mask |= spec->gpio_led; - spec->gpio_dir |= spec->gpio_led; - if (spec->gpio_led_polarity) - spec->gpio_data |= spec->gpio_led; - } + spec->gpio_mask |= spec->gpio_led; + spec->gpio_dir |= spec->gpio_led; + if (spec->gpio_led_polarity) + spec->gpio_data |= spec->gpio_led; } } @@ -4432,7 +4440,9 @@ static int stac92xx_init(struct hda_codec *codec) int pinctl, def_conf; /* power on when no jack detection is available */ - if (!spec->hp_detect) { + /* or when the VREF is used for controlling LED */ + if (!spec->hp_detect || + spec->vref_mute_led_nid == nid) { stac_toggle_power_map(codec, nid, 1); continue; } @@ -4459,8 +4469,12 @@ static int stac92xx_init(struct hda_codec *codec) stac_toggle_power_map(codec, nid, 1); continue; } - if (enable_pin_detect(codec, nid, STAC_PWR_EVENT)) + if (enable_pin_detect(codec, nid, STAC_PWR_EVENT)) { stac_issue_unsol_event(codec, nid); + continue; + } + /* none of the above, turn the port OFF */ + stac_toggle_power_map(codec, nid, 0); } /* sync mute LED */ @@ -4716,11 +4730,7 @@ static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid, if (idx >= spec->num_pwrs) return; - /* several codecs have two power down bits */ - if (spec->pwr_mapping) - idx = spec->pwr_mapping[idx]; - else - idx = 1 << idx; + idx = 1 << idx; val = snd_hda_codec_read(codec, codec->afg, 0, 0x0fec, 0x0) & 0xff; if (enable) @@ -4904,8 +4914,14 @@ static int find_mute_led_gpio(struct hda_codec *codec, int default_polarity) if (sscanf(dev->name, "HP_Mute_LED_%d_%x", &spec->gpio_led_polarity, &spec->gpio_led) == 2) { - if (spec->gpio_led < 4) + unsigned int max_gpio; + max_gpio = snd_hda_param_read(codec, codec->afg, + AC_PAR_GPIO_CAP); + max_gpio &= AC_GPIO_IO_COUNT; + if (spec->gpio_led < max_gpio) spec->gpio_led = 1 << spec->gpio_led; + else + spec->vref_mute_led_nid = spec->gpio_led; return 1; } if (sscanf(dev->name, "HP_Mute_LED_%d", @@ -5034,29 +5050,12 @@ static int stac92xx_pre_resume(struct hda_codec *codec) struct sigmatel_spec *spec = codec->spec; /* sync mute LED */ - if (spec->gpio_led) { - if (spec->gpio_led <= 8) { - stac_gpio_set(codec, spec->gpio_mask, - spec->gpio_dir, spec->gpio_data); - } else { - stac_vrefout_set(codec, - spec->gpio_led, spec->vref_led); - } - } - return 0; -} - -static int stac92xx_post_suspend(struct hda_codec *codec) -{ - struct sigmatel_spec *spec = codec->spec; - if (spec->gpio_led > 8) { - /* with vref-out pin used for mute led control - * codec AFG is prevented from D3 state, but on - * system suspend it can (and should) be used - */ - snd_hda_codec_read(codec, codec->afg, 0, - AC_VERB_SET_POWER_STATE, AC_PWRST_D3); - } + if (spec->vref_mute_led_nid) + stac_vrefout_set(codec, spec->vref_mute_led_nid, + spec->vref_led); + else if (spec->gpio_led) + stac_gpio_set(codec, spec->gpio_mask, + spec->gpio_dir, spec->gpio_data); return 0; } @@ -5067,7 +5066,7 @@ static void stac92xx_set_power_state(struct hda_codec *codec, hda_nid_t fg, struct sigmatel_spec *spec = codec->spec; if (power_state == AC_PWRST_D3) { - if (spec->gpio_led > 8) { + if (spec->vref_mute_led_nid) { /* with vref-out pin used for mute led control * codec AFG is prevented from D3 state */ @@ -5120,7 +5119,7 @@ static int stac92xx_update_led_status(struct hda_codec *codec) } } /*polarity defines *not* muted state level*/ - if (spec->gpio_led <= 8) { + if (!spec->vref_mute_led_nid) { if (muted) spec->gpio_data &= ~spec->gpio_led; /* orange */ else @@ -5138,7 +5137,8 @@ static int stac92xx_update_led_status(struct hda_codec *codec) muted_lvl = spec->gpio_led_polarity ? AC_PINCTL_VREF_GRD : AC_PINCTL_VREF_HIZ; spec->vref_led = muted ? muted_lvl : notmtd_lvl; - stac_vrefout_set(codec, spec->gpio_led, spec->vref_led); + stac_vrefout_set(codec, spec->vref_mute_led_nid, + spec->vref_led); } return 0; } @@ -5618,9 +5618,6 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) snd_hda_codec_set_pincfg(codec, 0xf, 0x2181205e); } - /* reset pin power-down; Windows may leave these bits after reboot */ - snd_hda_codec_write_cache(codec, codec->afg, 0, 0x7EC, 0); - snd_hda_codec_write_cache(codec, codec->afg, 0, 0x7ED, 0); codec->no_trigger_sense = 1; codec->spec = spec; @@ -5630,7 +5627,6 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) codec->slave_dig_outs = stac92hd83xxx_slave_dig_outs; spec->digbeep_nid = 0x21; spec->pwr_nids = stac92hd83xxx_pwr_nids; - spec->pwr_mapping = stac92hd83xxx_pwr_mapping; spec->num_pwrs = ARRAY_SIZE(stac92hd83xxx_pwr_nids); spec->multiout.dac_nids = spec->dac_nids; spec->init = stac92hd83xxx_core_init; @@ -5647,9 +5643,6 @@ again: stac92xx_set_config_regs(codec, stac92hd83xxx_brd_tbl[spec->board_config]); - if (spec->board_config != STAC_92HD83XXX_PWR_REF) - spec->num_pwrs = 0; - codec->patch_ops = stac92xx_patch_ops; if (find_mute_led_gpio(codec, 0)) @@ -5659,15 +5652,13 @@ again: #ifdef CONFIG_SND_HDA_POWER_SAVE if (spec->gpio_led) { - if (spec->gpio_led <= 8) { + if (!spec->vref_mute_led_nid) { spec->gpio_mask |= spec->gpio_led; spec->gpio_dir |= spec->gpio_led; spec->gpio_data |= spec->gpio_led; } else { codec->patch_ops.set_power_state = stac92xx_set_power_state; - codec->patch_ops.post_suspend = - stac92xx_post_suspend; } codec->patch_ops.pre_resume = stac92xx_pre_resume; codec->patch_ops.check_power_status = @@ -5858,8 +5849,6 @@ again: (codec->revision_id & 0xf) == 1) spec->stream_delay = 40; /* 40 milliseconds */ - /* no output amps */ - spec->num_pwrs = 0; /* disable VSW */ spec->init = stac92hd71bxx_core_init; unmute_init++; @@ -5874,8 +5863,6 @@ again: if ((codec->revision_id & 0xf) == 1) spec->stream_delay = 40; /* 40 milliseconds */ - /* no output amps */ - spec->num_pwrs = 0; /* fallthru */ default: spec->init = stac92hd71bxx_core_init; @@ -5978,15 +5965,13 @@ again: #ifdef CONFIG_SND_HDA_POWER_SAVE if (spec->gpio_led) { - if (spec->gpio_led <= 8) { + if (!spec->vref_mute_led_nid) { spec->gpio_mask |= spec->gpio_led; spec->gpio_dir |= spec->gpio_led; spec->gpio_data |= spec->gpio_led; } else { codec->patch_ops.set_power_state = stac92xx_set_power_state; - codec->patch_ops.post_suspend = - stac92xx_post_suspend; } codec->patch_ops.pre_resume = stac92xx_pre_resume; codec->patch_ops.check_power_status = diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 431c0d417ee..b5137629f8e 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -208,6 +208,7 @@ struct via_spec { /* work to check hp jack state */ struct hda_codec *codec; struct delayed_work vt1708_hp_work; + int hp_work_active; int vt1708_jack_detect; int vt1708_hp_present; @@ -305,27 +306,35 @@ enum { static void analog_low_current_mode(struct hda_codec *codec); static bool is_aa_path_mute(struct hda_codec *codec); -static void vt1708_start_hp_work(struct via_spec *spec) +#define hp_detect_with_aa(codec) \ + (snd_hda_get_bool_hint(codec, "analog_loopback_hp_detect") == 1 && \ + !is_aa_path_mute(codec)) + +static void vt1708_stop_hp_work(struct via_spec *spec) { if (spec->codec_type != VT1708 || spec->autocfg.hp_pins[0] == 0) return; - snd_hda_codec_write(spec->codec, 0x1, 0, 0xf81, - !spec->vt1708_jack_detect); - if (!delayed_work_pending(&spec->vt1708_hp_work)) - schedule_delayed_work(&spec->vt1708_hp_work, - msecs_to_jiffies(100)); + if (spec->hp_work_active) { + snd_hda_codec_write(spec->codec, 0x1, 0, 0xf81, 1); + cancel_delayed_work_sync(&spec->vt1708_hp_work); + spec->hp_work_active = 0; + } } -static void vt1708_stop_hp_work(struct via_spec *spec) +static void vt1708_update_hp_work(struct via_spec *spec) { if (spec->codec_type != VT1708 || spec->autocfg.hp_pins[0] == 0) return; - if (snd_hda_get_bool_hint(spec->codec, "analog_loopback_hp_detect") == 1 - && !is_aa_path_mute(spec->codec)) - return; - snd_hda_codec_write(spec->codec, 0x1, 0, 0xf81, - !spec->vt1708_jack_detect); - cancel_delayed_work_sync(&spec->vt1708_hp_work); + if (spec->vt1708_jack_detect && + (spec->active_streams || hp_detect_with_aa(spec->codec))) { + if (!spec->hp_work_active) { + snd_hda_codec_write(spec->codec, 0x1, 0, 0xf81, 0); + schedule_delayed_work(&spec->vt1708_hp_work, + msecs_to_jiffies(100)); + spec->hp_work_active = 1; + } + } else if (!hp_detect_with_aa(spec->codec)) + vt1708_stop_hp_work(spec); } static void set_widgets_power_state(struct hda_codec *codec) @@ -343,12 +352,7 @@ static int analog_input_switch_put(struct snd_kcontrol *kcontrol, set_widgets_power_state(codec); analog_low_current_mode(snd_kcontrol_chip(kcontrol)); - if (snd_hda_get_bool_hint(codec, "analog_loopback_hp_detect") == 1) { - if (is_aa_path_mute(codec)) - vt1708_start_hp_work(codec->spec); - else - vt1708_stop_hp_work(codec->spec); - } + vt1708_update_hp_work(codec->spec); return change; } @@ -1154,7 +1158,7 @@ static int via_playback_multi_pcm_prepare(struct hda_pcm_stream *hinfo, spec->cur_dac_stream_tag = stream_tag; spec->cur_dac_format = format; mutex_unlock(&spec->config_mutex); - vt1708_start_hp_work(spec); + vt1708_update_hp_work(spec); return 0; } @@ -1174,7 +1178,7 @@ static int via_playback_hp_pcm_prepare(struct hda_pcm_stream *hinfo, spec->cur_hp_stream_tag = stream_tag; spec->cur_hp_format = format; mutex_unlock(&spec->config_mutex); - vt1708_start_hp_work(spec); + vt1708_update_hp_work(spec); return 0; } @@ -1188,7 +1192,7 @@ static int via_playback_multi_pcm_cleanup(struct hda_pcm_stream *hinfo, snd_hda_multi_out_analog_cleanup(codec, &spec->multiout); spec->active_streams &= ~STREAM_MULTI_OUT; mutex_unlock(&spec->config_mutex); - vt1708_stop_hp_work(spec); + vt1708_update_hp_work(spec); return 0; } @@ -1203,7 +1207,7 @@ static int via_playback_hp_pcm_cleanup(struct hda_pcm_stream *hinfo, snd_hda_codec_setup_stream(codec, spec->hp_dac_nid, 0, 0, 0); spec->active_streams &= ~STREAM_INDEP_HP; mutex_unlock(&spec->config_mutex); - vt1708_stop_hp_work(spec); + vt1708_update_hp_work(spec); return 0; } @@ -1645,7 +1649,8 @@ static void via_hp_automute(struct hda_codec *codec) int nums; struct via_spec *spec = codec->spec; - if (!spec->hp_independent_mode && spec->autocfg.hp_pins[0]) + if (!spec->hp_independent_mode && spec->autocfg.hp_pins[0] && + (spec->codec_type != VT1708 || spec->vt1708_jack_detect)) present = snd_hda_jack_detect(codec, spec->autocfg.hp_pins[0]); if (spec->smart51_enabled) @@ -2612,8 +2617,6 @@ static int vt1708_jack_detect_get(struct snd_kcontrol *kcontrol, if (spec->codec_type != VT1708) return 0; - spec->vt1708_jack_detect = - !((snd_hda_codec_read(codec, 0x1, 0, 0xf84, 0) >> 8) & 0x1); ucontrol->value.integer.value[0] = spec->vt1708_jack_detect; return 0; } @@ -2623,18 +2626,22 @@ static int vt1708_jack_detect_put(struct snd_kcontrol *kcontrol, { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct via_spec *spec = codec->spec; - int change; + int val; if (spec->codec_type != VT1708) return 0; - spec->vt1708_jack_detect = ucontrol->value.integer.value[0]; - change = (0x1 & (snd_hda_codec_read(codec, 0x1, 0, 0xf84, 0) >> 8)) - == !spec->vt1708_jack_detect; - if (spec->vt1708_jack_detect) { + val = !!ucontrol->value.integer.value[0]; + if (spec->vt1708_jack_detect == val) + return 0; + spec->vt1708_jack_detect = val; + if (spec->vt1708_jack_detect && + snd_hda_get_bool_hint(codec, "analog_loopback_hp_detect") != 1) { mute_aa_path(codec, 1); notify_aa_path_ctls(codec); } - return change; + via_hp_automute(codec); + vt1708_update_hp_work(spec); + return 1; } static const struct snd_kcontrol_new vt1708_jack_detect_ctl = { @@ -2771,6 +2778,7 @@ static int via_init(struct hda_codec *codec) via_auto_init_unsol_event(codec); via_hp_automute(codec); + vt1708_update_hp_work(spec); return 0; } @@ -2787,7 +2795,9 @@ static void vt1708_update_hp_jack_state(struct work_struct *work) spec->vt1708_hp_present ^= 1; via_hp_automute(spec->codec); } - vt1708_start_hp_work(spec); + if (spec->vt1708_jack_detect) + schedule_delayed_work(&spec->vt1708_hp_work, + msecs_to_jiffies(100)); } static int get_mux_nids(struct hda_codec *codec) |