hda_auto_parser.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. /*
  2. * BIOS auto-parser helper functions for HD-audio
  3. *
  4. * Copyright (c) 2012 Takashi Iwai <tiwai@suse.de>
  5. *
  6. * This driver is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. */
  11. #include <linux/slab.h>
  12. #include <linux/export.h>
  13. #include <sound/core.h>
  14. #include "hda_codec.h"
  15. #include "hda_auto_parser.h"
  16. #define SFX "hda_codec: "
  17. int snd_hda_gen_add_verbs(struct hda_gen_spec *spec,
  18. const struct hda_verb *list)
  19. {
  20. const struct hda_verb **v;
  21. snd_array_init(&spec->verbs, sizeof(struct hda_verb *), 8);
  22. v = snd_array_new(&spec->verbs);
  23. if (!v)
  24. return -ENOMEM;
  25. *v = list;
  26. return 0;
  27. }
  28. EXPORT_SYMBOL_HDA(snd_hda_gen_add_verbs);
  29. void snd_hda_gen_apply_verbs(struct hda_codec *codec)
  30. {
  31. struct hda_gen_spec *spec = codec->spec;
  32. int i;
  33. for (i = 0; i < spec->verbs.used; i++) {
  34. struct hda_verb **v = snd_array_elem(&spec->verbs, i);
  35. snd_hda_sequence_write(codec, *v);
  36. }
  37. }
  38. EXPORT_SYMBOL_HDA(snd_hda_gen_apply_verbs);
  39. void snd_hda_apply_pincfgs(struct hda_codec *codec,
  40. const struct hda_pintbl *cfg)
  41. {
  42. for (; cfg->nid; cfg++)
  43. snd_hda_codec_set_pincfg(codec, cfg->nid, cfg->val);
  44. }
  45. EXPORT_SYMBOL_HDA(snd_hda_apply_pincfgs);
  46. void snd_hda_apply_fixup(struct hda_codec *codec, int action)
  47. {
  48. struct hda_gen_spec *spec = codec->spec;
  49. int id = spec->fixup_id;
  50. #ifdef CONFIG_SND_DEBUG_VERBOSE
  51. const char *modelname = spec->fixup_name;
  52. #endif
  53. int depth = 0;
  54. if (!spec->fixup_list)
  55. return;
  56. while (id >= 0) {
  57. const struct hda_fixup *fix = spec->fixup_list + id;
  58. switch (fix->type) {
  59. case HDA_FIXUP_PINS:
  60. if (action != HDA_FIXUP_ACT_PRE_PROBE || !fix->v.pins)
  61. break;
  62. snd_printdd(KERN_INFO SFX
  63. "%s: Apply pincfg for %s\n",
  64. codec->chip_name, modelname);
  65. snd_hda_apply_pincfgs(codec, fix->v.pins);
  66. break;
  67. case HDA_FIXUP_VERBS:
  68. if (action != HDA_FIXUP_ACT_PROBE || !fix->v.verbs)
  69. break;
  70. snd_printdd(KERN_INFO SFX
  71. "%s: Apply fix-verbs for %s\n",
  72. codec->chip_name, modelname);
  73. snd_hda_gen_add_verbs(codec->spec, fix->v.verbs);
  74. break;
  75. case HDA_FIXUP_FUNC:
  76. if (!fix->v.func)
  77. break;
  78. snd_printdd(KERN_INFO SFX
  79. "%s: Apply fix-func for %s\n",
  80. codec->chip_name, modelname);
  81. fix->v.func(codec, fix, action);
  82. break;
  83. default:
  84. snd_printk(KERN_ERR SFX
  85. "%s: Invalid fixup type %d\n",
  86. codec->chip_name, fix->type);
  87. break;
  88. }
  89. if (!fix->chained)
  90. break;
  91. if (++depth > 10)
  92. break;
  93. id = fix->chain_id;
  94. }
  95. }
  96. EXPORT_SYMBOL_HDA(snd_hda_apply_fixup);
  97. void snd_hda_pick_fixup(struct hda_codec *codec,
  98. const struct hda_model_fixup *models,
  99. const struct snd_pci_quirk *quirk,
  100. const struct hda_fixup *fixlist)
  101. {
  102. struct hda_gen_spec *spec = codec->spec;
  103. const struct snd_pci_quirk *q;
  104. int id = -1;
  105. const char *name = NULL;
  106. /* when model=nofixup is given, don't pick up any fixups */
  107. if (codec->modelname && !strcmp(codec->modelname, "nofixup")) {
  108. spec->fixup_list = NULL;
  109. spec->fixup_id = -1;
  110. return;
  111. }
  112. if (codec->modelname && models) {
  113. while (models->name) {
  114. if (!strcmp(codec->modelname, models->name)) {
  115. id = models->id;
  116. name = models->name;
  117. break;
  118. }
  119. models++;
  120. }
  121. }
  122. if (id < 0) {
  123. q = snd_pci_quirk_lookup(codec->bus->pci, quirk);
  124. if (q) {
  125. id = q->value;
  126. #ifdef CONFIG_SND_DEBUG_VERBOSE
  127. name = q->name;
  128. #endif
  129. }
  130. }
  131. if (id < 0) {
  132. for (q = quirk; q->subvendor; q++) {
  133. unsigned int vendorid =
  134. q->subdevice | (q->subvendor << 16);
  135. if (vendorid == codec->subsystem_id) {
  136. id = q->value;
  137. #ifdef CONFIG_SND_DEBUG_VERBOSE
  138. name = q->name;
  139. #endif
  140. break;
  141. }
  142. }
  143. }
  144. spec->fixup_id = id;
  145. if (id >= 0) {
  146. spec->fixup_list = fixlist;
  147. spec->fixup_name = name;
  148. }
  149. }
  150. EXPORT_SYMBOL_HDA(snd_hda_pick_fixup);