diff options
Diffstat (limited to 'sound/pci/hda/hda_intel.c')
-rw-r--r-- | sound/pci/hda/hda_intel.c | 106 |
1 files changed, 70 insertions, 36 deletions
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 06fe2c546ee4..0852e204a4c8 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -407,6 +407,14 @@ struct azx_rb { u32 res[AZX_MAX_CODECS]; /* last read value */ }; +struct azx_pcm { + struct azx *chip; + struct snd_pcm *pcm; + struct hda_codec *codec; + struct hda_pcm_stream *hinfo[2]; + struct list_head list; +}; + struct azx { struct snd_card *card; struct pci_dev *pci; @@ -434,7 +442,7 @@ struct azx { struct azx_dev *azx_dev; /* PCM */ - struct snd_pcm *pcm[HDA_MAX_PCMS]; + struct list_head pcm_list; /* azx_pcm list */ /* HD codec */ unsigned short codec_mask; @@ -479,6 +487,7 @@ enum { AZX_DRIVER_SCH, AZX_DRIVER_ATI, AZX_DRIVER_ATIHDMI, + AZX_DRIVER_ATIHDMI_NS, AZX_DRIVER_VIA, AZX_DRIVER_SIS, AZX_DRIVER_ULI, @@ -525,6 +534,7 @@ static char *driver_short_names[] __devinitdata = { [AZX_DRIVER_SCH] = "HDA Intel MID", [AZX_DRIVER_ATI] = "HDA ATI SB", [AZX_DRIVER_ATIHDMI] = "HDA ATI HDMI", + [AZX_DRIVER_ATIHDMI_NS] = "HDA ATI HDMI", [AZX_DRIVER_VIA] = "HDA VIA VT82xx", [AZX_DRIVER_SIS] = "HDA SIS966", [AZX_DRIVER_ULI] = "HDA ULI M5461", @@ -1143,16 +1153,6 @@ static void update_pci_byte(struct pci_dev *pci, unsigned int reg, static void azx_init_pci(struct azx *chip) { - /* force to non-snoop mode for a new VIA controller when BIOS is set */ - if (chip->snoop && chip->driver_type == AZX_DRIVER_VIA) { - u8 snoop; - pci_read_config_byte(chip->pci, 0x42, &snoop); - if (!(snoop & 0x80) && chip->pci->revision == 0x30) { - chip->snoop = 0; - snd_printdd(SFX "Force to non-snoop mode\n"); - } - } - /* Clear bits 0-2 of PCI register TCSEL (at offset 0x44) * TCSEL == Traffic Class Select Register, which sets PCI express QOS * Ensuring these bits are 0 clears playback static on some HD Audio @@ -1486,10 +1486,9 @@ static void azx_bus_reset(struct hda_bus *bus) azx_init_chip(chip, 1); #ifdef CONFIG_PM if (chip->initialized) { - int i; - - for (i = 0; i < HDA_MAX_PCMS; i++) - snd_pcm_suspend_all(chip->pcm[i]); + struct azx_pcm *p; + list_for_each_entry(p, &chip->pcm_list, list) + snd_pcm_suspend_all(p->pcm); snd_hda_suspend(chip->bus); snd_hda_resume(chip->bus); } @@ -1667,12 +1666,6 @@ static struct snd_pcm_hardware azx_pcm_hw = { .fifo_size = 0, }; -struct azx_pcm { - struct azx *chip; - struct hda_codec *codec; - struct hda_pcm_stream *hinfo[2]; -}; - static int azx_pcm_open(struct snd_pcm_substream *substream) { struct azx_pcm *apcm = snd_pcm_substream_chip(substream); @@ -2197,7 +2190,7 @@ static void azx_pcm_free(struct snd_pcm *pcm) { struct azx_pcm *apcm = pcm->private_data; if (apcm) { - apcm->chip->pcm[pcm->device] = NULL; + list_del(&apcm->list); kfree(apcm); } } @@ -2215,14 +2208,11 @@ azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec, unsigned int size; int s, err; - if (pcm_dev >= HDA_MAX_PCMS) { - snd_printk(KERN_ERR SFX "Invalid PCM device number %d\n", - pcm_dev); - return -EINVAL; - } - if (chip->pcm[pcm_dev]) { - snd_printk(KERN_ERR SFX "PCM %d already exists\n", pcm_dev); - return -EBUSY; + list_for_each_entry(apcm, &chip->pcm_list, list) { + if (apcm->pcm->device == pcm_dev) { + snd_printk(KERN_ERR SFX "PCM %d already exists\n", pcm_dev); + return -EBUSY; + } } err = snd_pcm_new(chip->card, cpcm->name, pcm_dev, cpcm->stream[SNDRV_PCM_STREAM_PLAYBACK].substreams, @@ -2235,12 +2225,13 @@ azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec, if (apcm == NULL) return -ENOMEM; apcm->chip = chip; + apcm->pcm = pcm; apcm->codec = codec; pcm->private_data = apcm; pcm->private_free = azx_pcm_free; if (cpcm->pcm_type == HDA_PCM_TYPE_MODEM) pcm->dev_class = SNDRV_PCM_CLASS_MODEM; - chip->pcm[pcm_dev] = pcm; + list_add_tail(&apcm->list, &chip->pcm_list); cpcm->pcm = pcm; for (s = 0; s < 2; s++) { apcm->hinfo[s] = &cpcm->stream[s]; @@ -2370,12 +2361,12 @@ static int azx_suspend(struct pci_dev *pci, pm_message_t state) { struct snd_card *card = pci_get_drvdata(pci); struct azx *chip = card->private_data; - int i; + struct azx_pcm *p; snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); azx_clear_irq_pending(chip); - for (i = 0; i < HDA_MAX_PCMS; i++) - snd_pcm_suspend_all(chip->pcm[i]); + list_for_each_entry(p, &chip->pcm_list, list) + snd_pcm_suspend_all(p->pcm); if (chip->initialized) snd_hda_suspend(chip->bus); azx_stop_chip(chip); @@ -2502,7 +2493,6 @@ static int azx_dev_free(struct snd_device *device) static struct snd_pci_quirk position_fix_list[] __devinitdata = { SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB), SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB), - SND_PCI_QUIRK(0x1028, 0x02c6, "Dell Inspiron 1010", POS_FIX_LPIB), SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB), SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB), SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS", POS_FIX_LPIB), @@ -2633,6 +2623,35 @@ static void __devinit check_msi(struct azx *chip) } } +/* check the snoop mode availability */ +static void __devinit azx_check_snoop_available(struct azx *chip) +{ + bool snoop = chip->snoop; + + switch (chip->driver_type) { + case AZX_DRIVER_VIA: + /* force to non-snoop mode for a new VIA controller + * when BIOS is set + */ + if (snoop) { + u8 val; + pci_read_config_byte(chip->pci, 0x42, &val); + if (!(val & 0x80) && chip->pci->revision == 0x30) + snoop = false; + } + break; + case AZX_DRIVER_ATIHDMI_NS: + /* new ATI HDMI requires non-snoop */ + snoop = false; + break; + } + + if (snoop != chip->snoop) { + snd_printk(KERN_INFO SFX "Force to %s mode\n", + snoop ? "snoop" : "non-snoop"); + chip->snoop = snoop; + } +} /* * constructor @@ -2671,6 +2690,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, check_msi(chip); chip->dev_index = dev; INIT_WORK(&chip->irq_pending_work, azx_irq_pending_work); + INIT_LIST_HEAD(&chip->pcm_list); chip->position_fix[0] = chip->position_fix[1] = check_position_fix(chip, position_fix[dev]); @@ -2678,6 +2698,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, chip->single_cmd = single_cmd; chip->snoop = hda_snoop; + azx_check_snoop_available(chip); if (bdl_pos_adj[dev] < 0) { switch (chip->driver_type) { @@ -2776,6 +2797,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, chip->capture_streams = ULI_NUM_CAPTURE; break; case AZX_DRIVER_ATIHDMI: + case AZX_DRIVER_ATIHDMI_NS: chip->playback_streams = ATIHDMI_NUM_PLAYBACK; chip->capture_streams = ATIHDMI_NUM_CAPTURE; break; @@ -2970,7 +2992,11 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { /* SCH */ { PCI_DEVICE(0x8086, 0x811b), .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP | - AZX_DCAPS_BUFSIZE}, + AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_LPIB }, /* Poulsbo */ + { PCI_DEVICE(0x8086, 0x080a), + .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP | + AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_LPIB }, /* Oaktrail */ + /* ICH */ { PCI_DEVICE(0x8086, 0x2668), .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC | AZX_DCAPS_BUFSIZE }, /* ICH6 */ @@ -3037,6 +3063,14 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, { PCI_DEVICE(0x1002, 0xaa48), .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI }, + { PCI_DEVICE(0x1002, 0x9902), + .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI }, + { PCI_DEVICE(0x1002, 0xaaa0), + .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI }, + { PCI_DEVICE(0x1002, 0xaaa8), + .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI }, + { PCI_DEVICE(0x1002, 0xaab0), + .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI }, /* VIA VT8251/VT8237A */ { PCI_DEVICE(0x1106, 0x3288), .driver_data = AZX_DRIVER_VIA | AZX_DCAPS_POSFIX_VIA }, |