diff options
Diffstat (limited to 'sound/pci/hda/hda_codec.c')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 307 |
1 files changed, 16 insertions, 291 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 5e755eb6f19a..61c8174e8013 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -40,69 +40,6 @@ | |||
40 | #define CREATE_TRACE_POINTS | 40 | #define CREATE_TRACE_POINTS |
41 | #include "hda_trace.h" | 41 | #include "hda_trace.h" |
42 | 42 | ||
43 | /* | ||
44 | * vendor / preset table | ||
45 | */ | ||
46 | |||
47 | struct hda_vendor_id { | ||
48 | unsigned int id; | ||
49 | const char *name; | ||
50 | }; | ||
51 | |||
52 | /* codec vendor labels */ | ||
53 | static struct hda_vendor_id hda_vendor_ids[] = { | ||
54 | { 0x1002, "ATI" }, | ||
55 | { 0x1013, "Cirrus Logic" }, | ||
56 | { 0x1057, "Motorola" }, | ||
57 | { 0x1095, "Silicon Image" }, | ||
58 | { 0x10de, "Nvidia" }, | ||
59 | { 0x10ec, "Realtek" }, | ||
60 | { 0x1102, "Creative" }, | ||
61 | { 0x1106, "VIA" }, | ||
62 | { 0x111d, "IDT" }, | ||
63 | { 0x11c1, "LSI" }, | ||
64 | { 0x11d4, "Analog Devices" }, | ||
65 | { 0x13f6, "C-Media" }, | ||
66 | { 0x14f1, "Conexant" }, | ||
67 | { 0x17e8, "Chrontel" }, | ||
68 | { 0x1854, "LG" }, | ||
69 | { 0x1aec, "Wolfson Microelectronics" }, | ||
70 | { 0x1af4, "QEMU" }, | ||
71 | { 0x434d, "C-Media" }, | ||
72 | { 0x8086, "Intel" }, | ||
73 | { 0x8384, "SigmaTel" }, | ||
74 | {} /* terminator */ | ||
75 | }; | ||
76 | |||
77 | static DEFINE_MUTEX(preset_mutex); | ||
78 | static LIST_HEAD(hda_preset_tables); | ||
79 | |||
80 | /** | ||
81 | * snd_hda_add_codec_preset - Add a codec preset to the chain | ||
82 | * @preset: codec preset table to add | ||
83 | */ | ||
84 | int snd_hda_add_codec_preset(struct hda_codec_preset_list *preset) | ||
85 | { | ||
86 | mutex_lock(&preset_mutex); | ||
87 | list_add_tail(&preset->list, &hda_preset_tables); | ||
88 | mutex_unlock(&preset_mutex); | ||
89 | return 0; | ||
90 | } | ||
91 | EXPORT_SYMBOL_GPL(snd_hda_add_codec_preset); | ||
92 | |||
93 | /** | ||
94 | * snd_hda_delete_codec_preset - Delete a codec preset from the chain | ||
95 | * @preset: codec preset table to delete | ||
96 | */ | ||
97 | int snd_hda_delete_codec_preset(struct hda_codec_preset_list *preset) | ||
98 | { | ||
99 | mutex_lock(&preset_mutex); | ||
100 | list_del(&preset->list); | ||
101 | mutex_unlock(&preset_mutex); | ||
102 | return 0; | ||
103 | } | ||
104 | EXPORT_SYMBOL_GPL(snd_hda_delete_codec_preset); | ||
105 | |||
106 | #ifdef CONFIG_PM | 43 | #ifdef CONFIG_PM |
107 | #define codec_in_pm(codec) ((codec)->in_pm) | 44 | #define codec_in_pm(codec) ((codec)->in_pm) |
108 | static void hda_power_work(struct work_struct *work); | 45 | static void hda_power_work(struct work_struct *work); |
@@ -885,111 +822,6 @@ int snd_hda_bus_new(struct snd_card *card, | |||
885 | } | 822 | } |
886 | EXPORT_SYMBOL_GPL(snd_hda_bus_new); | 823 | EXPORT_SYMBOL_GPL(snd_hda_bus_new); |
887 | 824 | ||
888 | #if IS_ENABLED(CONFIG_SND_HDA_GENERIC) | ||
889 | #define is_generic_config(codec) \ | ||
890 | (codec->modelname && !strcmp(codec->modelname, "generic")) | ||
891 | #else | ||
892 | #define is_generic_config(codec) 0 | ||
893 | #endif | ||
894 | |||
895 | #ifdef MODULE | ||
896 | #define HDA_MODREQ_MAX_COUNT 2 /* two request_modules()'s */ | ||
897 | #else | ||
898 | #define HDA_MODREQ_MAX_COUNT 0 /* all presets are statically linked */ | ||
899 | #endif | ||
900 | |||
901 | /* | ||
902 | * find a matching codec preset | ||
903 | */ | ||
904 | static const struct hda_codec_preset * | ||
905 | find_codec_preset(struct hda_codec *codec) | ||
906 | { | ||
907 | struct hda_codec_preset_list *tbl; | ||
908 | const struct hda_codec_preset *preset; | ||
909 | unsigned int mod_requested = 0; | ||
910 | |||
911 | again: | ||
912 | mutex_lock(&preset_mutex); | ||
913 | list_for_each_entry(tbl, &hda_preset_tables, list) { | ||
914 | if (!try_module_get(tbl->owner)) { | ||
915 | codec_err(codec, "cannot module_get\n"); | ||
916 | continue; | ||
917 | } | ||
918 | for (preset = tbl->preset; preset->id; preset++) { | ||
919 | u32 mask = preset->mask; | ||
920 | if (preset->afg && preset->afg != codec->afg) | ||
921 | continue; | ||
922 | if (preset->mfg && preset->mfg != codec->mfg) | ||
923 | continue; | ||
924 | if (!mask) | ||
925 | mask = ~0; | ||
926 | if (preset->id == (codec->vendor_id & mask) && | ||
927 | (!preset->rev || | ||
928 | preset->rev == codec->revision_id)) { | ||
929 | mutex_unlock(&preset_mutex); | ||
930 | codec->owner = tbl->owner; | ||
931 | return preset; | ||
932 | } | ||
933 | } | ||
934 | module_put(tbl->owner); | ||
935 | } | ||
936 | mutex_unlock(&preset_mutex); | ||
937 | |||
938 | if (mod_requested < HDA_MODREQ_MAX_COUNT) { | ||
939 | if (!mod_requested) | ||
940 | request_module("snd-hda-codec-id:%08x", | ||
941 | codec->vendor_id); | ||
942 | else | ||
943 | request_module("snd-hda-codec-id:%04x*", | ||
944 | (codec->vendor_id >> 16) & 0xffff); | ||
945 | mod_requested++; | ||
946 | goto again; | ||
947 | } | ||
948 | return NULL; | ||
949 | } | ||
950 | |||
951 | /* | ||
952 | * get_codec_name - store the codec name | ||
953 | */ | ||
954 | static int get_codec_name(struct hda_codec *codec) | ||
955 | { | ||
956 | const struct hda_vendor_id *c; | ||
957 | const char *vendor = NULL; | ||
958 | u16 vendor_id = codec->vendor_id >> 16; | ||
959 | char tmp[16]; | ||
960 | |||
961 | if (codec->vendor_name) | ||
962 | goto get_chip_name; | ||
963 | |||
964 | for (c = hda_vendor_ids; c->id; c++) { | ||
965 | if (c->id == vendor_id) { | ||
966 | vendor = c->name; | ||
967 | break; | ||
968 | } | ||
969 | } | ||
970 | if (!vendor) { | ||
971 | sprintf(tmp, "Generic %04x", vendor_id); | ||
972 | vendor = tmp; | ||
973 | } | ||
974 | codec->vendor_name = kstrdup(vendor, GFP_KERNEL); | ||
975 | if (!codec->vendor_name) | ||
976 | return -ENOMEM; | ||
977 | |||
978 | get_chip_name: | ||
979 | if (codec->chip_name) | ||
980 | return 0; | ||
981 | |||
982 | if (codec->preset && codec->preset->name) | ||
983 | codec->chip_name = kstrdup(codec->preset->name, GFP_KERNEL); | ||
984 | else { | ||
985 | sprintf(tmp, "ID %x", codec->vendor_id & 0xffff); | ||
986 | codec->chip_name = kstrdup(tmp, GFP_KERNEL); | ||
987 | } | ||
988 | if (!codec->chip_name) | ||
989 | return -ENOMEM; | ||
990 | return 0; | ||
991 | } | ||
992 | |||
993 | /* | 825 | /* |
994 | * look for an AFG and MFG nodes | 826 | * look for an AFG and MFG nodes |
995 | */ | 827 | */ |
@@ -1301,20 +1133,6 @@ get_hda_cvt_setup(struct hda_codec *codec, hda_nid_t nid) | |||
1301 | } | 1133 | } |
1302 | 1134 | ||
1303 | /* | 1135 | /* |
1304 | * Dynamic symbol binding for the codec parsers | ||
1305 | */ | ||
1306 | |||
1307 | #define load_parser(codec, sym) \ | ||
1308 | ((codec)->parser = (int (*)(struct hda_codec *))symbol_request(sym)) | ||
1309 | |||
1310 | static void unload_parser(struct hda_codec *codec) | ||
1311 | { | ||
1312 | if (codec->parser) | ||
1313 | symbol_put_addr(codec->parser); | ||
1314 | codec->parser = NULL; | ||
1315 | } | ||
1316 | |||
1317 | /* | ||
1318 | * codec destructor | 1136 | * codec destructor |
1319 | */ | 1137 | */ |
1320 | static void snd_hda_codec_free(struct hda_codec *codec) | 1138 | static void snd_hda_codec_free(struct hda_codec *codec) |
@@ -1322,6 +1140,8 @@ static void snd_hda_codec_free(struct hda_codec *codec) | |||
1322 | if (!codec) | 1140 | if (!codec) |
1323 | return; | 1141 | return; |
1324 | cancel_delayed_work_sync(&codec->jackpoll_work); | 1142 | cancel_delayed_work_sync(&codec->jackpoll_work); |
1143 | if (device_is_registered(hda_codec_dev(codec))) | ||
1144 | device_del(hda_codec_dev(codec)); | ||
1325 | snd_hda_jack_tbl_clear(codec); | 1145 | snd_hda_jack_tbl_clear(codec); |
1326 | free_init_pincfgs(codec); | 1146 | free_init_pincfgs(codec); |
1327 | #ifdef CONFIG_PM | 1147 | #ifdef CONFIG_PM |
@@ -1335,12 +1155,8 @@ static void snd_hda_codec_free(struct hda_codec *codec) | |||
1335 | snd_array_free(&codec->spdif_out); | 1155 | snd_array_free(&codec->spdif_out); |
1336 | remove_conn_list(codec); | 1156 | remove_conn_list(codec); |
1337 | codec->bus->caddr_tbl[codec->addr] = NULL; | 1157 | codec->bus->caddr_tbl[codec->addr] = NULL; |
1338 | if (codec->patch_ops.free) | ||
1339 | codec->patch_ops.free(codec); | ||
1340 | hda_call_pm_notify(codec, false); /* cancel leftover refcounts */ | 1158 | hda_call_pm_notify(codec, false); /* cancel leftover refcounts */ |
1341 | snd_hda_sysfs_clear(codec); | 1159 | snd_hda_sysfs_clear(codec); |
1342 | unload_parser(codec); | ||
1343 | module_put(codec->owner); | ||
1344 | free_hda_cache(&codec->amp_cache); | 1160 | free_hda_cache(&codec->amp_cache); |
1345 | free_hda_cache(&codec->cmd_cache); | 1161 | free_hda_cache(&codec->cmd_cache); |
1346 | kfree(codec->vendor_name); | 1162 | kfree(codec->vendor_name); |
@@ -1348,7 +1164,7 @@ static void snd_hda_codec_free(struct hda_codec *codec) | |||
1348 | kfree(codec->modelname); | 1164 | kfree(codec->modelname); |
1349 | kfree(codec->wcaps); | 1165 | kfree(codec->wcaps); |
1350 | codec->bus->num_codecs--; | 1166 | codec->bus->num_codecs--; |
1351 | put_device(&codec->dev); | 1167 | put_device(hda_codec_dev(codec)); |
1352 | } | 1168 | } |
1353 | 1169 | ||
1354 | static bool snd_hda_codec_get_supported_ps(struct hda_codec *codec, | 1170 | static bool snd_hda_codec_get_supported_ps(struct hda_codec *codec, |
@@ -1360,10 +1176,7 @@ static unsigned int hda_set_power_state(struct hda_codec *codec, | |||
1360 | static int snd_hda_codec_dev_register(struct snd_device *device) | 1176 | static int snd_hda_codec_dev_register(struct snd_device *device) |
1361 | { | 1177 | { |
1362 | struct hda_codec *codec = device->device_data; | 1178 | struct hda_codec *codec = device->device_data; |
1363 | int err = device_add(&codec->dev); | ||
1364 | 1179 | ||
1365 | if (err < 0) | ||
1366 | return err; | ||
1367 | snd_hda_register_beep_device(codec); | 1180 | snd_hda_register_beep_device(codec); |
1368 | return 0; | 1181 | return 0; |
1369 | } | 1182 | } |
@@ -1373,7 +1186,6 @@ static int snd_hda_codec_dev_disconnect(struct snd_device *device) | |||
1373 | struct hda_codec *codec = device->device_data; | 1186 | struct hda_codec *codec = device->device_data; |
1374 | 1187 | ||
1375 | snd_hda_detach_beep_device(codec); | 1188 | snd_hda_detach_beep_device(codec); |
1376 | device_del(&codec->dev); | ||
1377 | return 0; | 1189 | return 0; |
1378 | } | 1190 | } |
1379 | 1191 | ||
@@ -1386,7 +1198,7 @@ static int snd_hda_codec_dev_free(struct snd_device *device) | |||
1386 | /* just free the container */ | 1198 | /* just free the container */ |
1387 | static void snd_hda_codec_dev_release(struct device *dev) | 1199 | static void snd_hda_codec_dev_release(struct device *dev) |
1388 | { | 1200 | { |
1389 | kfree(container_of(dev, struct hda_codec, dev)); | 1201 | kfree(dev_to_hda_codec(dev)); |
1390 | } | 1202 | } |
1391 | 1203 | ||
1392 | /** | 1204 | /** |
@@ -1402,6 +1214,7 @@ int snd_hda_codec_new(struct hda_bus *bus, | |||
1402 | struct hda_codec **codecp) | 1214 | struct hda_codec **codecp) |
1403 | { | 1215 | { |
1404 | struct hda_codec *codec; | 1216 | struct hda_codec *codec; |
1217 | struct device *dev; | ||
1405 | char component[31]; | 1218 | char component[31]; |
1406 | hda_nid_t fg; | 1219 | hda_nid_t fg; |
1407 | int err; | 1220 | int err; |
@@ -1429,14 +1242,14 @@ int snd_hda_codec_new(struct hda_bus *bus, | |||
1429 | return -ENOMEM; | 1242 | return -ENOMEM; |
1430 | } | 1243 | } |
1431 | 1244 | ||
1432 | device_initialize(&codec->dev); | 1245 | dev = hda_codec_dev(codec); |
1433 | codec->dev.parent = &bus->card->card_dev; | 1246 | device_initialize(dev); |
1434 | codec->dev.class = sound_class; | 1247 | dev->parent = bus->card->dev; |
1435 | codec->dev.release = snd_hda_codec_dev_release; | 1248 | dev->bus = &snd_hda_bus_type; |
1436 | codec->dev.groups = snd_hda_dev_attr_groups; | 1249 | dev->release = snd_hda_codec_dev_release; |
1437 | dev_set_name(&codec->dev, "hdaudioC%dD%d", bus->card->number, | 1250 | dev->groups = snd_hda_dev_attr_groups; |
1438 | codec_addr); | 1251 | dev_set_name(dev, "hdaudioC%dD%d", bus->card->number, codec_addr); |
1439 | dev_set_drvdata(&codec->dev, codec); /* for sysfs */ | 1252 | dev_set_drvdata(dev, codec); /* for sysfs */ |
1440 | 1253 | ||
1441 | codec->bus = bus; | 1254 | codec->bus = bus; |
1442 | codec->addr = codec_addr; | 1255 | codec->addr = codec_addr; |
@@ -1587,92 +1400,6 @@ int snd_hda_codec_update_widgets(struct hda_codec *codec) | |||
1587 | } | 1400 | } |
1588 | EXPORT_SYMBOL_GPL(snd_hda_codec_update_widgets); | 1401 | EXPORT_SYMBOL_GPL(snd_hda_codec_update_widgets); |
1589 | 1402 | ||
1590 | |||
1591 | #if IS_ENABLED(CONFIG_SND_HDA_CODEC_HDMI) | ||
1592 | /* if all audio out widgets are digital, let's assume the codec as a HDMI/DP */ | ||
1593 | static bool is_likely_hdmi_codec(struct hda_codec *codec) | ||
1594 | { | ||
1595 | hda_nid_t nid = codec->start_nid; | ||
1596 | int i; | ||
1597 | |||
1598 | for (i = 0; i < codec->num_nodes; i++, nid++) { | ||
1599 | unsigned int wcaps = get_wcaps(codec, nid); | ||
1600 | switch (get_wcaps_type(wcaps)) { | ||
1601 | case AC_WID_AUD_IN: | ||
1602 | return false; /* HDMI parser supports only HDMI out */ | ||
1603 | case AC_WID_AUD_OUT: | ||
1604 | if (!(wcaps & AC_WCAP_DIGITAL)) | ||
1605 | return false; | ||
1606 | break; | ||
1607 | } | ||
1608 | } | ||
1609 | return true; | ||
1610 | } | ||
1611 | #else | ||
1612 | /* no HDMI codec parser support */ | ||
1613 | #define is_likely_hdmi_codec(codec) false | ||
1614 | #endif /* CONFIG_SND_HDA_CODEC_HDMI */ | ||
1615 | |||
1616 | /** | ||
1617 | * snd_hda_codec_configure - (Re-)configure the HD-audio codec | ||
1618 | * @codec: the HDA codec | ||
1619 | * | ||
1620 | * Start parsing of the given codec tree and (re-)initialize the whole | ||
1621 | * patch instance. | ||
1622 | * | ||
1623 | * Returns 0 if successful or a negative error code. | ||
1624 | */ | ||
1625 | int snd_hda_codec_configure(struct hda_codec *codec) | ||
1626 | { | ||
1627 | int (*patch)(struct hda_codec *) = NULL; | ||
1628 | int err; | ||
1629 | |||
1630 | codec->preset = find_codec_preset(codec); | ||
1631 | if (!codec->vendor_name || !codec->chip_name) { | ||
1632 | err = get_codec_name(codec); | ||
1633 | if (err < 0) | ||
1634 | return err; | ||
1635 | } | ||
1636 | |||
1637 | if (!is_generic_config(codec) && codec->preset) | ||
1638 | patch = codec->preset->patch; | ||
1639 | if (!patch) { | ||
1640 | unload_parser(codec); /* to be sure */ | ||
1641 | if (is_likely_hdmi_codec(codec)) { | ||
1642 | #if IS_MODULE(CONFIG_SND_HDA_CODEC_HDMI) | ||
1643 | patch = load_parser(codec, snd_hda_parse_hdmi_codec); | ||
1644 | #elif IS_BUILTIN(CONFIG_SND_HDA_CODEC_HDMI) | ||
1645 | patch = snd_hda_parse_hdmi_codec; | ||
1646 | #endif | ||
1647 | } | ||
1648 | if (!patch) { | ||
1649 | #if IS_MODULE(CONFIG_SND_HDA_GENERIC) | ||
1650 | patch = load_parser(codec, snd_hda_parse_generic_codec); | ||
1651 | #elif IS_BUILTIN(CONFIG_SND_HDA_GENERIC) | ||
1652 | patch = snd_hda_parse_generic_codec; | ||
1653 | #endif | ||
1654 | } | ||
1655 | if (!patch) { | ||
1656 | codec_err(codec, "No codec parser is available\n"); | ||
1657 | return -ENODEV; | ||
1658 | } | ||
1659 | } | ||
1660 | |||
1661 | err = patch(codec); | ||
1662 | if (err < 0) { | ||
1663 | unload_parser(codec); | ||
1664 | return err; | ||
1665 | } | ||
1666 | |||
1667 | /* audio codec should override the mixer name */ | ||
1668 | if (codec->afg || !*codec->bus->card->mixername) | ||
1669 | snprintf(codec->bus->card->mixername, | ||
1670 | sizeof(codec->bus->card->mixername), | ||
1671 | "%s %s", codec->vendor_name, codec->chip_name); | ||
1672 | return 0; | ||
1673 | } | ||
1674 | EXPORT_SYMBOL_GPL(snd_hda_codec_configure); | ||
1675 | |||
1676 | /* update the stream-id if changed */ | 1403 | /* update the stream-id if changed */ |
1677 | static void update_pcm_stream_id(struct hda_codec *codec, | 1404 | static void update_pcm_stream_id(struct hda_codec *codec, |
1678 | struct hda_cvt_setup *p, hda_nid_t nid, | 1405 | struct hda_cvt_setup *p, hda_nid_t nid, |
@@ -2739,8 +2466,9 @@ int snd_hda_codec_reset(struct hda_codec *codec) | |||
2739 | } | 2466 | } |
2740 | } | 2467 | } |
2741 | snd_hda_detach_beep_device(codec); | 2468 | snd_hda_detach_beep_device(codec); |
2742 | if (codec->patch_ops.free) | 2469 | if (device_is_registered(hda_codec_dev(codec))) |
2743 | codec->patch_ops.free(codec); | 2470 | device_del(hda_codec_dev(codec)); |
2471 | |||
2744 | memset(&codec->patch_ops, 0, sizeof(codec->patch_ops)); | 2472 | memset(&codec->patch_ops, 0, sizeof(codec->patch_ops)); |
2745 | snd_hda_jack_tbl_clear(codec); | 2473 | snd_hda_jack_tbl_clear(codec); |
2746 | codec->proc_widget_hook = NULL; | 2474 | codec->proc_widget_hook = NULL; |
@@ -2759,9 +2487,6 @@ int snd_hda_codec_reset(struct hda_codec *codec) | |||
2759 | codec->preset = NULL; | 2487 | codec->preset = NULL; |
2760 | codec->slave_dig_outs = NULL; | 2488 | codec->slave_dig_outs = NULL; |
2761 | codec->spdif_status_reset = 0; | 2489 | codec->spdif_status_reset = 0; |
2762 | unload_parser(codec); | ||
2763 | module_put(codec->owner); | ||
2764 | codec->owner = NULL; | ||
2765 | 2490 | ||
2766 | /* allow device access again */ | 2491 | /* allow device access again */ |
2767 | snd_hda_unlock_devices(bus); | 2492 | snd_hda_unlock_devices(bus); |