ALSA: ctxfi - Add subsystem option

Added a new option "subsystem" to override the PCI SSID for identifying
the card type.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index c540637..c83fd7b 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -482,6 +482,9 @@
 
     reference_rate	- reference sample rate, 44100 or 48000 (default)
     multiple		- multiple to ref. sample rate, 1 or 2 (default)
+    subsystem		- override the PCI SSID for probing; the value
+			  consists of SSVID << 16 | SSDID.  The default is
+			  zero, which means no override.
 
     This module supports multiple cards.
 
diff --git a/sound/pci/ctxfi/ctatc.c b/sound/pci/ctxfi/ctatc.c
index cb65bd0..903594e 100644
--- a/sound/pci/ctxfi/ctatc.c
+++ b/sound/pci/ctxfi/ctatc.c
@@ -1225,10 +1225,11 @@
 	return ct_atc_destroy(atc);
 }
 
-static int __devinit atc_identify_card(struct ct_atc *atc)
+static int __devinit atc_identify_card(struct ct_atc *atc, unsigned int ssid)
 {
 	const struct snd_pci_quirk *p;
 	const struct snd_pci_quirk *list;
+	u16 vendor_id, device_id;
 
 	switch (atc->chip_type) {
 	case ATC20K1:
@@ -1242,13 +1243,19 @@
 	default:
 		return -ENOENT;
 	}
-	p = snd_pci_quirk_lookup(atc->pci, list);
+	if (ssid) {
+		vendor_id = ssid >> 16;
+		device_id = ssid & 0xffff;
+	} else {
+		vendor_id = atc->pci->subsystem_vendor;
+		device_id = atc->pci->subsystem_device;
+	}
+	p = snd_pci_quirk_lookup_id(vendor_id, device_id, list);
 	if (p) {
 		if (p->value < 0) {
 			printk(KERN_ERR "ctxfi: "
 			       "Device %04x:%04x is black-listed\n",
-			       atc->pci->subsystem_vendor,
-			       atc->pci->subsystem_device);
+			       vendor_id, device_id);
 			return -ENOENT;
 		}
 		atc->model = p->value;
@@ -1261,8 +1268,7 @@
 	atc->model_name = ct_subsys_name[atc->model];
 	snd_printd("ctxfi: chip %s model %s (%04x:%04x) is found\n",
 		   atc->chip_name, atc->model_name,
-		   atc->pci->subsystem_vendor,
-		   atc->pci->subsystem_device);
+		   vendor_id, device_id);
 	return 0;
 }
 
@@ -1636,7 +1642,8 @@
 
 int __devinit ct_atc_create(struct snd_card *card, struct pci_dev *pci,
 			    unsigned int rsr, unsigned int msr,
-			    int chip_type, struct ct_atc **ratc)
+			    int chip_type, unsigned int ssid,
+			    struct ct_atc **ratc)
 {
 	struct ct_atc *atc;
 	static struct snd_device_ops ops = {
@@ -1662,7 +1669,7 @@
 	mutex_init(&atc->atc_mutex);
 
 	/* Find card model */
-	err = atc_identify_card(atc);
+	err = atc_identify_card(atc, ssid);
 	if (err < 0) {
 		printk(KERN_ERR "ctatc: Card not recognised\n");
 		goto error1;
diff --git a/sound/pci/ctxfi/ctatc.h b/sound/pci/ctxfi/ctatc.h
index 9fd8a57..7167c01 100644
--- a/sound/pci/ctxfi/ctatc.h
+++ b/sound/pci/ctxfi/ctatc.h
@@ -148,7 +148,7 @@
 
 int __devinit ct_atc_create(struct snd_card *card, struct pci_dev *pci,
 			    unsigned int rsr, unsigned int msr, int chip_type,
-			    struct ct_atc **ratc);
+			    unsigned int subsysid, struct ct_atc **ratc);
 int __devinit ct_atc_create_alsa_devs(struct ct_atc *atc);
 
 #endif /* CTATC_H */
diff --git a/sound/pci/ctxfi/xfi.c b/sound/pci/ctxfi/xfi.c
index 7654174..ed44ed7 100644
--- a/sound/pci/ctxfi/xfi.c
+++ b/sound/pci/ctxfi/xfi.c
@@ -32,6 +32,7 @@
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
 static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+static unsigned int subsystem[SNDRV_CARDS];
 
 module_param_array(index, int, NULL, 0444);
 MODULE_PARM_DESC(index, "Index value for Creative X-Fi driver");
@@ -39,6 +40,8 @@
 MODULE_PARM_DESC(id, "ID string for Creative X-Fi driver");
 module_param_array(enable, bool, NULL, 0444);
 MODULE_PARM_DESC(enable, "Enable Creative X-Fi driver");
+module_param_array(subsystem, int, NULL, 0444);
+MODULE_PARM_DESC(subsystem, "Override subsystem ID for Creative X-Fi driver");
 
 static struct pci_device_id ct_pci_dev_ids[] = {
 	/* only X-Fi is supported, so... */
@@ -85,7 +88,7 @@
 		multiple = 2;
 	}
 	err = ct_atc_create(card, pci, reference_rate, multiple,
-			    pci_id->driver_data, &atc);
+			    pci_id->driver_data, subsystem[dev], &atc);
 	if (err < 0)
 		goto error;