diff options
author | Takashi Iwai <tiwai@suse.de> | 2013-11-27 06:17:11 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2013-11-27 06:17:11 -0500 |
commit | 351892a8278b50f723974ad42ce591aae57b41e7 (patch) | |
tree | 63fafb11e0ae7921b9c882c18431ab85c493daad | |
parent | d2208ca0562b40f02d507cd5845174dbe9dc8d6c (diff) | |
parent | 0e24dbb7f44877a3565ee461d2209b0942b1a753 (diff) |
Merge branch 'topic/hda' into for-next
-rw-r--r-- | sound/pci/hda/Makefile | 5 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.c | 185 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.h | 8 | ||||
-rw-r--r-- | sound/pci/hda/hda_generic.c | 4 | ||||
-rw-r--r-- | sound/pci/hda/hda_intel.c | 2 | ||||
-rw-r--r-- | sound/pci/hda/hda_local.h | 8 | ||||
-rw-r--r-- | sound/pci/hda/patch_hdmi.c | 24 |
7 files changed, 166 insertions, 70 deletions
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile index c091438286a3..5a40c652df41 100644 --- a/sound/pci/hda/Makefile +++ b/sound/pci/hda/Makefile | |||
@@ -3,7 +3,6 @@ snd-hda-intel-objs := hda_intel.o | |||
3 | snd-hda-intel-$(CONFIG_SND_HDA_I915) += hda_i915.o | 3 | snd-hda-intel-$(CONFIG_SND_HDA_I915) += hda_i915.o |
4 | 4 | ||
5 | snd-hda-codec-y := hda_codec.o hda_jack.o hda_auto_parser.o | 5 | snd-hda-codec-y := hda_codec.o hda_jack.o hda_auto_parser.o |
6 | snd-hda-codec-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o | ||
7 | snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o | 6 | snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o |
8 | snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o | 7 | snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o |
9 | snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o | 8 | snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o |
@@ -12,6 +11,7 @@ snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o | |||
12 | CFLAGS_hda_codec.o := -I$(src) | 11 | CFLAGS_hda_codec.o := -I$(src) |
13 | CFLAGS_hda_intel.o := -I$(src) | 12 | CFLAGS_hda_intel.o := -I$(src) |
14 | 13 | ||
14 | snd-hda-codec-generic-objs := hda_generic.o | ||
15 | snd-hda-codec-realtek-objs := patch_realtek.o | 15 | snd-hda-codec-realtek-objs := patch_realtek.o |
16 | snd-hda-codec-cmedia-objs := patch_cmedia.o | 16 | snd-hda-codec-cmedia-objs := patch_cmedia.o |
17 | snd-hda-codec-analog-objs := patch_analog.o | 17 | snd-hda-codec-analog-objs := patch_analog.o |
@@ -28,6 +28,9 @@ snd-hda-codec-hdmi-objs := patch_hdmi.o hda_eld.o | |||
28 | obj-$(CONFIG_SND_HDA_INTEL) := snd-hda-codec.o | 28 | obj-$(CONFIG_SND_HDA_INTEL) := snd-hda-codec.o |
29 | 29 | ||
30 | # codec drivers (note: CONFIG_SND_HDA_CODEC_XXX are booleans) | 30 | # codec drivers (note: CONFIG_SND_HDA_CODEC_XXX are booleans) |
31 | ifdef CONFIG_SND_HDA_GENERIC | ||
32 | obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-generic.o | ||
33 | endif | ||
31 | ifdef CONFIG_SND_HDA_CODEC_REALTEK | 34 | ifdef CONFIG_SND_HDA_CODEC_REALTEK |
32 | obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-realtek.o | 35 | obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-realtek.o |
33 | endif | 36 | endif |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 69178c4f4113..85886220ee74 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -96,19 +96,28 @@ EXPORT_SYMBOL_HDA(snd_hda_delete_codec_preset); | |||
96 | 96 | ||
97 | #ifdef CONFIG_PM | 97 | #ifdef CONFIG_PM |
98 | #define codec_in_pm(codec) ((codec)->in_pm) | 98 | #define codec_in_pm(codec) ((codec)->in_pm) |
99 | static void hda_pm_work(struct work_struct *work); | ||
99 | static void hda_power_work(struct work_struct *work); | 100 | static void hda_power_work(struct work_struct *work); |
100 | static void hda_keep_power_on(struct hda_codec *codec); | 101 | static void hda_keep_power_on(struct hda_codec *codec); |
101 | #define hda_codec_is_power_on(codec) ((codec)->power_on) | 102 | #define hda_codec_is_power_on(codec) ((codec)->power_on) |
102 | static inline void hda_call_pm_notify(struct hda_bus *bus, bool power_up) | 103 | |
104 | static void hda_call_pm_notify(struct hda_codec *codec, bool power_up) | ||
103 | { | 105 | { |
106 | struct hda_bus *bus = codec->bus; | ||
107 | |||
108 | if ((power_up && codec->pm_up_notified) || | ||
109 | (!power_up && !codec->pm_up_notified)) | ||
110 | return; | ||
104 | if (bus->ops.pm_notify) | 111 | if (bus->ops.pm_notify) |
105 | bus->ops.pm_notify(bus, power_up); | 112 | bus->ops.pm_notify(bus, power_up); |
113 | codec->pm_up_notified = power_up; | ||
106 | } | 114 | } |
115 | |||
107 | #else | 116 | #else |
108 | #define codec_in_pm(codec) 0 | 117 | #define codec_in_pm(codec) 0 |
109 | static inline void hda_keep_power_on(struct hda_codec *codec) {} | 118 | static inline void hda_keep_power_on(struct hda_codec *codec) {} |
110 | #define hda_codec_is_power_on(codec) 1 | 119 | #define hda_codec_is_power_on(codec) 1 |
111 | #define hda_call_pm_notify(bus, state) {} | 120 | #define hda_call_pm_notify(codec, state) {} |
112 | #endif | 121 | #endif |
113 | 122 | ||
114 | /** | 123 | /** |
@@ -831,6 +840,12 @@ static int snd_hda_bus_free(struct hda_bus *bus) | |||
831 | bus->ops.private_free(bus); | 840 | bus->ops.private_free(bus); |
832 | if (bus->workq) | 841 | if (bus->workq) |
833 | destroy_workqueue(bus->workq); | 842 | destroy_workqueue(bus->workq); |
843 | |||
844 | #ifdef CONFIG_PM | ||
845 | if (bus->pm_wq) | ||
846 | destroy_workqueue(bus->pm_wq); | ||
847 | #endif | ||
848 | |||
834 | kfree(bus); | 849 | kfree(bus); |
835 | return 0; | 850 | return 0; |
836 | } | 851 | } |
@@ -875,6 +890,9 @@ int snd_hda_bus_new(struct snd_card *card, | |||
875 | .dev_register = snd_hda_bus_dev_register, | 890 | .dev_register = snd_hda_bus_dev_register, |
876 | .dev_free = snd_hda_bus_dev_free, | 891 | .dev_free = snd_hda_bus_dev_free, |
877 | }; | 892 | }; |
893 | #ifdef CONFIG_PM | ||
894 | char wqname[16]; | ||
895 | #endif | ||
878 | 896 | ||
879 | if (snd_BUG_ON(!temp)) | 897 | if (snd_BUG_ON(!temp)) |
880 | return -EINVAL; | 898 | return -EINVAL; |
@@ -911,6 +929,16 @@ int snd_hda_bus_new(struct snd_card *card, | |||
911 | return -ENOMEM; | 929 | return -ENOMEM; |
912 | } | 930 | } |
913 | 931 | ||
932 | #ifdef CONFIG_PM | ||
933 | sprintf(wqname, "hda-pm-wq-%d", card->number); | ||
934 | bus->pm_wq = create_workqueue(wqname); | ||
935 | if (!bus->pm_wq) { | ||
936 | snd_printk(KERN_ERR "cannot create PM workqueue\n"); | ||
937 | snd_hda_bus_free(bus); | ||
938 | return -ENOMEM; | ||
939 | } | ||
940 | #endif | ||
941 | |||
914 | err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops); | 942 | err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops); |
915 | if (err < 0) { | 943 | if (err < 0) { |
916 | snd_hda_bus_free(bus); | 944 | snd_hda_bus_free(bus); |
@@ -945,9 +973,6 @@ find_codec_preset(struct hda_codec *codec) | |||
945 | const struct hda_codec_preset *preset; | 973 | const struct hda_codec_preset *preset; |
946 | unsigned int mod_requested = 0; | 974 | unsigned int mod_requested = 0; |
947 | 975 | ||
948 | if (is_generic_config(codec)) | ||
949 | return NULL; /* use the generic parser */ | ||
950 | |||
951 | again: | 976 | again: |
952 | mutex_lock(&preset_mutex); | 977 | mutex_lock(&preset_mutex); |
953 | list_for_each_entry(tbl, &hda_preset_tables, list) { | 978 | list_for_each_entry(tbl, &hda_preset_tables, list) { |
@@ -1330,6 +1355,28 @@ get_hda_cvt_setup(struct hda_codec *codec, hda_nid_t nid) | |||
1330 | } | 1355 | } |
1331 | 1356 | ||
1332 | /* | 1357 | /* |
1358 | * Dynamic symbol binding for the codec parsers | ||
1359 | */ | ||
1360 | #ifdef MODULE | ||
1361 | #define load_parser_sym(sym) ((int (*)(struct hda_codec *))symbol_request(sym)) | ||
1362 | #define unload_parser_addr(addr) symbol_put_addr(addr) | ||
1363 | #else | ||
1364 | #define load_parser_sym(sym) (sym) | ||
1365 | #define unload_parser_addr(addr) do {} while (0) | ||
1366 | #endif | ||
1367 | |||
1368 | #define load_parser(codec, sym) \ | ||
1369 | ((codec)->parser = load_parser_sym(sym)) | ||
1370 | |||
1371 | static void unload_parser(struct hda_codec *codec) | ||
1372 | { | ||
1373 | if (codec->parser) { | ||
1374 | unload_parser_addr(codec->parser); | ||
1375 | codec->parser = NULL; | ||
1376 | } | ||
1377 | } | ||
1378 | |||
1379 | /* | ||
1333 | * codec destructor | 1380 | * codec destructor |
1334 | */ | 1381 | */ |
1335 | static void snd_hda_codec_free(struct hda_codec *codec) | 1382 | static void snd_hda_codec_free(struct hda_codec *codec) |
@@ -1352,10 +1399,8 @@ static void snd_hda_codec_free(struct hda_codec *codec) | |||
1352 | codec->bus->caddr_tbl[codec->addr] = NULL; | 1399 | codec->bus->caddr_tbl[codec->addr] = NULL; |
1353 | if (codec->patch_ops.free) | 1400 | if (codec->patch_ops.free) |
1354 | codec->patch_ops.free(codec); | 1401 | codec->patch_ops.free(codec); |
1355 | #ifdef CONFIG_PM | 1402 | hda_call_pm_notify(codec, false); /* cancel leftover refcounts */ |
1356 | if (!codec->pm_down_notified) /* cancel leftover refcounts */ | 1403 | unload_parser(codec); |
1357 | hda_call_pm_notify(codec->bus, false); | ||
1358 | #endif | ||
1359 | module_put(codec->owner); | 1404 | module_put(codec->owner); |
1360 | free_hda_cache(&codec->amp_cache); | 1405 | free_hda_cache(&codec->amp_cache); |
1361 | free_hda_cache(&codec->cmd_cache); | 1406 | free_hda_cache(&codec->cmd_cache); |
@@ -1363,6 +1408,7 @@ static void snd_hda_codec_free(struct hda_codec *codec) | |||
1363 | kfree(codec->chip_name); | 1408 | kfree(codec->chip_name); |
1364 | kfree(codec->modelname); | 1409 | kfree(codec->modelname); |
1365 | kfree(codec->wcaps); | 1410 | kfree(codec->wcaps); |
1411 | codec->bus->num_codecs--; | ||
1366 | kfree(codec); | 1412 | kfree(codec); |
1367 | } | 1413 | } |
1368 | 1414 | ||
@@ -1428,12 +1474,12 @@ int snd_hda_codec_new(struct hda_bus *bus, | |||
1428 | #ifdef CONFIG_PM | 1474 | #ifdef CONFIG_PM |
1429 | spin_lock_init(&codec->power_lock); | 1475 | spin_lock_init(&codec->power_lock); |
1430 | INIT_DELAYED_WORK(&codec->power_work, hda_power_work); | 1476 | INIT_DELAYED_WORK(&codec->power_work, hda_power_work); |
1477 | INIT_WORK(&codec->pm_work, hda_pm_work); | ||
1431 | /* snd_hda_codec_new() marks the codec as power-up, and leave it as is. | 1478 | /* snd_hda_codec_new() marks the codec as power-up, and leave it as is. |
1432 | * the caller has to power down appropriatley after initialization | 1479 | * the caller has to power down appropriatley after initialization |
1433 | * phase. | 1480 | * phase. |
1434 | */ | 1481 | */ |
1435 | hda_keep_power_on(codec); | 1482 | hda_keep_power_on(codec); |
1436 | hda_call_pm_notify(bus, true); | ||
1437 | #endif | 1483 | #endif |
1438 | 1484 | ||
1439 | if (codec->bus->modelname) { | 1485 | if (codec->bus->modelname) { |
@@ -1445,6 +1491,11 @@ int snd_hda_codec_new(struct hda_bus *bus, | |||
1445 | } | 1491 | } |
1446 | 1492 | ||
1447 | list_add_tail(&codec->list, &bus->codec_list); | 1493 | list_add_tail(&codec->list, &bus->codec_list); |
1494 | bus->num_codecs++; | ||
1495 | #ifdef CONFIG_PM | ||
1496 | workqueue_set_max_active(bus->pm_wq, bus->num_codecs); | ||
1497 | #endif | ||
1498 | |||
1448 | bus->caddr_tbl[codec_addr] = codec; | 1499 | bus->caddr_tbl[codec_addr] = codec; |
1449 | 1500 | ||
1450 | codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT, | 1501 | codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT, |
@@ -1486,11 +1537,14 @@ int snd_hda_codec_new(struct hda_bus *bus, | |||
1486 | #ifdef CONFIG_PM | 1537 | #ifdef CONFIG_PM |
1487 | codec->d3_stop_clk = snd_hda_codec_get_supported_ps(codec, fg, | 1538 | codec->d3_stop_clk = snd_hda_codec_get_supported_ps(codec, fg, |
1488 | AC_PWRST_CLKSTOP); | 1539 | AC_PWRST_CLKSTOP); |
1489 | if (!codec->d3_stop_clk) | ||
1490 | bus->power_keep_link_on = 1; | ||
1491 | #endif | 1540 | #endif |
1492 | codec->epss = snd_hda_codec_get_supported_ps(codec, fg, | 1541 | codec->epss = snd_hda_codec_get_supported_ps(codec, fg, |
1493 | AC_PWRST_EPSS); | 1542 | AC_PWRST_EPSS); |
1543 | #ifdef CONFIG_PM | ||
1544 | if (!codec->d3_stop_clk || !codec->epss) | ||
1545 | bus->power_keep_link_on = 1; | ||
1546 | #endif | ||
1547 | |||
1494 | 1548 | ||
1495 | /* power-up all before initialization */ | 1549 | /* power-up all before initialization */ |
1496 | hda_set_power_state(codec, AC_PWRST_D0); | 1550 | hda_set_power_state(codec, AC_PWRST_D0); |
@@ -1537,6 +1591,31 @@ int snd_hda_codec_update_widgets(struct hda_codec *codec) | |||
1537 | EXPORT_SYMBOL_HDA(snd_hda_codec_update_widgets); | 1591 | EXPORT_SYMBOL_HDA(snd_hda_codec_update_widgets); |
1538 | 1592 | ||
1539 | 1593 | ||
1594 | #ifdef CONFIG_SND_HDA_CODEC_HDMI | ||
1595 | /* if all audio out widgets are digital, let's assume the codec as a HDMI/DP */ | ||
1596 | static bool is_likely_hdmi_codec(struct hda_codec *codec) | ||
1597 | { | ||
1598 | hda_nid_t nid = codec->start_nid; | ||
1599 | int i; | ||
1600 | |||
1601 | for (i = 0; i < codec->num_nodes; i++, nid++) { | ||
1602 | unsigned int wcaps = get_wcaps(codec, nid); | ||
1603 | switch (get_wcaps_type(wcaps)) { | ||
1604 | case AC_WID_AUD_IN: | ||
1605 | return false; /* HDMI parser supports only HDMI out */ | ||
1606 | case AC_WID_AUD_OUT: | ||
1607 | if (!(wcaps & AC_WCAP_DIGITAL)) | ||
1608 | return false; | ||
1609 | break; | ||
1610 | } | ||
1611 | } | ||
1612 | return true; | ||
1613 | } | ||
1614 | #else | ||
1615 | /* no HDMI codec parser support */ | ||
1616 | #define is_likely_hdmi_codec(codec) false | ||
1617 | #endif /* CONFIG_SND_HDA_CODEC_HDMI */ | ||
1618 | |||
1540 | /** | 1619 | /** |
1541 | * snd_hda_codec_configure - (Re-)configure the HD-audio codec | 1620 | * snd_hda_codec_configure - (Re-)configure the HD-audio codec |
1542 | * @codec: the HDA codec | 1621 | * @codec: the HDA codec |
@@ -1548,6 +1627,7 @@ EXPORT_SYMBOL_HDA(snd_hda_codec_update_widgets); | |||
1548 | */ | 1627 | */ |
1549 | int snd_hda_codec_configure(struct hda_codec *codec) | 1628 | int snd_hda_codec_configure(struct hda_codec *codec) |
1550 | { | 1629 | { |
1630 | int (*patch)(struct hda_codec *) = NULL; | ||
1551 | int err; | 1631 | int err; |
1552 | 1632 | ||
1553 | codec->preset = find_codec_preset(codec); | 1633 | codec->preset = find_codec_preset(codec); |
@@ -1557,29 +1637,40 @@ int snd_hda_codec_configure(struct hda_codec *codec) | |||
1557 | return err; | 1637 | return err; |
1558 | } | 1638 | } |
1559 | 1639 | ||
1560 | if (is_generic_config(codec)) { | 1640 | if (!is_generic_config(codec) && codec->preset) |
1561 | err = snd_hda_parse_generic_codec(codec); | 1641 | patch = codec->preset->patch; |
1562 | goto patched; | 1642 | if (!patch) { |
1563 | } | 1643 | unload_parser(codec); /* to be sure */ |
1564 | if (codec->preset && codec->preset->patch) { | 1644 | if (is_likely_hdmi_codec(codec)) |
1565 | err = codec->preset->patch(codec); | 1645 | patch = load_parser(codec, snd_hda_parse_hdmi_codec); |
1566 | goto patched; | 1646 | #ifdef CONFIG_SND_HDA_GENERIC |
1647 | if (!patch) | ||
1648 | patch = load_parser(codec, snd_hda_parse_generic_codec); | ||
1649 | #endif | ||
1650 | if (!patch) { | ||
1651 | printk(KERN_ERR "hda-codec: No codec parser is available\n"); | ||
1652 | return -ENODEV; | ||
1653 | } | ||
1567 | } | 1654 | } |
1568 | 1655 | ||
1569 | /* call the default parser */ | 1656 | err = patch(codec); |
1570 | err = snd_hda_parse_generic_codec(codec); | 1657 | if (err < 0) { |
1571 | if (err < 0) | 1658 | unload_parser(codec); |
1572 | printk(KERN_ERR "hda-codec: No codec parser is available\n"); | 1659 | return err; |
1660 | } | ||
1573 | 1661 | ||
1574 | patched: | 1662 | if (codec->patch_ops.unsol_event) { |
1575 | if (!err && codec->patch_ops.unsol_event) | ||
1576 | err = init_unsol_queue(codec->bus); | 1663 | err = init_unsol_queue(codec->bus); |
1664 | if (err < 0) | ||
1665 | return err; | ||
1666 | } | ||
1667 | |||
1577 | /* audio codec should override the mixer name */ | 1668 | /* audio codec should override the mixer name */ |
1578 | if (!err && (codec->afg || !*codec->bus->card->mixername)) | 1669 | if (codec->afg || !*codec->bus->card->mixername) |
1579 | snprintf(codec->bus->card->mixername, | 1670 | snprintf(codec->bus->card->mixername, |
1580 | sizeof(codec->bus->card->mixername), | 1671 | sizeof(codec->bus->card->mixername), |
1581 | "%s %s", codec->vendor_name, codec->chip_name); | 1672 | "%s %s", codec->vendor_name, codec->chip_name); |
1582 | return err; | 1673 | return 0; |
1583 | } | 1674 | } |
1584 | EXPORT_SYMBOL_HDA(snd_hda_codec_configure); | 1675 | EXPORT_SYMBOL_HDA(snd_hda_codec_configure); |
1585 | 1676 | ||
@@ -2610,6 +2701,7 @@ int snd_hda_codec_reset(struct hda_codec *codec) | |||
2610 | codec->preset = NULL; | 2701 | codec->preset = NULL; |
2611 | codec->slave_dig_outs = NULL; | 2702 | codec->slave_dig_outs = NULL; |
2612 | codec->spdif_status_reset = 0; | 2703 | codec->spdif_status_reset = 0; |
2704 | unload_parser(codec); | ||
2613 | module_put(codec->owner); | 2705 | module_put(codec->owner); |
2614 | codec->owner = NULL; | 2706 | codec->owner = NULL; |
2615 | 2707 | ||
@@ -4000,10 +4092,6 @@ static void hda_call_codec_resume(struct hda_codec *codec) | |||
4000 | * in the resume / power-save sequence | 4092 | * in the resume / power-save sequence |
4001 | */ | 4093 | */ |
4002 | hda_keep_power_on(codec); | 4094 | hda_keep_power_on(codec); |
4003 | if (codec->pm_down_notified) { | ||
4004 | codec->pm_down_notified = 0; | ||
4005 | hda_call_pm_notify(codec->bus, true); | ||
4006 | } | ||
4007 | hda_set_power_state(codec, AC_PWRST_D0); | 4095 | hda_set_power_state(codec, AC_PWRST_D0); |
4008 | restore_shutup_pins(codec); | 4096 | restore_shutup_pins(codec); |
4009 | hda_exec_init_verbs(codec); | 4097 | hda_exec_init_verbs(codec); |
@@ -4877,11 +4965,8 @@ static void hda_power_work(struct work_struct *work) | |||
4877 | spin_unlock(&codec->power_lock); | 4965 | spin_unlock(&codec->power_lock); |
4878 | 4966 | ||
4879 | state = hda_call_codec_suspend(codec, true); | 4967 | state = hda_call_codec_suspend(codec, true); |
4880 | if (!codec->pm_down_notified && | 4968 | if (!bus->power_keep_link_on && (state & AC_PWRST_CLK_STOP_OK)) |
4881 | !bus->power_keep_link_on && (state & AC_PWRST_CLK_STOP_OK)) { | 4969 | hda_call_pm_notify(codec, false); |
4882 | codec->pm_down_notified = 1; | ||
4883 | hda_call_pm_notify(bus, false); | ||
4884 | } | ||
4885 | } | 4970 | } |
4886 | 4971 | ||
4887 | static void hda_keep_power_on(struct hda_codec *codec) | 4972 | static void hda_keep_power_on(struct hda_codec *codec) |
@@ -4891,6 +4976,7 @@ static void hda_keep_power_on(struct hda_codec *codec) | |||
4891 | codec->power_on = 1; | 4976 | codec->power_on = 1; |
4892 | codec->power_jiffies = jiffies; | 4977 | codec->power_jiffies = jiffies; |
4893 | spin_unlock(&codec->power_lock); | 4978 | spin_unlock(&codec->power_lock); |
4979 | hda_call_pm_notify(codec, true); | ||
4894 | } | 4980 | } |
4895 | 4981 | ||
4896 | /* update the power on/off account with the current jiffies */ | 4982 | /* update the power on/off account with the current jiffies */ |
@@ -4910,8 +4996,6 @@ void snd_hda_update_power_acct(struct hda_codec *codec) | |||
4910 | /* call this with codec->power_lock held! */ | 4996 | /* call this with codec->power_lock held! */ |
4911 | static void __snd_hda_power_up(struct hda_codec *codec, bool wait_power_down) | 4997 | static void __snd_hda_power_up(struct hda_codec *codec, bool wait_power_down) |
4912 | { | 4998 | { |
4913 | struct hda_bus *bus = codec->bus; | ||
4914 | |||
4915 | /* Return if power_on or transitioning to power_on, unless currently | 4999 | /* Return if power_on or transitioning to power_on, unless currently |
4916 | * powering down. */ | 5000 | * powering down. */ |
4917 | if ((codec->power_on || codec->power_transition > 0) && | 5001 | if ((codec->power_on || codec->power_transition > 0) && |
@@ -4938,11 +5022,6 @@ static void __snd_hda_power_up(struct hda_codec *codec, bool wait_power_down) | |||
4938 | codec->power_transition = 1; /* avoid reentrance */ | 5022 | codec->power_transition = 1; /* avoid reentrance */ |
4939 | spin_unlock(&codec->power_lock); | 5023 | spin_unlock(&codec->power_lock); |
4940 | 5024 | ||
4941 | if (codec->pm_down_notified) { | ||
4942 | codec->pm_down_notified = 0; | ||
4943 | hda_call_pm_notify(bus, true); | ||
4944 | } | ||
4945 | |||
4946 | hda_call_codec_resume(codec); | 5025 | hda_call_codec_resume(codec); |
4947 | 5026 | ||
4948 | spin_lock(&codec->power_lock); | 5027 | spin_lock(&codec->power_lock); |
@@ -5036,6 +5115,14 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec, | |||
5036 | return 0; | 5115 | return 0; |
5037 | } | 5116 | } |
5038 | EXPORT_SYMBOL_HDA(snd_hda_check_amp_list_power); | 5117 | EXPORT_SYMBOL_HDA(snd_hda_check_amp_list_power); |
5118 | |||
5119 | static void hda_pm_work(struct work_struct *work) | ||
5120 | { | ||
5121 | struct hda_codec *codec = | ||
5122 | container_of(work, struct hda_codec, pm_work); | ||
5123 | |||
5124 | hda_call_codec_suspend(codec, false); | ||
5125 | } | ||
5039 | #endif | 5126 | #endif |
5040 | 5127 | ||
5041 | /* | 5128 | /* |
@@ -5611,9 +5698,17 @@ int snd_hda_suspend(struct hda_bus *bus) | |||
5611 | 5698 | ||
5612 | list_for_each_entry(codec, &bus->codec_list, list) { | 5699 | list_for_each_entry(codec, &bus->codec_list, list) { |
5613 | cancel_delayed_work_sync(&codec->jackpoll_work); | 5700 | cancel_delayed_work_sync(&codec->jackpoll_work); |
5614 | if (hda_codec_is_power_on(codec)) | 5701 | if (hda_codec_is_power_on(codec)) { |
5615 | hda_call_codec_suspend(codec, false); | 5702 | if (bus->num_codecs > 1) |
5703 | queue_work(bus->pm_wq, &codec->pm_work); | ||
5704 | else | ||
5705 | hda_call_codec_suspend(codec, false); | ||
5706 | } | ||
5616 | } | 5707 | } |
5708 | |||
5709 | if (bus->num_codecs > 1) | ||
5710 | flush_workqueue(bus->pm_wq); | ||
5711 | |||
5617 | return 0; | 5712 | return 0; |
5618 | } | 5713 | } |
5619 | EXPORT_SYMBOL_HDA(snd_hda_suspend); | 5714 | EXPORT_SYMBOL_HDA(snd_hda_suspend); |
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 7aa9870040c1..9a2798a0313c 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -673,6 +673,7 @@ struct hda_bus { | |||
673 | 673 | ||
674 | /* codec linked list */ | 674 | /* codec linked list */ |
675 | struct list_head codec_list; | 675 | struct list_head codec_list; |
676 | unsigned int num_codecs; | ||
676 | /* link caddr -> codec */ | 677 | /* link caddr -> codec */ |
677 | struct hda_codec *caddr_tbl[HDA_MAX_CODEC_ADDRESS + 1]; | 678 | struct hda_codec *caddr_tbl[HDA_MAX_CODEC_ADDRESS + 1]; |
678 | 679 | ||
@@ -683,6 +684,9 @@ struct hda_bus { | |||
683 | struct hda_bus_unsolicited *unsol; | 684 | struct hda_bus_unsolicited *unsol; |
684 | char workq_name[16]; | 685 | char workq_name[16]; |
685 | struct workqueue_struct *workq; /* common workqueue for codecs */ | 686 | struct workqueue_struct *workq; /* common workqueue for codecs */ |
687 | #ifdef CONFIG_PM | ||
688 | struct workqueue_struct *pm_wq; /* workqueue to parallel codec PM */ | ||
689 | #endif | ||
686 | 690 | ||
687 | /* assigned PCMs */ | 691 | /* assigned PCMs */ |
688 | DECLARE_BITMAP(pcm_dev_bits, SNDRV_PCM_DEVICES); | 692 | DECLARE_BITMAP(pcm_dev_bits, SNDRV_PCM_DEVICES); |
@@ -834,6 +838,7 @@ struct hda_codec { | |||
834 | /* detected preset */ | 838 | /* detected preset */ |
835 | const struct hda_codec_preset *preset; | 839 | const struct hda_codec_preset *preset; |
836 | struct module *owner; | 840 | struct module *owner; |
841 | int (*parser)(struct hda_codec *codec); | ||
837 | const char *vendor_name; /* codec vendor name */ | 842 | const char *vendor_name; /* codec vendor name */ |
838 | const char *chip_name; /* codec chip name */ | 843 | const char *chip_name; /* codec chip name */ |
839 | const char *modelname; /* model name for preset */ | 844 | const char *modelname; /* model name for preset */ |
@@ -907,7 +912,7 @@ struct hda_codec { | |||
907 | #ifdef CONFIG_PM | 912 | #ifdef CONFIG_PM |
908 | unsigned int power_on :1; /* current (global) power-state */ | 913 | unsigned int power_on :1; /* current (global) power-state */ |
909 | unsigned int d3_stop_clk:1; /* support D3 operation without BCLK */ | 914 | unsigned int d3_stop_clk:1; /* support D3 operation without BCLK */ |
910 | unsigned int pm_down_notified:1; /* PM notified to controller */ | 915 | unsigned int pm_up_notified:1; /* PM notified to controller */ |
911 | unsigned int in_pm:1; /* suspend/resume being performed */ | 916 | unsigned int in_pm:1; /* suspend/resume being performed */ |
912 | int power_transition; /* power-state in transition */ | 917 | int power_transition; /* power-state in transition */ |
913 | int power_count; /* current (global) power refcount */ | 918 | int power_count; /* current (global) power refcount */ |
@@ -916,6 +921,7 @@ struct hda_codec { | |||
916 | unsigned long power_off_acct; | 921 | unsigned long power_off_acct; |
917 | unsigned long power_jiffies; | 922 | unsigned long power_jiffies; |
918 | spinlock_t power_lock; | 923 | spinlock_t power_lock; |
924 | struct work_struct pm_work; /* task to parallel multi-codec PM */ | ||
919 | #endif | 925 | #endif |
920 | 926 | ||
921 | /* filter the requested power state per nid */ | 927 | /* filter the requested power state per nid */ |
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 3067ed4fe3b2..9b251456f2a0 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/ctype.h> | 28 | #include <linux/ctype.h> |
29 | #include <linux/string.h> | 29 | #include <linux/string.h> |
30 | #include <linux/bitops.h> | 30 | #include <linux/bitops.h> |
31 | #include <linux/module.h> | ||
31 | #include <sound/core.h> | 32 | #include <sound/core.h> |
32 | #include <sound/jack.h> | 33 | #include <sound/jack.h> |
33 | #include "hda_codec.h" | 34 | #include "hda_codec.h" |
@@ -5291,3 +5292,6 @@ error: | |||
5291 | return err; | 5292 | return err; |
5292 | } | 5293 | } |
5293 | EXPORT_SYMBOL_HDA(snd_hda_parse_generic_codec); | 5294 | EXPORT_SYMBOL_HDA(snd_hda_parse_generic_codec); |
5295 | |||
5296 | MODULE_LICENSE("GPL"); | ||
5297 | MODULE_DESCRIPTION("Generic HD-audio codec parser"); | ||
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index c6d230193da6..dfdb96603636 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -3978,7 +3978,7 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { | |||
3978 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM }, | 3978 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM }, |
3979 | /* Panther Point */ | 3979 | /* Panther Point */ |
3980 | { PCI_DEVICE(0x8086, 0x1e20), | 3980 | { PCI_DEVICE(0x8086, 0x1e20), |
3981 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM }, | 3981 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, |
3982 | /* Lynx Point */ | 3982 | /* Lynx Point */ |
3983 | { PCI_DEVICE(0x8086, 0x8c20), | 3983 | { PCI_DEVICE(0x8086, 0x8c20), |
3984 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, | 3984 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, |
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index d398b648bb5d..da80c5bd7fd4 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h | |||
@@ -352,14 +352,8 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, | |||
352 | /* | 352 | /* |
353 | * generic codec parser | 353 | * generic codec parser |
354 | */ | 354 | */ |
355 | #ifdef CONFIG_SND_HDA_GENERIC | ||
356 | int snd_hda_parse_generic_codec(struct hda_codec *codec); | 355 | int snd_hda_parse_generic_codec(struct hda_codec *codec); |
357 | #else | 356 | int snd_hda_parse_hdmi_codec(struct hda_codec *codec); |
358 | static inline int snd_hda_parse_generic_codec(struct hda_codec *codec) | ||
359 | { | ||
360 | return -ENODEV; | ||
361 | } | ||
362 | #endif | ||
363 | 357 | ||
364 | /* | 358 | /* |
365 | * generic proc interface | 359 | * generic proc interface |
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 08407bed093e..4098196b2300 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c | |||
@@ -1692,21 +1692,6 @@ static int hdmi_parse_codec(struct hda_codec *codec) | |||
1692 | } | 1692 | } |
1693 | } | 1693 | } |
1694 | 1694 | ||
1695 | #ifdef CONFIG_PM | ||
1696 | /* We're seeing some problems with unsolicited hot plug events on | ||
1697 | * PantherPoint after S3, if this is not enabled */ | ||
1698 | if (codec->vendor_id == 0x80862806) | ||
1699 | codec->bus->power_keep_link_on = 1; | ||
1700 | /* | ||
1701 | * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event | ||
1702 | * can be lost and presence sense verb will become inaccurate if the | ||
1703 | * HDA link is powered off at hot plug or hw initialization time. | ||
1704 | */ | ||
1705 | else if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) & | ||
1706 | AC_PWRST_EPSS)) | ||
1707 | codec->bus->power_keep_link_on = 1; | ||
1708 | #endif | ||
1709 | |||
1710 | return 0; | 1695 | return 0; |
1711 | } | 1696 | } |
1712 | 1697 | ||
@@ -3214,6 +3199,15 @@ static int patch_via_hdmi(struct hda_codec *codec) | |||
3214 | } | 3199 | } |
3215 | 3200 | ||
3216 | /* | 3201 | /* |
3202 | * called from hda_codec.c for generic HDMI support | ||
3203 | */ | ||
3204 | int snd_hda_parse_hdmi_codec(struct hda_codec *codec) | ||
3205 | { | ||
3206 | return patch_generic_hdmi(codec); | ||
3207 | } | ||
3208 | EXPORT_SYMBOL_HDA(snd_hda_parse_hdmi_codec); | ||
3209 | |||
3210 | /* | ||
3217 | * patch entries | 3211 | * patch entries |
3218 | */ | 3212 | */ |
3219 | static const struct hda_codec_preset snd_hda_preset_hdmi[] = { | 3213 | static const struct hda_codec_preset snd_hda_preset_hdmi[] = { |