diff options
author | Takashi Iwai <tiwai@suse.de> | 2013-11-18 06:03:56 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2013-11-26 07:42:38 -0500 |
commit | b21bdd0d343c8b2496690283211e27c9af598ed3 (patch) | |
tree | 23500f17dae3e8998009078e389f5702572ebbbf /sound/pci/hda/hda_codec.c | |
parent | 873ce8ad502cce3ba9295890d52afcce385d4107 (diff) |
ALSA: hda - Split the generic parser as an individual module
Drop the hard dependency on the generic parser code and load / unload
the generic parser code dynamically if built as a module. This allows
us to avoid the generic parser if only HDMI/DP codecs are found.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/hda_codec.c')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 67 |
1 files changed, 49 insertions, 18 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 69178c4f4113..4d3f46329eb5 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -945,9 +945,6 @@ find_codec_preset(struct hda_codec *codec) | |||
945 | const struct hda_codec_preset *preset; | 945 | const struct hda_codec_preset *preset; |
946 | unsigned int mod_requested = 0; | 946 | unsigned int mod_requested = 0; |
947 | 947 | ||
948 | if (is_generic_config(codec)) | ||
949 | return NULL; /* use the generic parser */ | ||
950 | |||
951 | again: | 948 | again: |
952 | mutex_lock(&preset_mutex); | 949 | mutex_lock(&preset_mutex); |
953 | list_for_each_entry(tbl, &hda_preset_tables, list) { | 950 | list_for_each_entry(tbl, &hda_preset_tables, list) { |
@@ -1330,6 +1327,28 @@ get_hda_cvt_setup(struct hda_codec *codec, hda_nid_t nid) | |||
1330 | } | 1327 | } |
1331 | 1328 | ||
1332 | /* | 1329 | /* |
1330 | * Dynamic symbol binding for the codec parsers | ||
1331 | */ | ||
1332 | #ifdef MODULE | ||
1333 | #define load_parser_sym(sym) ((int (*)(struct hda_codec *))symbol_request(sym)) | ||
1334 | #define unload_parser_addr(addr) symbol_put_addr(addr) | ||
1335 | #else | ||
1336 | #define load_parser_sym(sym) (sym) | ||
1337 | #define unload_parser_addr(addr) do {} while (0) | ||
1338 | #endif | ||
1339 | |||
1340 | #define load_parser(codec, sym) \ | ||
1341 | ((codec)->parser = load_parser_sym(sym)) | ||
1342 | |||
1343 | static void unload_parser(struct hda_codec *codec) | ||
1344 | { | ||
1345 | if (codec->parser) { | ||
1346 | unload_parser_addr(codec->parser); | ||
1347 | codec->parser = NULL; | ||
1348 | } | ||
1349 | } | ||
1350 | |||
1351 | /* | ||
1333 | * codec destructor | 1352 | * codec destructor |
1334 | */ | 1353 | */ |
1335 | static void snd_hda_codec_free(struct hda_codec *codec) | 1354 | static void snd_hda_codec_free(struct hda_codec *codec) |
@@ -1356,6 +1375,7 @@ static void snd_hda_codec_free(struct hda_codec *codec) | |||
1356 | if (!codec->pm_down_notified) /* cancel leftover refcounts */ | 1375 | if (!codec->pm_down_notified) /* cancel leftover refcounts */ |
1357 | hda_call_pm_notify(codec->bus, false); | 1376 | hda_call_pm_notify(codec->bus, false); |
1358 | #endif | 1377 | #endif |
1378 | unload_parser(codec); | ||
1359 | module_put(codec->owner); | 1379 | module_put(codec->owner); |
1360 | free_hda_cache(&codec->amp_cache); | 1380 | free_hda_cache(&codec->amp_cache); |
1361 | free_hda_cache(&codec->cmd_cache); | 1381 | free_hda_cache(&codec->cmd_cache); |
@@ -1548,6 +1568,7 @@ EXPORT_SYMBOL_HDA(snd_hda_codec_update_widgets); | |||
1548 | */ | 1568 | */ |
1549 | int snd_hda_codec_configure(struct hda_codec *codec) | 1569 | int snd_hda_codec_configure(struct hda_codec *codec) |
1550 | { | 1570 | { |
1571 | int (*patch)(struct hda_codec *) = NULL; | ||
1551 | int err; | 1572 | int err; |
1552 | 1573 | ||
1553 | codec->preset = find_codec_preset(codec); | 1574 | codec->preset = find_codec_preset(codec); |
@@ -1557,29 +1578,38 @@ int snd_hda_codec_configure(struct hda_codec *codec) | |||
1557 | return err; | 1578 | return err; |
1558 | } | 1579 | } |
1559 | 1580 | ||
1560 | if (is_generic_config(codec)) { | 1581 | if (!is_generic_config(codec) && codec->preset) |
1561 | err = snd_hda_parse_generic_codec(codec); | 1582 | patch = codec->preset->patch; |
1562 | goto patched; | 1583 | if (!patch) { |
1563 | } | 1584 | unload_parser(codec); /* to be sure */ |
1564 | if (codec->preset && codec->preset->patch) { | 1585 | #ifdef CONFIG_SND_HDA_GENERIC |
1565 | err = codec->preset->patch(codec); | 1586 | if (!patch) |
1566 | goto patched; | 1587 | patch = load_parser(codec, snd_hda_parse_generic_codec); |
1588 | #endif | ||
1589 | if (!patch) { | ||
1590 | printk(KERN_ERR "hda-codec: No codec parser is available\n"); | ||
1591 | return -ENODEV; | ||
1592 | } | ||
1567 | } | 1593 | } |
1568 | 1594 | ||
1569 | /* call the default parser */ | 1595 | err = patch(codec); |
1570 | err = snd_hda_parse_generic_codec(codec); | 1596 | if (err < 0) { |
1571 | if (err < 0) | 1597 | unload_parser(codec); |
1572 | printk(KERN_ERR "hda-codec: No codec parser is available\n"); | 1598 | return err; |
1599 | } | ||
1573 | 1600 | ||
1574 | patched: | 1601 | if (codec->patch_ops.unsol_event) { |
1575 | if (!err && codec->patch_ops.unsol_event) | ||
1576 | err = init_unsol_queue(codec->bus); | 1602 | err = init_unsol_queue(codec->bus); |
1603 | if (err < 0) | ||
1604 | return err; | ||
1605 | } | ||
1606 | |||
1577 | /* audio codec should override the mixer name */ | 1607 | /* audio codec should override the mixer name */ |
1578 | if (!err && (codec->afg || !*codec->bus->card->mixername)) | 1608 | if (codec->afg || !*codec->bus->card->mixername) |
1579 | snprintf(codec->bus->card->mixername, | 1609 | snprintf(codec->bus->card->mixername, |
1580 | sizeof(codec->bus->card->mixername), | 1610 | sizeof(codec->bus->card->mixername), |
1581 | "%s %s", codec->vendor_name, codec->chip_name); | 1611 | "%s %s", codec->vendor_name, codec->chip_name); |
1582 | return err; | 1612 | return 0; |
1583 | } | 1613 | } |
1584 | EXPORT_SYMBOL_HDA(snd_hda_codec_configure); | 1614 | EXPORT_SYMBOL_HDA(snd_hda_codec_configure); |
1585 | 1615 | ||
@@ -2610,6 +2640,7 @@ int snd_hda_codec_reset(struct hda_codec *codec) | |||
2610 | codec->preset = NULL; | 2640 | codec->preset = NULL; |
2611 | codec->slave_dig_outs = NULL; | 2641 | codec->slave_dig_outs = NULL; |
2612 | codec->spdif_status_reset = 0; | 2642 | codec->spdif_status_reset = 0; |
2643 | unload_parser(codec); | ||
2613 | module_put(codec->owner); | 2644 | module_put(codec->owner); |
2614 | codec->owner = NULL; | 2645 | codec->owner = NULL; |
2615 | 2646 | ||