···11+/*22+ * Helper functions for jack-detection kcontrols33+ *44+ * Copyright (c) 2011 Takashi Iwai <tiwai@suse.de>55+ *66+ * This program is free software; you can redistribute it and/or modify it77+ * under the terms of the GNU General Public License as published by the Free88+ * Software Foundation; either version 2 of the License, or (at your option)99+ * any later version.1010+ */1111+1212+#include <linux/kernel.h>1313+#include <linux/export.h>1414+#include <sound/core.h>1515+#include <sound/control.h>1616+1717+#define jack_detect_kctl_info snd_ctl_boolean_mono_info1818+1919+static int jack_detect_kctl_get(struct snd_kcontrol *kcontrol,2020+ struct snd_ctl_elem_value *ucontrol)2121+{2222+ ucontrol->value.integer.value[0] = kcontrol->private_value;2323+ return 0;2424+}2525+2626+static struct snd_kcontrol_new jack_detect_kctl = {2727+ /* name is filled later */2828+ .iface = SNDRV_CTL_ELEM_IFACE_CARD,2929+ .access = SNDRV_CTL_ELEM_ACCESS_READ,3030+ .info = jack_detect_kctl_info,3131+ .get = jack_detect_kctl_get,3232+};3333+3434+struct snd_kcontrol *3535+snd_kctl_jack_new(const char *name, int idx, void *private_data)3636+{3737+ struct snd_kcontrol *kctl;3838+ kctl = snd_ctl_new1(&jack_detect_kctl, private_data);3939+ if (!kctl)4040+ return NULL;4141+ snprintf(kctl->id.name, sizeof(kctl->id.name), "%s Jack", name);4242+ kctl->id.index = idx;4343+ kctl->private_value = 0;4444+ return kctl;4545+}4646+EXPORT_SYMBOL_GPL(snd_kctl_jack_new);4747+4848+void snd_kctl_jack_report(struct snd_card *card,4949+ struct snd_kcontrol *kctl, bool status)5050+{5151+ if (kctl->private_value == status)5252+ return;5353+ kctl->private_value = status;5454+ snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id);5555+}5656+EXPORT_SYMBOL_GPL(snd_kctl_jack_report);
+1
sound/pci/hda/Kconfig
···22 tristate "Intel HD Audio"33 select SND_PCM44 select SND_VMASTER55+ select SND_KCTL_JACK56 help67 Say Y here to include support for Intel "High Definition78 Audio" (Azalia) and its compatible devices.
···3333#include <sound/jack.h>3434#include "hda_local.h"3535#include "hda_beep.h"3636+#include "hda_jack.h"3637#include <sound/hda_hwdep.h>37383839#define CREATE_TRACE_POINTS···17241723}17251724EXPORT_SYMBOL_HDA(snd_hda_override_pin_caps);1726172517271727-/**17281728- * snd_hda_pin_sense - execute pin sense measurement17291729- * @codec: the CODEC to sense17301730- * @nid: the pin NID to sense17311731- *17321732- * Execute necessary pin sense measurement and return its Presence Detect,17331733- * Impedance, ELD Valid etc. status bits.17341734- */17351735-u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid)17361736-{17371737- u32 pincap;17381738-17391739- if (!codec->no_trigger_sense) {17401740- pincap = snd_hda_query_pin_caps(codec, nid);17411741- if (pincap & AC_PINCAP_TRIG_REQ) /* need trigger? */17421742- snd_hda_codec_read(codec, nid, 0,17431743- AC_VERB_SET_PIN_SENSE, 0);17441744- }17451745- return snd_hda_codec_read(codec, nid, 0,17461746- AC_VERB_GET_PIN_SENSE, 0);17471747-}17481748-EXPORT_SYMBOL_HDA(snd_hda_pin_sense);17491749-17501750-/**17511751- * snd_hda_jack_detect - query pin Presence Detect status17521752- * @codec: the CODEC to sense17531753- * @nid: the pin NID to sense17541754- *17551755- * Query and return the pin's Presence Detect status.17561756- */17571757-int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid)17581758-{17591759- u32 sense = snd_hda_pin_sense(codec, nid);17601760- return !!(sense & AC_PINSENSE_PRESENCE);17611761-}17621762-EXPORT_SYMBOL_HDA(snd_hda_jack_detect);17631763-17641726/*17651727 * read the current volume to info17661728 * if the cache exists, read the cache value.···22722308 }22732309 if (codec->patch_ops.free)22742310 codec->patch_ops.free(codec);23112311+ snd_hda_jack_tbl_clear(codec);22752312 codec->proc_widget_hook = NULL;22762313 codec->spec = NULL;22772314 free_hda_cache(&codec->amp_cache);···33293364 restore_pincfgs(codec); /* restore all current pin configs */33303365 restore_shutup_pins(codec);33313366 hda_exec_init_verbs(codec);33673367+ snd_hda_jack_set_dirty_all(codec);33323368 if (codec->patch_ops.resume)33333369 codec->patch_ops.resume(codec);33343370 else {···38153849 for (i = 0; audio_idx[type][i] >= 0 ; i++)38163850 if (!test_and_set_bit(audio_idx[type][i], bus->pcm_dev_bits))38173851 return audio_idx[type][i];38523852+38533853+ /* non-fixed slots starting from 10 */38543854+ for (i = 10; i < 32; i++) {38553855+ if (!test_and_set_bit(i, bus->pcm_dev_bits))38563856+ return i;38573857+ }3818385838193859 snd_printk(KERN_WARNING "Too many %s devices\n",38203860 snd_hda_pcm_type_name[type]);···49765004 * "Rear", "Internal".49775005 */4978500649794979-const char *hda_get_input_pin_label(struct hda_codec *codec, hda_nid_t pin,49804980- int check_location)50075007+static const char *hda_get_input_pin_label(struct hda_codec *codec,50085008+ hda_nid_t pin, bool check_location)49815009{49825010 unsigned int def_conf;49835011 static const char * const mic_names[] = {···50165044 return "Misc";50175045 }50185046}50195019-EXPORT_SYMBOL_HDA(hda_get_input_pin_label);5020504750215048/* Check whether the location prefix needs to be added to the label.50225049 * If all mic-jacks are in the same location (e.g. rear panel), we don't···50715100 has_multiple_pins);50725101}50735102EXPORT_SYMBOL_HDA(hda_get_autocfg_input_label);51035103+51045104+/* return the position of NID in the list, or -1 if not found */51055105+static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)51065106+{51075107+ int i;51085108+ for (i = 0; i < nums; i++)51095109+ if (list[i] == nid)51105110+ return i;51115111+ return -1;51125112+}51135113+51145114+/* get a unique suffix or an index number */51155115+static const char *check_output_sfx(hda_nid_t nid, const hda_nid_t *pins,51165116+ int num_pins, int *indexp)51175117+{51185118+ static const char * const channel_sfx[] = {51195119+ " Front", " Surround", " CLFE", " Side"51205120+ };51215121+ int i;51225122+51235123+ i = find_idx_in_nid_list(nid, pins, num_pins);51245124+ if (i < 0)51255125+ return NULL;51265126+ if (num_pins == 1)51275127+ return "";51285128+ if (num_pins > ARRAY_SIZE(channel_sfx)) {51295129+ if (indexp)51305130+ *indexp = i;51315131+ return "";51325132+ }51335133+ return channel_sfx[i];51345134+}51355135+51365136+static int fill_audio_out_name(struct hda_codec *codec, hda_nid_t nid,51375137+ const struct auto_pin_cfg *cfg,51385138+ const char *name, char *label, int maxlen,51395139+ int *indexp)51405140+{51415141+ unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid);51425142+ int attr = snd_hda_get_input_pin_attr(def_conf);51435143+ const char *pfx = "", *sfx = "";51445144+51455145+ /* handle as a speaker if it's a fixed line-out */51465146+ if (!strcmp(name, "Line-Out") && attr == INPUT_PIN_ATTR_INT)51475147+ name = "Speaker";51485148+ /* check the location */51495149+ switch (attr) {51505150+ case INPUT_PIN_ATTR_DOCK:51515151+ pfx = "Dock ";51525152+ break;51535153+ case INPUT_PIN_ATTR_FRONT:51545154+ pfx = "Front ";51555155+ break;51565156+ }51575157+ if (cfg) {51585158+ /* try to give a unique suffix if needed */51595159+ sfx = check_output_sfx(nid, cfg->line_out_pins, cfg->line_outs,51605160+ indexp);51615161+ if (!sfx)51625162+ sfx = check_output_sfx(nid, cfg->speaker_pins, cfg->speaker_outs,51635163+ indexp);51645164+ if (!sfx) {51655165+ /* don't add channel suffix for Headphone controls */51665166+ int idx = find_idx_in_nid_list(nid, cfg->hp_pins,51675167+ cfg->hp_outs);51685168+ if (idx >= 0)51695169+ *indexp = idx;51705170+ sfx = "";51715171+ }51725172+ }51735173+ snprintf(label, maxlen, "%s%s%s", pfx, name, sfx);51745174+ return 1;51755175+}51765176+51775177+/**51785178+ * snd_hda_get_pin_label - Get a label for the given I/O pin51795179+ *51805180+ * Get a label for the given pin. This function works for both input and51815181+ * output pins. When @cfg is given as non-NULL, the function tries to get51825182+ * an optimized label using hda_get_autocfg_input_label().51835183+ *51845184+ * This function tries to give a unique label string for the pin as much as51855185+ * possible. For example, when the multiple line-outs are present, it adds51865186+ * the channel suffix like "Front", "Surround", etc (only when @cfg is given).51875187+ * If no unique name with a suffix is available and @indexp is non-NULL, the51885188+ * index number is stored in the pointer.51895189+ */51905190+int snd_hda_get_pin_label(struct hda_codec *codec, hda_nid_t nid,51915191+ const struct auto_pin_cfg *cfg,51925192+ char *label, int maxlen, int *indexp)51935193+{51945194+ unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid);51955195+ const char *name = NULL;51965196+ int i;51975197+51985198+ if (indexp)51995199+ *indexp = 0;52005200+ if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)52015201+ return 0;52025202+52035203+ switch (get_defcfg_device(def_conf)) {52045204+ case AC_JACK_LINE_OUT:52055205+ return fill_audio_out_name(codec, nid, cfg, "Line-Out",52065206+ label, maxlen, indexp);52075207+ case AC_JACK_SPEAKER:52085208+ return fill_audio_out_name(codec, nid, cfg, "Speaker",52095209+ label, maxlen, indexp);52105210+ case AC_JACK_HP_OUT:52115211+ return fill_audio_out_name(codec, nid, cfg, "Headphone",52125212+ label, maxlen, indexp);52135213+ case AC_JACK_SPDIF_OUT:52145214+ case AC_JACK_DIG_OTHER_OUT:52155215+ if (get_defcfg_location(def_conf) == AC_JACK_LOC_HDMI)52165216+ name = "HDMI";52175217+ else52185218+ name = "SPDIF";52195219+ if (cfg && indexp) {52205220+ i = find_idx_in_nid_list(nid, cfg->dig_out_pins,52215221+ cfg->dig_outs);52225222+ if (i >= 0)52235223+ *indexp = i;52245224+ }52255225+ break;52265226+ default:52275227+ if (cfg) {52285228+ for (i = 0; i < cfg->num_inputs; i++) {52295229+ if (cfg->inputs[i].pin != nid)52305230+ continue;52315231+ name = hda_get_autocfg_input_label(codec, cfg, i);52325232+ if (name)52335233+ break;52345234+ }52355235+ }52365236+ if (!name)52375237+ name = hda_get_input_pin_label(codec, nid, true);52385238+ break;52395239+ }52405240+ if (!name)52415241+ return 0;52425242+ strlcpy(label, name, maxlen);52435243+ return 1;52445244+}52455245+EXPORT_SYMBOL_HDA(snd_hda_get_pin_label);5074524650755247/**50765248 * snd_hda_add_imux_item - Add an item to input_mux···53655251 buf[j] = '\0'; /* necessary when j == 0 */53665252}53675253EXPORT_SYMBOL_HDA(snd_print_pcm_bits);53685368-53695369-#ifdef CONFIG_SND_HDA_INPUT_JACK53705370-/*53715371- * Input-jack notification support53725372- */53735373-struct hda_jack_item {53745374- hda_nid_t nid;53755375- int type;53765376- struct snd_jack *jack;53775377-};53785378-53795379-static const char *get_jack_default_name(struct hda_codec *codec, hda_nid_t nid,53805380- int type)53815381-{53825382- switch (type) {53835383- case SND_JACK_HEADPHONE:53845384- return "Headphone";53855385- case SND_JACK_MICROPHONE:53865386- return "Mic";53875387- case SND_JACK_LINEOUT:53885388- return "Line-out";53895389- case SND_JACK_LINEIN:53905390- return "Line-in";53915391- case SND_JACK_HEADSET:53925392- return "Headset";53935393- case SND_JACK_VIDEOOUT:53945394- return "HDMI/DP";53955395- default:53965396- return "Misc";53975397- }53985398-}53995399-54005400-static void hda_free_jack_priv(struct snd_jack *jack)54015401-{54025402- struct hda_jack_item *jacks = jack->private_data;54035403- jacks->nid = 0;54045404- jacks->jack = NULL;54055405-}54065406-54075407-int snd_hda_input_jack_add(struct hda_codec *codec, hda_nid_t nid, int type,54085408- const char *name)54095409-{54105410- struct hda_jack_item *jack;54115411- int err;54125412-54135413- snd_array_init(&codec->jacks, sizeof(*jack), 32);54145414- jack = snd_array_new(&codec->jacks);54155415- if (!jack)54165416- return -ENOMEM;54175417-54185418- jack->nid = nid;54195419- jack->type = type;54205420- if (!name)54215421- name = get_jack_default_name(codec, nid, type);54225422- err = snd_jack_new(codec->bus->card, name, type, &jack->jack);54235423- if (err < 0) {54245424- jack->nid = 0;54255425- return err;54265426- }54275427- jack->jack->private_data = jack;54285428- jack->jack->private_free = hda_free_jack_priv;54295429- return 0;54305430-}54315431-EXPORT_SYMBOL_HDA(snd_hda_input_jack_add);54325432-54335433-void snd_hda_input_jack_report(struct hda_codec *codec, hda_nid_t nid)54345434-{54355435- struct hda_jack_item *jacks = codec->jacks.list;54365436- int i;54375437-54385438- if (!jacks)54395439- return;54405440-54415441- for (i = 0; i < codec->jacks.used; i++, jacks++) {54425442- unsigned int pin_ctl;54435443- unsigned int present;54445444- int type;54455445-54465446- if (jacks->nid != nid)54475447- continue;54485448- present = snd_hda_jack_detect(codec, nid);54495449- type = jacks->type;54505450- if (type == (SND_JACK_HEADPHONE | SND_JACK_LINEOUT)) {54515451- pin_ctl = snd_hda_codec_read(codec, nid, 0,54525452- AC_VERB_GET_PIN_WIDGET_CONTROL, 0);54535453- type = (pin_ctl & AC_PINCTL_HP_EN) ?54545454- SND_JACK_HEADPHONE : SND_JACK_LINEOUT;54555455- }54565456- snd_jack_report(jacks->jack, present ? type : 0);54575457- }54585458-}54595459-EXPORT_SYMBOL_HDA(snd_hda_input_jack_report);54605460-54615461-/* free jack instances manually when clearing/reconfiguring */54625462-void snd_hda_input_jack_free(struct hda_codec *codec)54635463-{54645464- if (!codec->bus->shutdown && codec->jacks.list) {54655465- struct hda_jack_item *jacks = codec->jacks.list;54665466- int i;54675467- for (i = 0; i < codec->jacks.used; i++, jacks++) {54685468- if (jacks->jack)54695469- snd_device_free(codec->bus->card, jacks->jack);54705470- }54715471- }54725472- snd_array_free(&codec->jacks);54735473-}54745474-EXPORT_SYMBOL_HDA(snd_hda_input_jack_free);54755475-#endif /* CONFIG_SND_HDA_INPUT_JACK */5476525454775255MODULE_DESCRIPTION("HDA codec core");54785256MODULE_LICENSE("GPL");
+3-3
sound/pci/hda/hda_codec.h
···547547/* max. codec address */548548#define HDA_MAX_CODEC_ADDRESS 0x0f549549550550-/* max number of PCM devics per card */551551-#define HDA_MAX_PCMS 10552552-553550/*554551 * generic arrays555552 */···865868 /* codec-specific additional proc output */866869 void (*proc_widget_hook)(struct snd_info_buffer *buffer,867870 struct hda_codec *codec, hda_nid_t nid);871871+872872+ /* jack detection */873873+ struct snd_array jacktbl;868874869875#ifdef CONFIG_SND_HDA_INPUT_JACK870876 /* jack detection */
+70-36
sound/pci/hda/hda_intel.c
···407407 u32 res[AZX_MAX_CODECS]; /* last read value */408408};409409410410+struct azx_pcm {411411+ struct azx *chip;412412+ struct snd_pcm *pcm;413413+ struct hda_codec *codec;414414+ struct hda_pcm_stream *hinfo[2];415415+ struct list_head list;416416+};417417+410418struct azx {411419 struct snd_card *card;412420 struct pci_dev *pci;···442434 struct azx_dev *azx_dev;443435444436 /* PCM */445445- struct snd_pcm *pcm[HDA_MAX_PCMS];437437+ struct list_head pcm_list; /* azx_pcm list */446438447439 /* HD codec */448440 unsigned short codec_mask;···487479 AZX_DRIVER_SCH,488480 AZX_DRIVER_ATI,489481 AZX_DRIVER_ATIHDMI,482482+ AZX_DRIVER_ATIHDMI_NS,490483 AZX_DRIVER_VIA,491484 AZX_DRIVER_SIS,492485 AZX_DRIVER_ULI,···534525 [AZX_DRIVER_SCH] = "HDA Intel MID",535526 [AZX_DRIVER_ATI] = "HDA ATI SB",536527 [AZX_DRIVER_ATIHDMI] = "HDA ATI HDMI",528528+ [AZX_DRIVER_ATIHDMI_NS] = "HDA ATI HDMI",537529 [AZX_DRIVER_VIA] = "HDA VIA VT82xx",538530 [AZX_DRIVER_SIS] = "HDA SIS966",539531 [AZX_DRIVER_ULI] = "HDA ULI M5461",···1153114311541144static void azx_init_pci(struct azx *chip)11551145{11561156- /* force to non-snoop mode for a new VIA controller when BIOS is set */11571157- if (chip->snoop && chip->driver_type == AZX_DRIVER_VIA) {11581158- u8 snoop;11591159- pci_read_config_byte(chip->pci, 0x42, &snoop);11601160- if (!(snoop & 0x80) && chip->pci->revision == 0x30) {11611161- chip->snoop = 0;11621162- snd_printdd(SFX "Force to non-snoop mode\n");11631163- }11641164- }11651165-11661146 /* Clear bits 0-2 of PCI register TCSEL (at offset 0x44)11671147 * TCSEL == Traffic Class Select Register, which sets PCI express QOS11681148 * Ensuring these bits are 0 clears playback static on some HD Audio···14861486 azx_init_chip(chip, 1);14871487#ifdef CONFIG_PM14881488 if (chip->initialized) {14891489- int i;14901490-14911491- for (i = 0; i < HDA_MAX_PCMS; i++)14921492- snd_pcm_suspend_all(chip->pcm[i]);14891489+ struct azx_pcm *p;14901490+ list_for_each_entry(p, &chip->pcm_list, list)14911491+ snd_pcm_suspend_all(p->pcm);14931492 snd_hda_suspend(chip->bus);14941493 snd_hda_resume(chip->bus);14951494 }···16641665 .periods_min = 2,16651666 .periods_max = AZX_MAX_FRAG,16661667 .fifo_size = 0,16671667-};16681668-16691669-struct azx_pcm {16701670- struct azx *chip;16711671- struct hda_codec *codec;16721672- struct hda_pcm_stream *hinfo[2];16731668};1674166916751670static int azx_pcm_open(struct snd_pcm_substream *substream)···21902197{21912198 struct azx_pcm *apcm = pcm->private_data;21922199 if (apcm) {21932193- apcm->chip->pcm[pcm->device] = NULL;22002200+ list_del(&apcm->list);21942201 kfree(apcm);21952202 }21962203}···22082215 unsigned int size;22092216 int s, err;2210221722112211- if (pcm_dev >= HDA_MAX_PCMS) {22122212- snd_printk(KERN_ERR SFX "Invalid PCM device number %d\n",22132213- pcm_dev);22142214- return -EINVAL;22152215- }22162216- if (chip->pcm[pcm_dev]) {22172217- snd_printk(KERN_ERR SFX "PCM %d already exists\n", pcm_dev);22182218- return -EBUSY;22182218+ list_for_each_entry(apcm, &chip->pcm_list, list) {22192219+ if (apcm->pcm->device == pcm_dev) {22202220+ snd_printk(KERN_ERR SFX "PCM %d already exists\n", pcm_dev);22212221+ return -EBUSY;22222222+ }22192223 }22202224 err = snd_pcm_new(chip->card, cpcm->name, pcm_dev,22212225 cpcm->stream[SNDRV_PCM_STREAM_PLAYBACK].substreams,···22252235 if (apcm == NULL)22262236 return -ENOMEM;22272237 apcm->chip = chip;22382238+ apcm->pcm = pcm;22282239 apcm->codec = codec;22292240 pcm->private_data = apcm;22302241 pcm->private_free = azx_pcm_free;22312242 if (cpcm->pcm_type == HDA_PCM_TYPE_MODEM)22322243 pcm->dev_class = SNDRV_PCM_CLASS_MODEM;22332233- chip->pcm[pcm_dev] = pcm;22442244+ list_add_tail(&apcm->list, &chip->pcm_list);22342245 cpcm->pcm = pcm;22352246 for (s = 0; s < 2; s++) {22362247 apcm->hinfo[s] = &cpcm->stream[s];···23612370{23622371 struct snd_card *card = pci_get_drvdata(pci);23632372 struct azx *chip = card->private_data;23642364- int i;23732373+ struct azx_pcm *p;2365237423662375 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);23672376 azx_clear_irq_pending(chip);23682368- for (i = 0; i < HDA_MAX_PCMS; i++)23692369- snd_pcm_suspend_all(chip->pcm[i]);23772377+ list_for_each_entry(p, &chip->pcm_list, list)23782378+ snd_pcm_suspend_all(p->pcm);23702379 if (chip->initialized)23712380 snd_hda_suspend(chip->bus);23722381 azx_stop_chip(chip);···24932502static struct snd_pci_quirk position_fix_list[] __devinitdata = {24942503 SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB),24952504 SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB),24962496- SND_PCI_QUIRK(0x1028, 0x02c6, "Dell Inspiron 1010", POS_FIX_LPIB),24972505 SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB),24982506 SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB),24992507 SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS", POS_FIX_LPIB),···26232633 }26242634}2625263526362636+/* check the snoop mode availability */26372637+static void __devinit azx_check_snoop_available(struct azx *chip)26382638+{26392639+ bool snoop = chip->snoop;26402640+26412641+ switch (chip->driver_type) {26422642+ case AZX_DRIVER_VIA:26432643+ /* force to non-snoop mode for a new VIA controller26442644+ * when BIOS is set26452645+ */26462646+ if (snoop) {26472647+ u8 val;26482648+ pci_read_config_byte(chip->pci, 0x42, &val);26492649+ if (!(val & 0x80) && chip->pci->revision == 0x30)26502650+ snoop = false;26512651+ }26522652+ break;26532653+ case AZX_DRIVER_ATIHDMI_NS:26542654+ /* new ATI HDMI requires non-snoop */26552655+ snoop = false;26562656+ break;26572657+ }26582658+26592659+ if (snoop != chip->snoop) {26602660+ snd_printk(KERN_INFO SFX "Force to %s mode\n",26612661+ snoop ? "snoop" : "non-snoop");26622662+ chip->snoop = snoop;26632663+ }26642664+}2626266526272666/*26282667 * constructor···26902671 check_msi(chip);26912672 chip->dev_index = dev;26922673 INIT_WORK(&chip->irq_pending_work, azx_irq_pending_work);26742674+ INIT_LIST_HEAD(&chip->pcm_list);2693267526942676 chip->position_fix[0] = chip->position_fix[1] =26952677 check_position_fix(chip, position_fix[dev]);···2698267826992679 chip->single_cmd = single_cmd;27002680 chip->snoop = hda_snoop;26812681+ azx_check_snoop_available(chip);2701268227022683 if (bdl_pos_adj[dev] < 0) {27032684 switch (chip->driver_type) {···27972776 chip->capture_streams = ULI_NUM_CAPTURE;27982777 break;27992778 case AZX_DRIVER_ATIHDMI:27792779+ case AZX_DRIVER_ATIHDMI_NS:28002780 chip->playback_streams = ATIHDMI_NUM_PLAYBACK;28012781 chip->capture_streams = ATIHDMI_NUM_CAPTURE;28022782 break;···29922970 /* SCH */29932971 { PCI_DEVICE(0x8086, 0x811b),29942972 .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP |29952995- AZX_DCAPS_BUFSIZE},29732973+ AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_LPIB }, /* Poulsbo */29742974+ { PCI_DEVICE(0x8086, 0x080a),29752975+ .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP |29762976+ AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_LPIB }, /* Oaktrail */29772977+ /* ICH */29962978 { PCI_DEVICE(0x8086, 0x2668),29972979 .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC |29982980 AZX_DCAPS_BUFSIZE }, /* ICH6 */···30633037 .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },30643038 { PCI_DEVICE(0x1002, 0xaa48),30653039 .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },30403040+ { PCI_DEVICE(0x1002, 0x9902),30413041+ .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI },30423042+ { PCI_DEVICE(0x1002, 0xaaa0),30433043+ .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI },30443044+ { PCI_DEVICE(0x1002, 0xaaa8),30453045+ .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI },30463046+ { PCI_DEVICE(0x1002, 0xaab0),30473047+ .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI },30663048 /* VIA VT8251/VT8237A */30673049 { PCI_DEVICE(0x1106, 0x3288),30683050 .driver_data = AZX_DRIVER_VIA | AZX_DCAPS_POSFIX_VIA },
+353
sound/pci/hda/hda_jack.c
···11+/*22+ * Jack-detection handling for HD-audio33+ *44+ * Copyright (c) 2011 Takashi Iwai <tiwai@suse.de>55+ *66+ * This driver is free software; you can redistribute it and/or modify77+ * it under the terms of the GNU General Public License as published by88+ * the Free Software Foundation; either version 2 of the License, or99+ * (at your option) any later version.1010+ */1111+1212+#include <linux/init.h>1313+#include <linux/slab.h>1414+#include <linux/export.h>1515+#include <sound/core.h>1616+#include <sound/control.h>1717+#include <sound/jack.h>1818+#include "hda_codec.h"1919+#include "hda_local.h"2020+#include "hda_jack.h"2121+2222+/* execute pin sense measurement */2323+static u32 read_pin_sense(struct hda_codec *codec, hda_nid_t nid)2424+{2525+ u32 pincap;2626+2727+ if (!codec->no_trigger_sense) {2828+ pincap = snd_hda_query_pin_caps(codec, nid);2929+ if (pincap & AC_PINCAP_TRIG_REQ) /* need trigger? */3030+ snd_hda_codec_read(codec, nid, 0,3131+ AC_VERB_SET_PIN_SENSE, 0);3232+ }3333+ return snd_hda_codec_read(codec, nid, 0,3434+ AC_VERB_GET_PIN_SENSE, 0);3535+}3636+3737+/**3838+ * snd_hda_jack_tbl_get - query the jack-table entry for the given NID3939+ */4040+struct hda_jack_tbl *4141+snd_hda_jack_tbl_get(struct hda_codec *codec, hda_nid_t nid)4242+{4343+ struct hda_jack_tbl *jack = codec->jacktbl.list;4444+ int i;4545+4646+ if (!nid || !jack)4747+ return NULL;4848+ for (i = 0; i < codec->jacktbl.used; i++, jack++)4949+ if (jack->nid == nid)5050+ return jack;5151+ return NULL;5252+}5353+EXPORT_SYMBOL_HDA(snd_hda_jack_tbl_get);5454+5555+/**5656+ * snd_hda_jack_tbl_get_from_tag - query the jack-table entry for the given tag5757+ */5858+struct hda_jack_tbl *5959+snd_hda_jack_tbl_get_from_tag(struct hda_codec *codec, unsigned char tag)6060+{6161+ struct hda_jack_tbl *jack = codec->jacktbl.list;6262+ int i;6363+6464+ if (!tag || !jack)6565+ return NULL;6666+ for (i = 0; i < codec->jacktbl.used; i++, jack++)6767+ if (jack->tag == tag)6868+ return jack;6969+ return NULL;7070+}7171+EXPORT_SYMBOL_HDA(snd_hda_jack_tbl_get_from_tag);7272+7373+/**7474+ * snd_hda_jack_tbl_new - create a jack-table entry for the given NID7575+ */7676+struct hda_jack_tbl *7777+snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid)7878+{7979+ struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, nid);8080+ if (jack)8181+ return jack;8282+ snd_array_init(&codec->jacktbl, sizeof(*jack), 16);8383+ jack = snd_array_new(&codec->jacktbl);8484+ if (!jack)8585+ return NULL;8686+ jack->nid = nid;8787+ jack->jack_dirty = 1;8888+ jack->tag = codec->jacktbl.used;8989+ return jack;9090+}9191+EXPORT_SYMBOL_HDA(snd_hda_jack_tbl_new);9292+9393+void snd_hda_jack_tbl_clear(struct hda_codec *codec)9494+{9595+#ifdef CONFIG_SND_HDA_INPUT_JACK9696+ /* free jack instances manually when clearing/reconfiguring */9797+ if (!codec->bus->shutdown && codec->jacktbl.list) {9898+ struct hda_jack_tbl *jack = codec->jacktbl.list;9999+ int i;100100+ for (i = 0; i < codec->jacktbl.used; i++, jack++) {101101+ if (jack->jack)102102+ snd_device_free(codec->bus->card, jack->jack);103103+ }104104+ }105105+#endif106106+ snd_array_free(&codec->jacktbl);107107+}108108+109109+/* update the cached value and notification flag if needed */110110+static void jack_detect_update(struct hda_codec *codec,111111+ struct hda_jack_tbl *jack)112112+{113113+ if (jack->jack_dirty || !jack->jack_detect) {114114+ jack->pin_sense = read_pin_sense(codec, jack->nid);115115+ jack->jack_dirty = 0;116116+ }117117+}118118+119119+/**120120+ * snd_hda_set_dirty_all - Mark all the cached as dirty121121+ *122122+ * This function sets the dirty flag to all entries of jack table.123123+ * It's called from the resume path in hda_codec.c.124124+ */125125+void snd_hda_jack_set_dirty_all(struct hda_codec *codec)126126+{127127+ struct hda_jack_tbl *jack = codec->jacktbl.list;128128+ int i;129129+130130+ for (i = 0; i < codec->jacktbl.used; i++, jack++)131131+ if (jack->nid)132132+ jack->jack_dirty = 1;133133+}134134+EXPORT_SYMBOL_HDA(snd_hda_jack_set_dirty_all);135135+136136+/**137137+ * snd_hda_pin_sense - execute pin sense measurement138138+ * @codec: the CODEC to sense139139+ * @nid: the pin NID to sense140140+ *141141+ * Execute necessary pin sense measurement and return its Presence Detect,142142+ * Impedance, ELD Valid etc. status bits.143143+ */144144+u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid)145145+{146146+ struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, nid);147147+ if (jack) {148148+ jack_detect_update(codec, jack);149149+ return jack->pin_sense;150150+ }151151+ return read_pin_sense(codec, nid);152152+}153153+EXPORT_SYMBOL_HDA(snd_hda_pin_sense);154154+155155+#define get_jack_plug_state(sense) !!(sense & AC_PINSENSE_PRESENCE)156156+157157+/**158158+ * snd_hda_jack_detect - query pin Presence Detect status159159+ * @codec: the CODEC to sense160160+ * @nid: the pin NID to sense161161+ *162162+ * Query and return the pin's Presence Detect status.163163+ */164164+int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid)165165+{166166+ u32 sense = snd_hda_pin_sense(codec, nid);167167+ return get_jack_plug_state(sense);168168+}169169+EXPORT_SYMBOL_HDA(snd_hda_jack_detect);170170+171171+/**172172+ * snd_hda_jack_detect_enable - enable the jack-detection173173+ */174174+int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid,175175+ unsigned char action)176176+{177177+ struct hda_jack_tbl *jack = snd_hda_jack_tbl_new(codec, nid);178178+ if (!jack)179179+ return -ENOMEM;180180+ if (jack->jack_detect)181181+ return 0; /* already registered */182182+ jack->jack_detect = 1;183183+ if (action)184184+ jack->action = action;185185+ return snd_hda_codec_write_cache(codec, nid, 0,186186+ AC_VERB_SET_UNSOLICITED_ENABLE,187187+ AC_USRSP_EN | jack->tag);188188+}189189+EXPORT_SYMBOL_HDA(snd_hda_jack_detect_enable);190190+191191+/**192192+ * snd_hda_jack_report_sync - sync the states of all jacks and report if changed193193+ */194194+void snd_hda_jack_report_sync(struct hda_codec *codec)195195+{196196+ struct hda_jack_tbl *jack = codec->jacktbl.list;197197+ int i, state;198198+199199+ for (i = 0; i < codec->jacktbl.used; i++, jack++)200200+ if (jack->nid) {201201+ jack_detect_update(codec, jack);202202+ if (!jack->kctl)203203+ continue;204204+ state = get_jack_plug_state(jack->pin_sense);205205+ snd_kctl_jack_report(codec->bus->card, jack->kctl, state);206206+#ifdef CONFIG_SND_HDA_INPUT_JACK207207+ if (jack->jack)208208+ snd_jack_report(jack->jack,209209+ state ? jack->type : 0);210210+#endif211211+ }212212+}213213+EXPORT_SYMBOL_HDA(snd_hda_jack_report_sync);214214+215215+#ifdef CONFIG_SND_HDA_INPUT_JACK216216+/* guess the jack type from the pin-config */217217+static int get_input_jack_type(struct hda_codec *codec, hda_nid_t nid)218218+{219219+ unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid);220220+ switch (get_defcfg_device(def_conf)) {221221+ case AC_JACK_LINE_OUT:222222+ case AC_JACK_SPEAKER:223223+ return SND_JACK_LINEOUT;224224+ case AC_JACK_HP_OUT:225225+ return SND_JACK_HEADPHONE;226226+ case AC_JACK_SPDIF_OUT:227227+ case AC_JACK_DIG_OTHER_OUT:228228+ return SND_JACK_AVOUT;229229+ case AC_JACK_MIC_IN:230230+ return SND_JACK_MICROPHONE;231231+ default:232232+ return SND_JACK_LINEIN;233233+ }234234+}235235+236236+static void hda_free_jack_priv(struct snd_jack *jack)237237+{238238+ struct hda_jack_tbl *jacks = jack->private_data;239239+ jacks->nid = 0;240240+ jacks->jack = NULL;241241+}242242+#endif243243+244244+/**245245+ * snd_hda_jack_add_kctl - Add a kctl for the given pin246246+ *247247+ * This assigns a jack-detection kctl to the given pin. The kcontrol248248+ * will have the given name and index.249249+ */250250+int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid,251251+ const char *name, int idx)252252+{253253+ struct hda_jack_tbl *jack;254254+ struct snd_kcontrol *kctl;255255+ int err, state;256256+257257+ jack = snd_hda_jack_tbl_new(codec, nid);258258+ if (!jack)259259+ return 0;260260+ if (jack->kctl)261261+ return 0; /* already created */262262+ kctl = snd_kctl_jack_new(name, idx, codec);263263+ if (!kctl)264264+ return -ENOMEM;265265+ err = snd_hda_ctl_add(codec, nid, kctl);266266+ if (err < 0)267267+ return err;268268+ jack->kctl = kctl;269269+ state = snd_hda_jack_detect(codec, nid);270270+ snd_kctl_jack_report(codec->bus->card, kctl, state);271271+#ifdef CONFIG_SND_HDA_INPUT_JACK272272+ jack->type = get_input_jack_type(codec, nid);273273+ err = snd_jack_new(codec->bus->card, name, jack->type, &jack->jack);274274+ if (err < 0)275275+ return err;276276+ jack->jack->private_data = jack;277277+ jack->jack->private_free = hda_free_jack_priv;278278+ snd_jack_report(jack->jack, state ? jack->type : 0);279279+#endif280280+ return 0;281281+}282282+EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctl);283283+284284+static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid,285285+ const struct auto_pin_cfg *cfg)286286+{287287+ unsigned int def_conf, conn;288288+ char name[44];289289+ int idx, err;290290+291291+ if (!nid)292292+ return 0;293293+ if (!is_jack_detectable(codec, nid))294294+ return 0;295295+ def_conf = snd_hda_codec_get_pincfg(codec, nid);296296+ conn = get_defcfg_connect(def_conf);297297+ if (conn != AC_JACK_PORT_COMPLEX)298298+ return 0;299299+300300+ snd_hda_get_pin_label(codec, nid, cfg, name, sizeof(name), &idx);301301+ err = snd_hda_jack_add_kctl(codec, nid, name, idx);302302+ if (err < 0)303303+ return err;304304+ return snd_hda_jack_detect_enable(codec, nid, 0);305305+}306306+307307+/**308308+ * snd_hda_jack_add_kctls - Add kctls for all pins included in the given pincfg309309+ */310310+int snd_hda_jack_add_kctls(struct hda_codec *codec,311311+ const struct auto_pin_cfg *cfg)312312+{313313+ const hda_nid_t *p;314314+ int i, err;315315+316316+ for (i = 0, p = cfg->line_out_pins; i < cfg->line_outs; i++, p++) {317317+ err = add_jack_kctl(codec, *p, cfg);318318+ if (err < 0)319319+ return err;320320+ }321321+ for (i = 0, p = cfg->hp_pins; i < cfg->hp_outs; i++, p++) {322322+ if (*p == *cfg->line_out_pins) /* might be duplicated */323323+ break;324324+ err = add_jack_kctl(codec, *p, cfg);325325+ if (err < 0)326326+ return err;327327+ }328328+ for (i = 0, p = cfg->speaker_pins; i < cfg->speaker_outs; i++, p++) {329329+ if (*p == *cfg->line_out_pins) /* might be duplicated */330330+ break;331331+ err = add_jack_kctl(codec, *p, cfg);332332+ if (err < 0)333333+ return err;334334+ }335335+ for (i = 0; i < cfg->num_inputs; i++) {336336+ err = add_jack_kctl(codec, cfg->inputs[i].pin, cfg);337337+ if (err < 0)338338+ return err;339339+ }340340+ for (i = 0, p = cfg->dig_out_pins; i < cfg->dig_outs; i++, p++) {341341+ err = add_jack_kctl(codec, *p, cfg);342342+ if (err < 0)343343+ return err;344344+ }345345+ err = add_jack_kctl(codec, cfg->dig_in_pin, cfg);346346+ if (err < 0)347347+ return err;348348+ err = add_jack_kctl(codec, cfg->mono_out_pin, cfg);349349+ if (err < 0)350350+ return err;351351+ return 0;352352+}353353+EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctls);
+86
sound/pci/hda/hda_jack.h
···11+/*22+ * Jack-detection handling for HD-audio33+ *44+ * Copyright (c) 2011 Takashi Iwai <tiwai@suse.de>55+ *66+ * This driver is free software; you can redistribute it and/or modify77+ * it under the terms of the GNU General Public License as published by88+ * the Free Software Foundation; either version 2 of the License, or99+ * (at your option) any later version.1010+ */1111+1212+#ifndef __SOUND_HDA_JACK_H1313+#define __SOUND_HDA_JACK_H1414+1515+struct hda_jack_tbl {1616+ hda_nid_t nid;1717+ unsigned char action; /* event action (0 = none) */1818+ unsigned char tag; /* unsol event tag */1919+ unsigned int private_data; /* arbitrary data */2020+ /* jack-detection stuff */2121+ unsigned int pin_sense; /* cached pin-sense value */2222+ unsigned int jack_detect:1; /* capable of jack-detection? */2323+ unsigned int jack_dirty:1; /* needs to update? */2424+ struct snd_kcontrol *kctl; /* assigned kctl for jack-detection */2525+#ifdef CONFIG_SND_HDA_INPUT_JACK2626+ int type;2727+ struct snd_jack *jack;2828+#endif2929+};3030+3131+struct hda_jack_tbl *3232+snd_hda_jack_tbl_get(struct hda_codec *codec, hda_nid_t nid);3333+struct hda_jack_tbl *3434+snd_hda_jack_tbl_get_from_tag(struct hda_codec *codec, unsigned char tag);3535+3636+struct hda_jack_tbl *3737+snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid);3838+void snd_hda_jack_tbl_clear(struct hda_codec *codec);3939+4040+/**4141+ * snd_hda_jack_get_action - get jack-tbl entry for the tag4242+ *4343+ * Call this from the unsol event handler to get the assigned action for the4444+ * event. This will mark the dirty flag for the later reporting, too.4545+ */4646+static inline unsigned char4747+snd_hda_jack_get_action(struct hda_codec *codec, unsigned int tag)4848+{4949+ struct hda_jack_tbl *jack = snd_hda_jack_tbl_get_from_tag(codec, tag);5050+ if (jack) {5151+ jack->jack_dirty = 1;5252+ return jack->action;5353+ }5454+ return 0;5555+}5656+5757+void snd_hda_jack_set_dirty_all(struct hda_codec *codec);5858+5959+int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid,6060+ unsigned char action);6161+6262+u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid);6363+int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid);6464+6565+static inline bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid)6666+{6767+ if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_PRES_DETECT))6868+ return false;6969+ if (!codec->ignore_misc_bit &&7070+ (get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid)) &7171+ AC_DEFCFG_MISC_NO_PRESENCE))7272+ return false;7373+ if (!(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP))7474+ return false;7575+ return true;7676+}7777+7878+int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid,7979+ const char *name, int idx);8080+int snd_hda_jack_add_kctls(struct hda_codec *codec,8181+ const struct auto_pin_cfg *cfg);8282+8383+void snd_hda_jack_report_sync(struct hda_codec *codec);8484+8585+8686+#endif /* __SOUND_HDA_JACK_H */
+9-42
sound/pci/hda/hda_local.h
···394394};395395396396struct auto_pin_cfg;397397-const char *hda_get_input_pin_label(struct hda_codec *codec, hda_nid_t pin,398398- int check_location);399397const char *hda_get_autocfg_input_label(struct hda_codec *codec,400398 const struct auto_pin_cfg *cfg,401399 int input);400400+int snd_hda_get_pin_label(struct hda_codec *codec, hda_nid_t nid,401401+ const struct auto_pin_cfg *cfg,402402+ char *label, int maxlen, int *indexp);402403int snd_hda_add_imux_item(struct hda_input_mux *imux, const char *label,403404 int index, int *type_index_ret);404405···488487}489488490489/* get the widget type from widget capability bits */491491-#define get_wcaps_type(wcaps) (((wcaps) & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT)490490+static inline int get_wcaps_type(unsigned int wcaps)491491+{492492+ if (!wcaps)493493+ return -1; /* invalid type */494494+ return (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;495495+}492496493497static inline unsigned int get_wcaps_channels(u32 wcaps)494498{···511505u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid);512506int snd_hda_override_pin_caps(struct hda_codec *codec, hda_nid_t nid,513507 unsigned int caps);514514-u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid);515515-int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid);516516-517517-static inline bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid)518518-{519519- if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_PRES_DETECT))520520- return false;521521- if (!codec->ignore_misc_bit &&522522- (get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid)) &523523- AC_DEFCFG_MISC_NO_PRESENCE))524524- return false;525525- if (!(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP))526526- return false;527527- return true;528528-}529508530509/* flags for hda_nid_item */531510#define HDA_NID_ITEM_AMP (1<<0)···678687679688#define SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE 80680689void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen);681681-682682-/*683683- * Input-jack notification support684684- */685685-#ifdef CONFIG_SND_HDA_INPUT_JACK686686-int snd_hda_input_jack_add(struct hda_codec *codec, hda_nid_t nid, int type,687687- const char *name);688688-void snd_hda_input_jack_report(struct hda_codec *codec, hda_nid_t nid);689689-void snd_hda_input_jack_free(struct hda_codec *codec);690690-#else /* CONFIG_SND_HDA_INPUT_JACK */691691-static inline int snd_hda_input_jack_add(struct hda_codec *codec,692692- hda_nid_t nid, int type,693693- const char *name)694694-{695695- return 0;696696-}697697-static inline void snd_hda_input_jack_report(struct hda_codec *codec,698698- hda_nid_t nid)699699-{700700-}701701-static inline void snd_hda_input_jack_free(struct hda_codec *codec)702702-{703703-}704704-#endif /* CONFIG_SND_HDA_INPUT_JACK */705690706691#endif /* __SOUND_HDA_LOCAL_H */
+2
sound/pci/hda/hda_proc.c
···5454 [AC_WID_BEEP] = "Beep Generator Widget",5555 [AC_WID_VENDOR] = "Vendor Defined Widget",5656 };5757+ if (wid_value == -1)5858+ return "UNKNOWN Widget";5759 wid_value &= 0xf;5860 if (names[wid_value])5961 return names[wid_value];