Commit 5b1913a7 authored by Takashi Iwai's avatar Takashi Iwai
Browse files

ALSA: hda: Use own quirk lookup helper



For allowing the primary codec SSID matching (that works around the
conflicting PCI SSID problems), introduce a new struct hda_quirk,
which is compatible with the existing struct snd_pci_quirk along with
new helper functions and macros.

The existing snd_pci_quirk tables are replaced with hda_quirk tables
accordingly, while keeping SND_PCI_QUIRK() entry definitions as is.

This patch shouldn't bring any behavior change, just some renaming and
shifting the code.  The actual change for the codec SSID matching will
follow after this.

Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
Link: https://patch.msgid.link/20241008120233.7154-2-tiwai@suse.de
parent 1ceb43eb
Loading
Loading
Loading
Loading
+50 −11
Original line number Diff line number Diff line
@@ -956,6 +956,28 @@ void snd_hda_pick_pin_fixup(struct hda_codec *codec,
}
EXPORT_SYMBOL_GPL(snd_hda_pick_pin_fixup);

/* check whether the given quirk entry matches with vendor/device pair */
static bool hda_quirk_match(u16 vendor, u16 device, const struct hda_quirk *q)
{
	if (q->subvendor != vendor)
		return false;
	return !q->subdevice ||
		(device & q->subdevice_mask) == q->subdevice;
}

/* look through the quirk list and return the matching entry */
static const struct hda_quirk *
hda_quirk_lookup_id(u16 vendor, u16 device, const struct hda_quirk *list)
{
	const struct hda_quirk *q;

	for (q = list; q->subvendor || q->subdevice; q++) {
		if (hda_quirk_match(vendor, device, q))
			return q;
	}
	return NULL;
}

