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 | |
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>
-rw-r--r-- | sound/pci/hda/Makefile | 5 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.c | 67 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.h | 1 | ||||
-rw-r--r-- | sound/pci/hda/hda_generic.c | 4 | ||||
-rw-r--r-- | sound/pci/hda/hda_local.h | 7 |
5 files changed, 58 insertions, 26 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..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 | ||
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 7aa9870040c1..14e4b5a9c43c 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -834,6 +834,7 @@ struct hda_codec { | |||
834 | /* detected preset */ | 834 | /* detected preset */ |
835 | const struct hda_codec_preset *preset; | 835 | const struct hda_codec_preset *preset; |
836 | struct module *owner; | 836 | struct module *owner; |
837 | int (*parser)(struct hda_codec *codec); | ||
837 | const char *vendor_name; /* codec vendor name */ | 838 | const char *vendor_name; /* codec vendor name */ |
838 | const char *chip_name; /* codec chip name */ | 839 | const char *chip_name; /* codec chip name */ |
839 | const char *modelname; /* model name for preset */ | 840 | const char *modelname; /* model name for preset */ |
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_local.h b/sound/pci/hda/hda_local.h index d398b648bb5d..4d571a6d9230 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h | |||
@@ -352,14 +352,7 @@ 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 | ||
358 | static inline int snd_hda_parse_generic_codec(struct hda_codec *codec) | ||
359 | { | ||
360 | return -ENODEV; | ||
361 | } | ||
362 | #endif | ||
363 | 356 | ||
364 | /* | 357 | /* |
365 | * generic proc interface | 358 | * generic proc interface |