aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/hda_codec.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/hda/hda_codec.c')
-rw-r--r--sound/pci/hda/hda_codec.c111
1 files changed, 92 insertions, 19 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index e16cf63821ae..b7bba7dc7cf1 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -373,7 +373,7 @@ int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex)
373 unsol->queue[wp] = res; 373 unsol->queue[wp] = res;
374 unsol->queue[wp + 1] = res_ex; 374 unsol->queue[wp + 1] = res_ex;
375 375
376 schedule_work(&unsol->work); 376 queue_work(bus->workq, &unsol->work);
377 377
378 return 0; 378 return 0;
379} 379}
@@ -437,15 +437,17 @@ static int snd_hda_bus_free(struct hda_bus *bus)
437 437
438 if (!bus) 438 if (!bus)
439 return 0; 439 return 0;
440 if (bus->unsol) { 440 if (bus->workq)
441 flush_scheduled_work(); 441 flush_workqueue(bus->workq);
442 if (bus->unsol)
442 kfree(bus->unsol); 443 kfree(bus->unsol);
443 }
444 list_for_each_entry_safe(codec, n, &bus->codec_list, list) { 444 list_for_each_entry_safe(codec, n, &bus->codec_list, list) {
445 snd_hda_codec_free(codec); 445 snd_hda_codec_free(codec);
446 } 446 }
447 if (bus->ops.private_free) 447 if (bus->ops.private_free)
448 bus->ops.private_free(bus); 448 bus->ops.private_free(bus);
449 if (bus->workq)
450 destroy_workqueue(bus->workq);
449 kfree(bus); 451 kfree(bus);
450 return 0; 452 return 0;
451} 453}
@@ -485,6 +487,7 @@ int /*__devinit*/ snd_hda_bus_new(struct snd_card *card,
485{ 487{
486 struct hda_bus *bus; 488 struct hda_bus *bus;
487 int err; 489 int err;
490 char qname[8];
488 static struct snd_device_ops dev_ops = { 491 static struct snd_device_ops dev_ops = {
489 .dev_register = snd_hda_bus_dev_register, 492 .dev_register = snd_hda_bus_dev_register,
490 .dev_free = snd_hda_bus_dev_free, 493 .dev_free = snd_hda_bus_dev_free,
@@ -514,6 +517,14 @@ int /*__devinit*/ snd_hda_bus_new(struct snd_card *card,
514 mutex_init(&bus->cmd_mutex); 517 mutex_init(&bus->cmd_mutex);
515 INIT_LIST_HEAD(&bus->codec_list); 518 INIT_LIST_HEAD(&bus->codec_list);
516 519
520 snprintf(qname, sizeof(qname), "hda%d", card->number);
521 bus->workq = create_workqueue(qname);
522 if (!bus->workq) {
523 snd_printk(KERN_ERR "cannot create workqueue %s\n", qname);
524 kfree(bus);
525 return -ENOMEM;
526 }
527
517 err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops); 528 err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops);
518 if (err < 0) { 529 if (err < 0) {
519 snd_hda_bus_free(bus); 530 snd_hda_bus_free(bus);
@@ -684,7 +695,7 @@ static void snd_hda_codec_free(struct hda_codec *codec)
684 return; 695 return;
685#ifdef CONFIG_SND_HDA_POWER_SAVE 696#ifdef CONFIG_SND_HDA_POWER_SAVE
686 cancel_delayed_work(&codec->power_work); 697 cancel_delayed_work(&codec->power_work);
687 flush_scheduled_work(); 698 flush_workqueue(codec->bus->workq);
688#endif 699#endif
689 list_del(&codec->list); 700 list_del(&codec->list);
690 snd_array_free(&codec->mixers); 701 snd_array_free(&codec->mixers);
@@ -735,6 +746,7 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr
735 codec->bus = bus; 746 codec->bus = bus;
736 codec->addr = codec_addr; 747 codec->addr = codec_addr;
737 mutex_init(&codec->spdif_mutex); 748 mutex_init(&codec->spdif_mutex);
749 mutex_init(&codec->control_mutex);
738 init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); 750 init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
739 init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); 751 init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
740 snd_array_init(&codec->mixers, sizeof(struct snd_kcontrol *), 32); 752 snd_array_init(&codec->mixers, sizeof(struct snd_kcontrol *), 32);
@@ -1272,7 +1284,7 @@ void snd_hda_codec_reset(struct hda_codec *codec)
1272 1284
1273#ifdef CONFIG_SND_HDA_POWER_SAVE 1285#ifdef CONFIG_SND_HDA_POWER_SAVE
1274 cancel_delayed_work(&codec->power_work); 1286 cancel_delayed_work(&codec->power_work);
1275 flush_scheduled_work(); 1287 flush_workqueue(codec->bus->workq);
1276#endif 1288#endif
1277 snd_hda_ctls_clear(codec); 1289 snd_hda_ctls_clear(codec);
1278 /* relase PCMs */ 1290 /* relase PCMs */
@@ -1418,12 +1430,12 @@ int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol,
1418 unsigned long pval; 1430 unsigned long pval;
1419 int err; 1431 int err;
1420 1432
1421 mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */ 1433 mutex_lock(&codec->control_mutex);
1422 pval = kcontrol->private_value; 1434 pval = kcontrol->private_value;
1423 kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */ 1435 kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */
1424 err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol); 1436 err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
1425 kcontrol->private_value = pval; 1437 kcontrol->private_value = pval;
1426 mutex_unlock(&codec->spdif_mutex); 1438 mutex_unlock(&codec->control_mutex);
1427 return err; 1439 return err;
1428} 1440}
1429EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_get); 1441EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_get);
@@ -1435,7 +1447,7 @@ int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
1435 unsigned long pval; 1447 unsigned long pval;
1436 int i, indices, err = 0, change = 0; 1448 int i, indices, err = 0, change = 0;
1437 1449
1438 mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */ 1450 mutex_lock(&codec->control_mutex);
1439 pval = kcontrol->private_value; 1451 pval = kcontrol->private_value;
1440 indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT; 1452 indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT;
1441 for (i = 0; i < indices; i++) { 1453 for (i = 0; i < indices; i++) {
@@ -1447,7 +1459,7 @@ int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
1447 change |= err; 1459 change |= err;
1448 } 1460 }
1449 kcontrol->private_value = pval; 1461 kcontrol->private_value = pval;
1450 mutex_unlock(&codec->spdif_mutex); 1462 mutex_unlock(&codec->control_mutex);
1451 return err < 0 ? err : change; 1463 return err < 0 ? err : change;
1452} 1464}
1453EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_put); 1465EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_put);
@@ -1462,12 +1474,12 @@ int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol,
1462 struct hda_bind_ctls *c; 1474 struct hda_bind_ctls *c;
1463 int err; 1475 int err;
1464 1476
1465 mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */ 1477 mutex_lock(&codec->control_mutex);
1466 c = (struct hda_bind_ctls *)kcontrol->private_value; 1478 c = (struct hda_bind_ctls *)kcontrol->private_value;
1467 kcontrol->private_value = *c->values; 1479 kcontrol->private_value = *c->values;
1468 err = c->ops->info(kcontrol, uinfo); 1480 err = c->ops->info(kcontrol, uinfo);
1469 kcontrol->private_value = (long)c; 1481 kcontrol->private_value = (long)c;
1470 mutex_unlock(&codec->spdif_mutex); 1482 mutex_unlock(&codec->control_mutex);
1471 return err; 1483 return err;
1472} 1484}
1473EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_info); 1485EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_info);
@@ -1479,12 +1491,12 @@ int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol,
1479 struct hda_bind_ctls *c; 1491 struct hda_bind_ctls *c;
1480 int err; 1492 int err;
1481 1493
1482 mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */ 1494 mutex_lock(&codec->control_mutex);
1483 c = (struct hda_bind_ctls *)kcontrol->private_value; 1495 c = (struct hda_bind_ctls *)kcontrol->private_value;
1484 kcontrol->private_value = *c->values; 1496 kcontrol->private_value = *c->values;
1485 err = c->ops->get(kcontrol, ucontrol); 1497 err = c->ops->get(kcontrol, ucontrol);
1486 kcontrol->private_value = (long)c; 1498 kcontrol->private_value = (long)c;
1487 mutex_unlock(&codec->spdif_mutex); 1499 mutex_unlock(&codec->control_mutex);
1488 return err; 1500 return err;
1489} 1501}
1490EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_get); 1502EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_get);
@@ -1497,7 +1509,7 @@ int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
1497 unsigned long *vals; 1509 unsigned long *vals;
1498 int err = 0, change = 0; 1510 int err = 0, change = 0;
1499 1511
1500 mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */ 1512 mutex_lock(&codec->control_mutex);
1501 c = (struct hda_bind_ctls *)kcontrol->private_value; 1513 c = (struct hda_bind_ctls *)kcontrol->private_value;
1502 for (vals = c->values; *vals; vals++) { 1514 for (vals = c->values; *vals; vals++) {
1503 kcontrol->private_value = *vals; 1515 kcontrol->private_value = *vals;
@@ -1507,7 +1519,7 @@ int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
1507 change |= err; 1519 change |= err;
1508 } 1520 }
1509 kcontrol->private_value = (long)c; 1521 kcontrol->private_value = (long)c;
1510 mutex_unlock(&codec->spdif_mutex); 1522 mutex_unlock(&codec->control_mutex);
1511 return err < 0 ? err : change; 1523 return err < 0 ? err : change;
1512} 1524}
1513EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_put); 1525EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_put);
@@ -1519,12 +1531,12 @@ int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1519 struct hda_bind_ctls *c; 1531 struct hda_bind_ctls *c;
1520 int err; 1532 int err;
1521 1533
1522 mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */ 1534 mutex_lock(&codec->control_mutex);
1523 c = (struct hda_bind_ctls *)kcontrol->private_value; 1535 c = (struct hda_bind_ctls *)kcontrol->private_value;
1524 kcontrol->private_value = *c->values; 1536 kcontrol->private_value = *c->values;
1525 err = c->ops->tlv(kcontrol, op_flag, size, tlv); 1537 err = c->ops->tlv(kcontrol, op_flag, size, tlv);
1526 kcontrol->private_value = (long)c; 1538 kcontrol->private_value = (long)c;
1527 mutex_unlock(&codec->spdif_mutex); 1539 mutex_unlock(&codec->control_mutex);
1528 return err; 1540 return err;
1529} 1541}
1530EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_tlv); 1542EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_tlv);
@@ -2712,6 +2724,67 @@ int snd_hda_check_board_config(struct hda_codec *codec,
2712EXPORT_SYMBOL_HDA(snd_hda_check_board_config); 2724EXPORT_SYMBOL_HDA(snd_hda_check_board_config);
2713 2725
2714/** 2726/**
2727 * snd_hda_check_board_codec_sid_config - compare the current codec
2728 subsystem ID with the
2729 config table
2730
2731 This is important for Gateway notebooks with SB450 HDA Audio
2732 where the vendor ID of the PCI device is:
2733 ATI Technologies Inc SB450 HDA Audio [1002:437b]
2734 and the vendor/subvendor are found only at the codec.
2735
2736 * @codec: the HDA codec
2737 * @num_configs: number of config enums
2738 * @models: array of model name strings
2739 * @tbl: configuration table, terminated by null entries
2740 *
2741 * Compares the modelname or PCI subsystem id of the current codec with the
2742 * given configuration table. If a matching entry is found, returns its
2743 * config value (supposed to be 0 or positive).
2744 *
2745 * If no entries are matching, the function returns a negative value.
2746 */
2747int snd_hda_check_board_codec_sid_config(struct hda_codec *codec,
2748 int num_configs, const char **models,
2749 const struct snd_pci_quirk *tbl)
2750{
2751 const struct snd_pci_quirk *q;
2752
2753 /* Search for codec ID */
2754 for (q = tbl; q->subvendor; q++) {
2755 unsigned long vendorid = (q->subdevice) | (q->subvendor << 16);
2756
2757 if (vendorid == codec->subsystem_id)
2758 break;
2759 }
2760
2761 if (!q->subvendor)
2762 return -1;
2763
2764 tbl = q;
2765
2766 if (tbl->value >= 0 && tbl->value < num_configs) {
2767#ifdef CONFIG_SND_DEBUG_DETECT
2768 char tmp[10];
2769 const char *model = NULL;
2770 if (models)
2771 model = models[tbl->value];
2772 if (!model) {
2773 sprintf(tmp, "#%d", tbl->value);
2774 model = tmp;
2775 }
2776 snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
2777 "for config %x:%x (%s)\n",
2778 model, tbl->subvendor, tbl->subdevice,
2779 (tbl->name ? tbl->name : "Unknown device"));
2780#endif
2781 return tbl->value;
2782 }
2783 return -1;
2784}
2785EXPORT_SYMBOL_HDA(snd_hda_check_board_codec_sid_config);
2786
2787/**
2715 * snd_hda_add_new_ctls - create controls from the array 2788 * snd_hda_add_new_ctls - create controls from the array
2716 * @codec: the HDA codec 2789 * @codec: the HDA codec
2717 * @knew: the array of struct snd_kcontrol_new 2790 * @knew: the array of struct snd_kcontrol_new
@@ -2803,7 +2876,7 @@ void snd_hda_power_down(struct hda_codec *codec)
2803 return; 2876 return;
2804 if (power_save(codec)) { 2877 if (power_save(codec)) {
2805 codec->power_transition = 1; /* avoid reentrance */ 2878 codec->power_transition = 1; /* avoid reentrance */
2806 schedule_delayed_work(&codec->power_work, 2879 queue_delayed_work(codec->bus->workq, &codec->power_work,
2807 msecs_to_jiffies(power_save(codec) * 1000)); 2880 msecs_to_jiffies(power_save(codec) * 1000));
2808 } 2881 }
2809} 2882}