/**
 * snd_hda_pick_fixup - Pick up a fixup matching with PCI/codec SSID or model string
 * @codec: the HDA codec
@@ -975,14 +997,16 @@ 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,
			const struct hda_quirk *quirk,
			const struct hda_fixup *fixlist)
{
	const struct snd_pci_quirk *q;
	const struct hda_quirk *q;
	int id = HDA_FIXUP_ID_NOT_SET;
	const char *name = NULL;
	const char *type = NULL;
	unsigned int vendor, device;
	u16 pci_vendor, pci_device;
	u16 codec_vendor, codec_device;

	if (codec->fixup_id != HDA_FIXUP_ID_NOT_SET)
		return;
@@ -1013,27 +1037,42 @@ void snd_hda_pick_fixup(struct hda_codec *codec,
	if (!quirk)
		return;

	if (codec->bus->pci) {
		pci_vendor = codec->bus->pci->subsystem_vendor;
		pci_device = codec->bus->pci->subsystem_device;
	}

	codec_vendor = codec->core.subsystem_id >> 16;
	codec_device = codec->core.subsystem_id & 0xffff;

	/* match with the SSID alias given by the model string "XXXX:YYYY" */
	if (codec->modelname &&
	    sscanf(codec->modelname, "%04x:%04x", &vendor, &device) == 2) {
		q = snd_pci_quirk_lookup_id(vendor, device, quirk);
		q = hda_quirk_lookup_id(vendor, device, quirk);
		if (q) {
			type = "alias SSID";
			goto found_device;
		}
	}

	/* match with the PCI SSID */
	q = snd_pci_quirk_lookup(codec->bus->pci, quirk);
	if (q) {
	/* match primarily with the PCI SSID */
	for (q = quirk; q->subvendor || q->subdevice; q++) {
		/* if the entry is specific to codec SSID, check with it */
		if (!codec->bus->pci || q->match_codec_ssid) {
			if (hda_quirk_match(codec_vendor, codec_device, q)) {
				type = "codec SSID";
				goto found_device;
			}
		} else {
			if (hda_quirk_match(pci_vendor, pci_device, q)) {
				type = "PCI SSID";
				goto found_device;
			}
		}
	}

	/* match with the codec SSID */
	q = snd_pci_quirk_lookup_id(codec->core.subsystem_id >> 16,
				    codec->core.subsystem_id & 0xffff,
				    quirk);
	q = hda_quirk_lookup_id(codec_vendor, codec_device, quirk);
	if (q) {
		type = "codec SSID";
		goto found_device;
+21 −1
Original line number Diff line number Diff line
@@ -292,6 +292,26 @@ struct hda_fixup {
	} v;
};

/*
 * extended form of snd_pci_quirk:
 * for PCI SSID matching, use SND_PCI_QUIRK() like before;
 * for codec SSID matching, use the new HDA_CODEC_QUIRK() instead
 */
struct hda_quirk {
	unsigned short subvendor;	/* PCI subvendor ID */
	unsigned short subdevice;	/* PCI subdevice ID */
	unsigned short subdevice_mask;	/* bitmask to match */
	bool match_codec_ssid;		/* match only with codec SSID */
	int value;			/* value */
#ifdef CONFIG_SND_DEBUG_VERBOSE
	const char *name;		/* name of the device (optional) */
#endif
};

#define HDA_CODEC_QUIRK(vend, dev, xname, val) \
	{ _SND_PCI_QUIRK_ID(vend, dev), .value = (val), .name = (xname),\
			.match_codec_ssid = true }

struct snd_hda_pin_quirk {
	unsigned int codec;             /* Codec vendor/device ID */
	unsigned short subvendor;	/* PCI subvendor ID */
@@ -351,7 +371,7 @@ void snd_hda_apply_fixup(struct hda_codec *codec, int action);
void __snd_hda_apply_fixup(struct hda_codec *codec, int id, int action, int depth);
void snd_hda_pick_fixup(struct hda_codec *codec,
			const struct hda_model_fixup *models,
			const struct snd_pci_quirk *quirk,
			const struct hda_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,
+3 −3
Original line number Diff line number Diff line
@@ -345,7 +345,7 @@ static const struct hda_fixup ad1986a_fixups[] = {
	},
};

static const struct snd_pci_quirk ad1986a_fixup_tbl[] = {
static const struct hda_quirk ad1986a_fixup_tbl[] = {
	SND_PCI_QUIRK(0x103c, 0x30af, "HP B2800", AD1986A_FIXUP_LAPTOP_IMIC),
	SND_PCI_QUIRK(0x1043, 0x1153, "ASUS M9V", AD1986A_FIXUP_LAPTOP_IMIC),
	SND_PCI_QUIRK(0x1043, 0x1443, "ASUS Z99He", AD1986A_FIXUP_EAPD),
@@ -588,7 +588,7 @@ static const struct hda_fixup ad1981_fixups[] = {
	},
};

static const struct snd_pci_quirk ad1981_fixup_tbl[] = {
static const struct hda_quirk ad1981_fixup_tbl[] = {
	SND_PCI_QUIRK_VENDOR(0x1014, "Lenovo", AD1981_FIXUP_AMP_OVERRIDE),
	SND_PCI_QUIRK_VENDOR(0x103c, "HP", AD1981_FIXUP_HP_EAPD),
	SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo", AD1981_FIXUP_AMP_OVERRIDE),
@@ -1061,7 +1061,7 @@ static const struct hda_fixup ad1884_fixups[] = {
	},
};

static const struct snd_pci_quirk ad1884_fixup_tbl[] = {
static const struct hda_quirk ad1884_fixup_tbl[] = {
	SND_PCI_QUIRK(0x103c, 0x2a82, "HP Touchsmart", AD1884_FIXUP_HP_TOUCHSMART),
	SND_PCI_QUIRK_VENDOR(0x103c, "HP", AD1884_FIXUP_HP_EAPD),
	SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo Thinkpad", AD1884_FIXUP_THINKPAD),
+4 −4
Original line number Diff line number Diff line
@@ -385,7 +385,7 @@ static const struct hda_model_fixup cs420x_models[] = {
	{}
};

static const struct snd_pci_quirk cs420x_fixup_tbl[] = {
static const struct hda_quirk cs420x_fixup_tbl[] = {
	SND_PCI_QUIRK(0x10de, 0x0ac0, "MacBookPro 5,3", CS420X_MBP53),
	SND_PCI_QUIRK(0x10de, 0x0d94, "MacBookAir 3,1(2)", CS420X_MBP55),
	SND_PCI_QUIRK(0x10de, 0xcb79, "MacBookPro 5,5", CS420X_MBP55),
@@ -634,13 +634,13 @@ static const struct hda_model_fixup cs4208_models[] = {
	{}
};

static const struct snd_pci_quirk cs4208_fixup_tbl[] = {
static const struct hda_quirk cs4208_fixup_tbl[] = {
	SND_PCI_QUIRK_VENDOR(0x106b, "Apple", CS4208_MAC_AUTO),
	{} /* terminator */
};

/* codec SSID matching */
static const struct snd_pci_quirk cs4208_mac_fixup_tbl[] = {
static const struct hda_quirk cs4208_mac_fixup_tbl[] = {
	SND_PCI_QUIRK(0x106b, 0x5e00, "MacBookPro 11,2", CS4208_MBP11),
	SND_PCI_QUIRK(0x106b, 0x6c00, "MacMini 7,1", CS4208_MACMINI),
	SND_PCI_QUIRK(0x106b, 0x7100, "MacBookAir 6,1", CS4208_MBA6),
@@ -818,7 +818,7 @@ static const struct hda_model_fixup cs421x_models[] = {
	{}
};

static const struct snd_pci_quirk cs421x_fixup_tbl[] = {
static const struct hda_quirk cs421x_fixup_tbl[] = {
	/* Test Intel board + CDB2410  */
	SND_PCI_QUIRK(0x8086, 0x5001, "DP45SG/CDB4210", CS421X_CDB4210),
	{} /* terminator */
+4 −4
Original line number Diff line number Diff line
@@ -998,7 +998,7 @@ static const struct hda_fixup cxt_fixups[] = {
	},
};

static const struct snd_pci_quirk cxt5045_fixups[] = {
static const struct hda_quirk cxt5045_fixups[] = {
	SND_PCI_QUIRK(0x103c, 0x30d5, "HP 530", CXT_FIXUP_HP_530),
	SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba P105", CXT_FIXUP_TOSHIBA_P105),
	/* HP, Packard Bell, Fujitsu-Siemens & Lenovo laptops have
@@ -1018,7 +1018,7 @@ static const struct hda_model_fixup cxt5045_fixup_models[] = {
	{}
};

static const struct snd_pci_quirk cxt5047_fixups[] = {
static const struct hda_quirk cxt5047_fixups[] = {
	/* HP laptops have really bad sound over 0 dB on NID 0x10.
	 */
	SND_PCI_QUIRK_VENDOR(0x103c, "HP", CXT_FIXUP_CAP_MIX_AMP_5047),
@@ -1030,7 +1030,7 @@ static const struct hda_model_fixup cxt5047_fixup_models[] = {
	{}
};

static const struct snd_pci_quirk cxt5051_fixups[] = {
static const struct hda_quirk cxt5051_fixups[] = {
	SND_PCI_QUIRK(0x103c, 0x360b, "Compaq CQ60", CXT_PINCFG_COMPAQ_CQ60),
	SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo X200", CXT_PINCFG_LENOVO_X200),
	{}
@@ -1041,7 +1041,7 @@ static const struct hda_model_fixup cxt5051_fixup_models[] = {
	{}
};

static const struct snd_pci_quirk cxt5066_fixups[] = {
static const struct hda_quirk cxt5066_fixups[] = {
	SND_PCI_QUIRK(0x1025, 0x0543, "Acer Aspire One 522", CXT_FIXUP_STEREO_DMIC),
	SND_PCI_QUIRK(0x1025, 0x054c, "Acer Aspire 3830TG", CXT_FIXUP_ASPIRE_DMIC),
	SND_PCI_QUIRK(0x1025, 0x054f, "Acer Aspire 4830T", CXT_FIXUP_ASPIRE_DMIC),
Loading