diff options
| author | Takashi Iwai <tiwai@suse.de> | 2010-01-27 18:01:53 -0500 |
|---|---|---|
| committer | Takashi Iwai <tiwai@suse.de> | 2010-01-27 18:04:21 -0500 |
| commit | b09f3e78ee7bb69171411b75bd9e771fc7f24749 (patch) | |
| tree | ed4d4f357a805425e19de53b6b3710150482df06 | |
| parent | ccc5df058da70d1c26c72cd1c24072a89998d735 (diff) | |
ALSA: hda - Allow override more fields via patch loader
Allow the override of vendor-id, subsystem-id, revision-id and chip name
via patch loading. Updated the document, too.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
| -rw-r--r-- | Documentation/sound/alsa/HD-Audio.txt | 27 | ||||
| -rw-r--r-- | sound/pci/hda/hda_hwdep.c | 53 |
2 files changed, 65 insertions, 15 deletions
diff --git a/Documentation/sound/alsa/HD-Audio.txt b/Documentation/sound/alsa/HD-Audio.txt index 6325bec06a72..f4dd3bf99d12 100644 --- a/Documentation/sound/alsa/HD-Audio.txt +++ b/Documentation/sound/alsa/HD-Audio.txt | |||
| @@ -452,6 +452,33 @@ Similarly, the lines after `[verb]` are parsed as `init_verbs` | |||
| 452 | sysfs entries, and the lines after `[hint]` are parsed as `hints` | 452 | sysfs entries, and the lines after `[hint]` are parsed as `hints` |
| 453 | sysfs entries, respectively. | 453 | sysfs entries, respectively. |
| 454 | 454 | ||
| 455 | Another example to override the codec vendor id from 0x12345678 to | ||
| 456 | 0xdeadbeef is like below: | ||
| 457 | ------------------------------------------------------------------------ | ||
| 458 | [codec] | ||
| 459 | 0x12345678 0xabcd1234 2 | ||
| 460 | |||
| 461 | [vendor_id] | ||
| 462 | 0xdeadbeef | ||
| 463 | ------------------------------------------------------------------------ | ||
| 464 | |||
| 465 | In the similar way, you can override the codec subsystem_id via | ||
| 466 | `[subsystem_id]`, the revision id via `[revision_id]` line. | ||
| 467 | Also, the codec chip name can be rewritten via `[chip_name]` line. | ||
| 468 | ------------------------------------------------------------------------ | ||
| 469 | [codec] | ||
| 470 | 0x12345678 0xabcd1234 2 | ||
| 471 | |||
| 472 | [subsystem_id] | ||
| 473 | 0xffff1111 | ||
| 474 | |||
| 475 | [revision_id] | ||
| 476 | 0x10 | ||
| 477 | |||
| 478 | [chip_name] | ||
| 479 | My-own NEWS-0002 | ||
| 480 | ------------------------------------------------------------------------ | ||
| 481 | |||
| 455 | The hd-audio driver reads the file via request_firmware(). Thus, | 482 | The hd-audio driver reads the file via request_firmware(). Thus, |
| 456 | a patch file has to be located on the appropriate firmware path, | 483 | a patch file has to be located on the appropriate firmware path, |
| 457 | typically, /lib/firmware. For example, when you pass the option | 484 | typically, /lib/firmware. For example, when you pass the option |
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); |
