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.c122
1 files changed, 103 insertions, 19 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index e16cf63821a..d03f99298be 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}
@@ -514,6 +516,16 @@ int /*__devinit*/ snd_hda_bus_new(struct snd_card *card,
514 mutex_init(&bus->cmd_mutex); 516 mutex_init(&bus->cmd_mutex);
515 INIT_LIST_HEAD(&bus->codec_list); 517 INIT_LIST_HEAD(&bus->codec_list);
516 518
519 snprintf(bus->workq_name, sizeof(bus->workq_name),
520 "hd-audio%d", card->number);
521 bus->workq = create_singlethread_workqueue(bus->workq_name);
522 if (!bus->workq) {
523 snd_printk(KERN_ERR "cannot create workqueue %s\n",
524 bus->workq_name);
525 kfree(bus);
526 return -ENOMEM;
527 }
528
517 err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops); 529 err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops);
518 if (err < 0) { 530 if (err < 0) {
519 snd_hda_bus_free(bus); 531 snd_hda_bus_free(bus);
@@ -684,7 +696,7 @@ static void snd_hda_codec_free(struct hda_codec *codec)
684 return; 696 return;
685#ifdef CONFIG_SND_HDA_POWER_SAVE 697#ifdef CONFIG_SND_HDA_POWER_SAVE
686 cancel_delayed_work(&codec->power_work); 698 cancel_delayed_work(&codec->power_work);
687 flush_scheduled_work(); 699 flush_workqueue(codec->bus->workq);
688#endif 700#endif
689 list_del(&codec->list); 701 list_del(&codec->list);
690 snd_array_free(&codec->mixers); 702 snd_array_free(&codec->mixers);
@@ -735,6 +747,7 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr
735 codec->bus = bus; 747 codec->bus = bus;
736 codec->addr = codec_addr; 748 codec->addr = codec_addr;
737 mutex_init(&codec->spdif_mutex); 749 mutex_init(&codec->spdif_mutex);
750 mutex_init(&codec->control_mutex);
738 init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info)); 751 init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
739 init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head)); 752 init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
740 snd_array_init(&codec->mixers, sizeof(struct snd_kcontrol *), 32); 753 snd_array_init(&codec->mixers, sizeof(struct snd_kcontrol *), 32);
@@ -1272,7 +1285,7 @@ void snd_hda_codec_reset(struct hda_codec *codec)
1272 1285
1273#ifdef CONFIG_SND_HDA_POWER_SAVE 1286#ifdef CONFIG_SND_HDA_POWER_SAVE
1274 cancel_delayed_work(&codec->power_work); 1287 cancel_delayed_work(&codec->power_work);
1275 flush_scheduled_work(); 1288 flush_workqueue(codec->bus->workq);
1276#endif 1289#endif
1277 snd_hda_ctls_clear(codec); 1290 snd_hda_ctls_clear(codec);
1278 /* relase PCMs */ 1291 /* relase PCMs */
@@ -1418,12 +1431,12 @@ int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol,
1418 unsigned long pval; 1431 unsigned long pval;
1419 int err; 1432 int err;
1420 1433
1421 mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */ 1434 mutex_lock(&codec->control_mutex);
1422 pval = kcontrol->private_value; 1435 pval = kcontrol->private_value;
1423 kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */ 1436 kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */
1424 err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol); 1437 err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
1425 kcontrol->private_value = pval; 1438 kcontrol->private_value = pval;
1426 mutex_unlock(&codec->spdif_mutex); 1439 mutex_unlock(&codec->control_mutex);
1427 return err; 1440 return err;
1428} 1441}
1429EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_get); 1442EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_get);
@@ -1435,7 +1448,7 @@ int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
1435 unsigned long pval; 1448 unsigned long pval;
1436 int i, indices, err = 0, change = 0; 1449 int i, indices, err = 0, change = 0;
1437 1450
1438 mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */ 1451 mutex_lock(&codec->control_mutex);
1439 pval = kcontrol->private_value; 1452 pval = kcontrol->private_value;
1440 indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT; 1453 indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT;
1441 for (i = 0; i < indices; i++) { 1454 for (i = 0; i < indices; i++) {
@@ -1447,7 +1460,7 @@ int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
1447 change |= err; 1460 change |= err;
1448 } 1461 }
1449 kcontrol->private_value = pval; 1462 kcontrol->private_value = pval;
1450 mutex_unlock(&codec->spdif_mutex); 1463 mutex_unlock(&codec->control_mutex);
1451 return err < 0 ? err : change; 1464 return err < 0 ? err : change;
1452} 1465}
1453EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_put); 1466EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_put);
@@ -1462,12 +1475,12 @@ int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol,
1462 struct hda_bind_ctls *c; 1475 struct hda_bind_ctls *c;
1463 int err; 1476 int err;
1464 1477
1465 mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */ 1478 mutex_lock(&codec->control_mutex);
1466 c = (struct hda_bind_ctls *)kcontrol->private_value; 1479 c = (struct hda_bind_ctls *)kcontrol->private_value;
1467 kcontrol->private_value = *c->values; 1480 kcontrol->private_value = *c->values;
1468 err = c->ops->info(kcontrol, uinfo); 1481 err = c->ops->info(kcontrol, uinfo);
1469 kcontrol->private_value = (long)c; 1482 kcontrol->private_value = (long)c;
1470 mutex_unlock(&codec->spdif_mutex); 1483 mutex_unlock(&codec->control_mutex);
1471 return err; 1484 return err;
1472} 1485}
1473EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_info); 1486EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_info);
@@ -1479,12 +1492,12 @@ int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol,
1479 struct hda_bind_ctls *c; 1492 struct hda_bind_ctls *c;
1480 int err; 1493 int err;
1481 1494
1482 mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */ 1495 mutex_lock(&codec->control_mutex);
1483 c = (struct hda_bind_ctls *)kcontrol->private_value; 1496 c = (struct hda_bind_ctls *)kcontrol->private_value;
1484 kcontrol->private_value = *c->values; 1497 kcontrol->private_value = *c->values;
1485 err = c->ops->get(kcontrol, ucontrol); 1498 err = c->ops->get(kcontrol, ucontrol);
1486 kcontrol->private_value = (long)c; 1499 kcontrol->private_value = (long)c;
1487 mutex_unlock(&codec->spdif_mutex); 1500 mutex_unlock(&codec->control_mutex);
1488 return err; 1501 return err;
1489} 1502}
1490EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_get); 1503EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_get);
@@ -1497,7 +1510,7 @@ int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
1497 unsigned long *vals; 1510 unsigned long *vals;
1498 int err = 0, change = 0; 1511 int err = 0, change = 0;
1499 1512
1500 mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */ 1513 mutex_lock(&codec->control_mutex);
1501 c = (struct hda_bind_ctls *)kcontrol->private_value; 1514 c = (struct hda_bind_ctls *)kcontrol->private_value;
1502 for (vals = c->values; *vals; vals++) { 1515 for (vals = c->values; *vals; vals++) {
1503 kcontrol->private_value = *vals; 1516 kcontrol->private_value = *vals;
@@ -1507,7 +1520,7 @@ int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
1507 change |= err; 1520 change |= err;
1508 } 1521 }
1509 kcontrol->private_value = (long)c; 1522 kcontrol->private_value = (long)c;
1510 mutex_unlock(&codec->spdif_mutex); 1523 mutex_unlock(&codec->control_mutex);
1511 return err < 0 ? err : change; 1524 return err < 0 ? err : change;
1512} 1525}
1513EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_put); 1526EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_put);
@@ -1519,12 +1532,12 @@ int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1519 struct hda_bind_ctls *c; 1532 struct hda_bind_ctls *c;
1520 int err; 1533 int err;
1521 1534
1522 mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */ 1535 mutex_lock(&codec->control_mutex);
1523 c = (struct hda_bind_ctls *)kcontrol->private_value; 1536 c = (struct hda_bind_ctls *)kcontrol->private_value;
1524 kcontrol->private_value = *c->values; 1537 kcontrol->private_value = *c->values;
1525 err = c->ops->tlv(kcontrol, op_flag, size, tlv); 1538 err = c->ops->tlv(kcontrol, op_flag, size, tlv);
1526 kcontrol->private_value = (long)c; 1539 kcontrol->private_value = (long)c;
1527 mutex_unlock(&codec->spdif_mutex); 1540 mutex_unlock(&codec->control_mutex);
1528 return err; 1541 return err;
1529} 1542}
1530EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_tlv); 1543EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_tlv);
@@ -2712,6 +2725,67 @@ int snd_hda_check_board_config(struct hda_codec *codec,
2712EXPORT_SYMBOL_HDA(snd_hda_check_board_config); 2725EXPORT_SYMBOL_HDA(snd_hda_check_board_config);
2713 2726
2714/** 2727/**
2728 * snd_hda_check_board_codec_sid_config - compare the current codec
2729 subsystem ID with the
2730 config table
2731
2732 This is important for Gateway notebooks with SB450 HDA Audio
2733 where the vendor ID of the PCI device is:
2734 ATI Technologies Inc SB450 HDA Audio [1002:437b]
2735 and the vendor/subvendor are found only at the codec.
2736
2737 * @codec: the HDA codec
2738 * @num_configs: number of config enums
2739 * @models: array of model name strings
2740 * @tbl: configuration table, terminated by null entries
2741 *
2742 * Compares the modelname or PCI subsystem id of the current codec with the
2743 * given configuration table. If a matching entry is found, returns its
2744 * config value (supposed to be 0 or positive).
2745 *
2746 * If no entries are matching, the function returns a negative value.
2747 */
2748int snd_hda_check_board_codec_sid_config(struct hda_codec *codec,
2749 int num_configs, const char **models,
2750 const struct snd_pci_quirk *tbl)
2751{
2752 const struct snd_pci_quirk *q;
2753
2754 /* Search for codec ID */
2755 for (q = tbl; q->subvendor; q++) {
2756 unsigned long vendorid = (q->subdevice) | (q->subvendor << 16);
2757
2758 if (vendorid == codec->subsystem_id)
2759 break;
2760 }
2761
2762 if (!q->subvendor)
2763 return -1;
2764
2765 tbl = q;
2766
2767 if (tbl->value >= 0 && tbl->value < num_configs) {
2768#ifdef CONFIG_SND_DEBUG_DETECT
2769 char tmp[10];
2770 const char *model = NULL;
2771 if (models)
2772 model = models[tbl->value];
2773 if (!model) {
2774 sprintf(tmp, "#%d", tbl->value);
2775 model = tmp;
2776 }
2777 snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
2778 "for config %x:%x (%s)\n",
2779 model, tbl->subvendor, tbl->subdevice,
2780 (tbl->name ? tbl->name : "Unknown device"));
2781#endif
2782 return tbl->value;
2783 }
2784 return -1;
2785}
2786EXPORT_SYMBOL_HDA(snd_hda_check_board_codec_sid_config);
2787
2788/**
2715 * snd_hda_add_new_ctls - create controls from the array 2789 * snd_hda_add_new_ctls - create controls from the array
2716 * @codec: the HDA codec 2790 * @codec: the HDA codec
2717 * @knew: the array of struct snd_kcontrol_new 2791 * @knew: the array of struct snd_kcontrol_new
@@ -2803,7 +2877,7 @@ void snd_hda_power_down(struct hda_codec *codec)
2803 return; 2877 return;
2804 if (power_save(codec)) { 2878 if (power_save(codec)) {
2805 codec->power_transition = 1; /* avoid reentrance */ 2879 codec->power_transition = 1; /* avoid reentrance */
2806 schedule_delayed_work(&codec->power_work, 2880 queue_delayed_work(codec->bus->workq, &codec->power_work,
2807 msecs_to_jiffies(power_save(codec) * 1000)); 2881 msecs_to_jiffies(power_save(codec) * 1000));
2808 } 2882 }
2809} 2883}
@@ -3014,6 +3088,16 @@ int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
3014} 3088}
3015EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_prepare); 3089EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_prepare);
3016 3090
3091int snd_hda_multi_out_dig_cleanup(struct hda_codec *codec,
3092 struct hda_multi_out *mout)
3093{
3094 mutex_lock(&codec->spdif_mutex);
3095 cleanup_dig_out_stream(codec, mout->dig_out_nid);
3096 mutex_unlock(&codec->spdif_mutex);
3097 return 0;
3098}
3099EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_cleanup);
3100
3017/* 3101/*
3018 * release the digital out 3102 * release the digital out
3019 */ 3103 */