diff options
Diffstat (limited to 'sound/pci/hda/hda_codec.c')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 68 |
1 files changed, 38 insertions, 30 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 18bbc87e376f..8f34fb447983 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -52,6 +52,7 @@ struct hda_vendor_id { static struct hda_vendor_id hda_vendor_ids[] = { { 0x10ec, "Realtek" }, { 0x1057, "Motorola" }, + { 0x1106, "VIA" }, { 0x11d4, "Analog Devices" }, { 0x13f6, "C-Media" }, { 0x14f1, "Conexant" }, @@ -262,7 +263,7 @@ int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex) unsol->queue[wp] = res; unsol->queue[wp + 1] = res_ex; - queue_work(unsol->workq, &unsol->work); + schedule_work(&unsol->work); return 0; } @@ -309,12 +310,6 @@ static int init_unsol_queue(struct hda_bus *bus) snd_printk(KERN_ERR "hda_codec: can't allocate unsolicited queue\n"); return -ENOMEM; } - unsol->workq = create_singlethread_workqueue("hda_codec"); - if (! unsol->workq) { - snd_printk(KERN_ERR "hda_codec: can't create workqueue\n"); - kfree(unsol); - return -ENOMEM; - } INIT_WORK(&unsol->work, process_unsol_events); unsol->bus = bus; bus->unsol = unsol; @@ -333,7 +328,7 @@ static int snd_hda_bus_free(struct hda_bus *bus) if (! bus) return 0; if (bus->unsol) { - destroy_workqueue(bus->unsol->workq); + flush_scheduled_work(); kfree(bus->unsol); } list_for_each_safe(p, n, &bus->codec_list) { @@ -1714,6 +1709,8 @@ EXPORT_SYMBOL(snd_hda_build_pcms); /** * snd_hda_check_board_config - compare the current codec with the config table * @codec: the HDA codec + * @num_configs: number of config enums + * @models: array of model name strings * @tbl: configuration table, terminated by null entries * * Compares the modelname or PCI subsystem id of the current codec with the @@ -1722,33 +1719,44 @@ EXPORT_SYMBOL(snd_hda_build_pcms); * * If no entries are matching, the function returns a negative value. */ -int snd_hda_check_board_config(struct hda_codec *codec, const struct hda_board_config *tbl) -{ - const struct hda_board_config *c; - - if (codec->bus->modelname) { - for (c = tbl; c->modelname || c->pci_subvendor; c++) { - if (c->modelname && - ! strcmp(codec->bus->modelname, c->modelname)) { - snd_printd(KERN_INFO "hda_codec: model '%s' is selected\n", c->modelname); - return c->config; +int snd_hda_check_board_config(struct hda_codec *codec, + int num_configs, const char **models, + const struct snd_pci_quirk *tbl) +{ + if (codec->bus->modelname && models) { + int i; + for (i = 0; i < num_configs; i++) { + if (models[i] && + !strcmp(codec->bus->modelname, models[i])) { + snd_printd(KERN_INFO "hda_codec: model '%s' is " + "selected\n", models[i]); + return i; } } } - if (codec->bus->pci) { - u16 subsystem_vendor, subsystem_device; - pci_read_config_word(codec->bus->pci, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor); - pci_read_config_word(codec->bus->pci, PCI_SUBSYSTEM_ID, &subsystem_device); - for (c = tbl; c->modelname || c->pci_subvendor; c++) { - if (c->pci_subvendor == subsystem_vendor && - (! c->pci_subdevice /* all match */|| - (c->pci_subdevice == subsystem_device))) { - snd_printdd(KERN_INFO "hda_codec: PCI %x:%x, codec config %d is selected\n", - subsystem_vendor, subsystem_device, c->config); - return c->config; - } + if (!codec->bus->pci || !tbl) + return -1; + + tbl = snd_pci_quirk_lookup(codec->bus->pci, tbl); + if (!tbl) + return -1; + if (tbl->value >= 0 && tbl->value < num_configs) { +#ifdef CONFIG_SND_DEBUG_DETECT + char tmp[10]; + const char *model = NULL; + if (models) + model = models[tbl->value]; + if (!model) { + sprintf(tmp, "#%d", tbl->value); + model = tmp; } + snd_printdd(KERN_INFO "hda_codec: model '%s' is selected " + "for config %x:%x (%s)\n", + model, tbl->subvendor, tbl->subdevice, + (tbl->name ? tbl->name : "Unknown device")); +#endif + return tbl->value; } return -1; } |