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;
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;
AZX_DRIVER_SCH,
AZX_DRIVER_ATI,
AZX_DRIVER_ATIHDMI,
+ AZX_DRIVER_ATIHDMI_NS,
AZX_DRIVER_VIA,
AZX_DRIVER_SIS,
AZX_DRIVER_ULI,
[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",
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
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);
}
.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);
{
struct azx_pcm *apcm = pcm->private_data;
if (apcm) {
- apcm->chip->pcm[pcm->device] = NULL;
+ list_del(&apcm->list);
kfree(apcm);
}
}
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,
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];
{
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);
}
}
+/* 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
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]);
chip->single_cmd = single_cmd;
chip->snoop = hda_snoop;
+ azx_check_snoop_available(chip);
if (bdl_pos_adj[dev] < 0) {
switch (chip->driver_type) {
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;
.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 },