aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/hda_codec.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2013-11-18 06:03:56 -0500
committerTakashi Iwai <tiwai@suse.de>2013-11-26 07:42:38 -0500
commitb21bdd0d343c8b2496690283211e27c9af598ed3 (patch)
tree23500f17dae3e8998009078e389f5702572ebbbf /sound/pci/hda/hda_codec.c
parent873ce8ad502cce3ba9295890d52afcce385d4107 (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.c67
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
1343static 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 */
1335static void snd_hda_codec_free(struct hda_codec *codec) 1354static 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 */
1549int snd_hda_codec_configure(struct hda_codec *codec) 1569int 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}
1584EXPORT_SYMBOL_HDA(snd_hda_codec_configure); 1614EXPORT_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