فهرست منبع

[ALSA] HDA: Enable chipset gcap usage

This patch removes hardcoded values for the number of streams supported
by the southbridge in most chipsets, and reads these values from the
chipset directly.  Most systems are hardwired for 4 streams in each
direction, but newer chipsets change that capability.

Signed-off-by: Tobin Davis <tdavis@dsl-only.net>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
Tobin Davis 17 سال پیش
والد
کامیت
bcd7200394
1فایلهای تغییر یافته به همراه36 افزوده شده و 20 حذف شده
  1. 36 20
      sound/pci/hda/hda_intel.c

+ 36 - 20
sound/pci/hda/hda_intel.c

@@ -1708,12 +1708,13 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
 {
 {
 	struct azx *chip;
 	struct azx *chip;
 	int err;
 	int err;
+	unsigned short gcap;
 	static struct snd_device_ops ops = {
 	static struct snd_device_ops ops = {
 		.dev_free = azx_dev_free,
 		.dev_free = azx_dev_free,
 	};
 	};
 
 
 	*rchip = NULL;
 	*rchip = NULL;
-	
+
 	err = pci_enable_device(pci);
 	err = pci_enable_device(pci);
 	if (err < 0)
 	if (err < 0)
 		return err;
 		return err;
@@ -1775,25 +1776,40 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
 	pci_set_master(pci);
 	pci_set_master(pci);
 	synchronize_irq(chip->irq);
 	synchronize_irq(chip->irq);
 
 
-	switch (chip->driver_type) {
-	case AZX_DRIVER_ULI:
-		chip->playback_streams = ULI_NUM_PLAYBACK;
-		chip->capture_streams = ULI_NUM_CAPTURE;
-		chip->playback_index_offset = ULI_PLAYBACK_INDEX;
-		chip->capture_index_offset = ULI_CAPTURE_INDEX;
-		break;
-	case AZX_DRIVER_ATIHDMI:
-		chip->playback_streams = ATIHDMI_NUM_PLAYBACK;
-		chip->capture_streams = ATIHDMI_NUM_CAPTURE;
-		chip->playback_index_offset = ATIHDMI_PLAYBACK_INDEX;
-		chip->capture_index_offset = ATIHDMI_CAPTURE_INDEX;
-		break;
-	default:
-		chip->playback_streams = ICH6_NUM_PLAYBACK;
-		chip->capture_streams = ICH6_NUM_CAPTURE;
-		chip->playback_index_offset = ICH6_PLAYBACK_INDEX;
-		chip->capture_index_offset = ICH6_CAPTURE_INDEX;
-		break;
+	gcap = azx_readw(chip, GCAP);
+	snd_printdd("chipset global capabilities = 0x%x\n", gcap);
+
+	if (gcap) {
+		/* read number of streams from GCAP register instead of using
+		 * hardcoded value
+		 */
+		chip->playback_streams = (gcap & (0xF << 12)) >> 12;
+		chip->capture_streams = (gcap & (0xF << 8)) >> 8;
+		chip->playback_index_offset = (gcap & (0xF << 12)) >> 12;
+		chip->capture_index_offset = 0;
+	} else {
+		/* gcap didn't give any info, switching to old method */
+
+		switch (chip->driver_type) {
+		case AZX_DRIVER_ULI:
+			chip->playback_streams = ULI_NUM_PLAYBACK;
+			chip->capture_streams = ULI_NUM_CAPTURE;
+			chip->playback_index_offset = ULI_PLAYBACK_INDEX;
+			chip->capture_index_offset = ULI_CAPTURE_INDEX;
+			break;
+		case AZX_DRIVER_ATIHDMI:
+			chip->playback_streams = ATIHDMI_NUM_PLAYBACK;
+			chip->capture_streams = ATIHDMI_NUM_CAPTURE;
+			chip->playback_index_offset = ATIHDMI_PLAYBACK_INDEX;
+			chip->capture_index_offset = ATIHDMI_CAPTURE_INDEX;
+			break;
+		default:
+			chip->playback_streams = ICH6_NUM_PLAYBACK;
+			chip->capture_streams = ICH6_NUM_CAPTURE;
+			chip->playback_index_offset = ICH6_PLAYBACK_INDEX;
+			chip->capture_index_offset = ICH6_CAPTURE_INDEX;
+			break;
+		}
 	}
 	}
 	chip->num_streams = chip->playback_streams + chip->capture_streams;
 	chip->num_streams = chip->playback_streams + chip->capture_streams;
 	chip->azx_dev = kcalloc(chip->num_streams, sizeof(*chip->azx_dev),
 	chip->azx_dev = kcalloc(chip->num_streams, sizeof(*chip->azx_dev),