[ALSA] HDA: Enable chipset gcap usage
authorTobin Davis <tdavis@dsl-only.net>
Tue, 15 Jan 2008 10:23:55 +0000 (11:23 +0100)
committerJaroslav Kysela <perex@perex.cz>
Thu, 31 Jan 2008 16:29:58 +0000 (17:29 +0100)
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>
sound/pci/hda/hda_intel.c

index 25f35fa..5f2c3ca 100644 (file)
@@ -1708,12 +1708,13 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
 {
        struct azx *chip;
        int err;
+       unsigned short gcap;
        static struct snd_device_ops ops = {
                .dev_free = azx_dev_free,
        };
 
        *rchip = NULL;
-       
+
        err = pci_enable_device(pci);
        if (err < 0)
                return err;
@@ -1775,25 +1776,40 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
        pci_set_master(pci);
        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->azx_dev = kcalloc(chip->num_streams, sizeof(*chip->azx_dev),