@@ -839,6 +839,43 @@ void snd_hda_apply_fixup(struct hda_codec *codec, int action)
}
EXPORT_SYMBOL_GPL(snd_hda_apply_fixup);
+static bool pin_config_match(struct hda_codec *codec,
+ const struct hda_pintbl *pins)
+{
+ for (; pins->nid; pins++) {
+ u32 def_conf = snd_hda_codec_get_pincfg(codec, pins->nid);
+ if (pins->val != def_conf)
+ return false;
+ }
+ return true;
+}
+
+void snd_hda_pick_pin_fixup(struct hda_codec *codec,
+ const struct snd_hda_pin_quirk *pin_quirk,
+ const struct hda_fixup *fixlist)
+{
+ const struct snd_hda_pin_quirk *pq;
+
+ if (codec->fixup_forced)
+ return;
+
+ for (pq = pin_quirk; pq->subvendor; pq++) {
+ if (codec->bus->pci->subsystem_vendor != pq->subvendor)
+ continue;
+ if (codec->vendor_id != pq->codec)
+ continue;
+ if (pin_config_match(codec, pq->pins)) {
+ codec->fixup_id = pq->value;
+#ifdef CONFIG_SND_DEBUG_VERBOSE
+ codec->fixup_name = pq->name;
+#endif
+ codec->fixup_list = fixlist;
+ return;
+ }
+ }
+}
+EXPORT_SYMBOL_GPL(snd_hda_pick_pin_fixup);
+
void snd_hda_pick_fixup(struct hda_codec *codec,
const struct hda_model_fixup *models,
const struct snd_pci_quirk *quirk,
@@ -407,6 +407,16 @@ struct hda_fixup {
} v;
};
+struct snd_hda_pin_quirk {
+ unsigned int codec; /* Codec vendor/device ID */
+ unsigned short subvendor; /* PCI subvendor ID */
+ const struct hda_pintbl *pins; /* list of matching pins */
+#ifdef CONFIG_SND_DEBUG_VERBOSE
+ const char *name;
+#endif
+ int value; /* quirk value */
+};
+
/* fixup types */
enum {
HDA_FIXUP_INVALID,
@@ -434,6 +444,10 @@ void snd_hda_pick_fixup(struct hda_codec *codec,
const struct hda_model_fixup *models,
const struct snd_pci_quirk *quirk,
const struct hda_fixup *fixlist);
+void snd_hda_pick_pin_fixup(struct hda_codec *codec,
+ const struct snd_hda_pin_quirk *pin_quirk,
+ const struct hda_fixup *fixlist);
+
/*
* unsolicited event handler