diff options
Diffstat (limited to 'sound')
-rw-r--r-- | sound/pci/hda/hda_hwdep.c | 53 |
1 files changed, 38 insertions, 15 deletions
diff --git a/sound/pci/hda/hda_hwdep.c b/sound/pci/hda/hda_hwdep.c index b36919c0d363..a1fc83753cc6 100644 --- a/sound/pci/hda/hda_hwdep.c +++ b/sound/pci/hda/hda_hwdep.c | |||
@@ -625,6 +625,10 @@ enum { | |||
625 | LINE_MODE_PINCFG, | 625 | LINE_MODE_PINCFG, |
626 | LINE_MODE_VERB, | 626 | LINE_MODE_VERB, |
627 | LINE_MODE_HINT, | 627 | LINE_MODE_HINT, |
628 | LINE_MODE_VENDOR_ID, | ||
629 | LINE_MODE_SUBSYSTEM_ID, | ||
630 | LINE_MODE_REVISION_ID, | ||
631 | LINE_MODE_CHIP_NAME, | ||
628 | NUM_LINE_MODES, | 632 | NUM_LINE_MODES, |
629 | }; | 633 | }; |
630 | 634 | ||
@@ -654,53 +658,71 @@ static void parse_codec_mode(char *buf, struct hda_bus *bus, | |||
654 | } | 658 | } |
655 | 659 | ||
656 | /* parse the contents after the other command tags, [pincfg], [verb], | 660 | /* parse the contents after the other command tags, [pincfg], [verb], |
657 | * [hint] and [model] | 661 | * [vendor_id], [subsystem_id], [revision_id], [chip_name], [hint] and [model] |
658 | * just pass to the sysfs helper (only when any codec was specified) | 662 | * just pass to the sysfs helper (only when any codec was specified) |
659 | */ | 663 | */ |
660 | static void parse_pincfg_mode(char *buf, struct hda_bus *bus, | 664 | static void parse_pincfg_mode(char *buf, struct hda_bus *bus, |
661 | struct hda_codec **codecp) | 665 | struct hda_codec **codecp) |
662 | { | 666 | { |
663 | if (!*codecp) | ||
664 | return; | ||
665 | parse_user_pin_configs(*codecp, buf); | 667 | parse_user_pin_configs(*codecp, buf); |
666 | } | 668 | } |
667 | 669 | ||
668 | static void parse_verb_mode(char *buf, struct hda_bus *bus, | 670 | static void parse_verb_mode(char *buf, struct hda_bus *bus, |
669 | struct hda_codec **codecp) | 671 | struct hda_codec **codecp) |
670 | { | 672 | { |
671 | if (!*codecp) | ||
672 | return; | ||
673 | parse_init_verbs(*codecp, buf); | 673 | parse_init_verbs(*codecp, buf); |
674 | } | 674 | } |
675 | 675 | ||
676 | static void parse_hint_mode(char *buf, struct hda_bus *bus, | 676 | static void parse_hint_mode(char *buf, struct hda_bus *bus, |
677 | struct hda_codec **codecp) | 677 | struct hda_codec **codecp) |
678 | { | 678 | { |
679 | if (!*codecp) | ||
680 | return; | ||
681 | parse_hints(*codecp, buf); | 679 | parse_hints(*codecp, buf); |
682 | } | 680 | } |
683 | 681 | ||
684 | static void parse_model_mode(char *buf, struct hda_bus *bus, | 682 | static void parse_model_mode(char *buf, struct hda_bus *bus, |
685 | struct hda_codec **codecp) | 683 | struct hda_codec **codecp) |
686 | { | 684 | { |
687 | if (!*codecp) | ||
688 | return; | ||
689 | kfree((*codecp)->modelname); | 685 | kfree((*codecp)->modelname); |
690 | (*codecp)->modelname = kstrdup(buf, GFP_KERNEL); | 686 | (*codecp)->modelname = kstrdup(buf, GFP_KERNEL); |
691 | } | 687 | } |
692 | 688 | ||
689 | static void parse_chip_name_mode(char *buf, struct hda_bus *bus, | ||
690 | struct hda_codec **codecp) | ||
691 | { | ||
692 | kfree((*codecp)->chip_name); | ||
693 | (*codecp)->chip_name = kstrdup(buf, GFP_KERNEL); | ||
694 | } | ||
695 | |||
696 | #define DEFINE_PARSE_ID_MODE(name) \ | ||
697 | static void parse_##name##_mode(char *buf, struct hda_bus *bus, \ | ||
698 | struct hda_codec **codecp) \ | ||
699 | { \ | ||
700 | unsigned long val; \ | ||
701 | if (!strict_strtoul(buf, 0, &val)) \ | ||
702 | (*codecp)->name = val; \ | ||
703 | } | ||
704 | |||
705 | DEFINE_PARSE_ID_MODE(vendor_id); | ||
706 | DEFINE_PARSE_ID_MODE(subsystem_id); | ||
707 | DEFINE_PARSE_ID_MODE(revision_id); | ||
708 | |||
709 | |||
693 | struct hda_patch_item { | 710 | struct hda_patch_item { |
694 | const char *tag; | 711 | const char *tag; |
695 | void (*parser)(char *buf, struct hda_bus *bus, struct hda_codec **retc); | 712 | void (*parser)(char *buf, struct hda_bus *bus, struct hda_codec **retc); |
713 | int need_codec; | ||
696 | }; | 714 | }; |
697 | 715 | ||
698 | static struct hda_patch_item patch_items[NUM_LINE_MODES] = { | 716 | static struct hda_patch_item patch_items[NUM_LINE_MODES] = { |
699 | [LINE_MODE_CODEC] = { "[codec]", parse_codec_mode }, | 717 | [LINE_MODE_CODEC] = { "[codec]", parse_codec_mode, 0 }, |
700 | [LINE_MODE_MODEL] = { "[model]", parse_model_mode }, | 718 | [LINE_MODE_MODEL] = { "[model]", parse_model_mode, 1 }, |
701 | [LINE_MODE_VERB] = { "[verb]", parse_verb_mode }, | 719 | [LINE_MODE_VERB] = { "[verb]", parse_verb_mode, 1 }, |
702 | [LINE_MODE_PINCFG] = { "[pincfg]", parse_pincfg_mode }, | 720 | [LINE_MODE_PINCFG] = { "[pincfg]", parse_pincfg_mode, 1 }, |
703 | [LINE_MODE_HINT] = { "[hint]", parse_hint_mode }, | 721 | [LINE_MODE_HINT] = { "[hint]", parse_hint_mode, 1 }, |
722 | [LINE_MODE_VENDOR_ID] = { "[vendor_id]", parse_vendor_id_mode, 1 }, | ||
723 | [LINE_MODE_SUBSYSTEM_ID] = { "[subsystem_id]", parse_subsystem_id_mode, 1 }, | ||
724 | [LINE_MODE_REVISION_ID] = { "[revision_id]", parse_revision_id_mode, 1 }, | ||
725 | [LINE_MODE_CHIP_NAME] = { "[chip_name]", parse_chip_name_mode, 1 }, | ||
704 | }; | 726 | }; |
705 | 727 | ||
706 | /* check the line starting with '[' -- change the parser mode accodingly */ | 728 | /* check the line starting with '[' -- change the parser mode accodingly */ |
@@ -783,7 +805,8 @@ int snd_hda_load_patch(struct hda_bus *bus, const char *patch) | |||
783 | continue; | 805 | continue; |
784 | if (*buf == '[') | 806 | if (*buf == '[') |
785 | line_mode = parse_line_mode(buf, bus); | 807 | line_mode = parse_line_mode(buf, bus); |
786 | else if (patch_items[line_mode].parser) | 808 | else if (patch_items[line_mode].parser && |
809 | (codec || !patch_items[line_mode].need_codec)) | ||
787 | patch_items[line_mode].parser(buf, bus, &codec); | 810 | patch_items[line_mode].parser(buf, bus, &codec); |
788 | } | 811 | } |
789 | release_firmware(fw); | 812 | release_firmware(fw); |