diff options
Diffstat (limited to 'sound/pci/hda/hda_intel.c')
-rw-r--r-- | sound/pci/hda/hda_intel.c | 49 |
1 files changed, 30 insertions, 19 deletions
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index c19e71a94e1..4ab8102f87e 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -497,6 +497,7 @@ enum { AZX_DRIVER_NVIDIA, AZX_DRIVER_TERA, AZX_DRIVER_CTX, + AZX_DRIVER_CTHDA, AZX_DRIVER_GENERIC, AZX_NUM_DRIVERS, /* keep this as last entry */ }; @@ -518,6 +519,7 @@ enum { #define AZX_DCAPS_OLD_SSYNC (1 << 20) /* Old SSYNC reg for ICH */ #define AZX_DCAPS_BUFSIZE (1 << 21) /* no buffer size alignment */ #define AZX_DCAPS_ALIGN_BUFSIZE (1 << 22) /* buffer size alignment */ +#define AZX_DCAPS_4K_BDLE_BOUNDARY (1 << 23) /* BDLE in 4k boundary */ /* quirks for ATI SB / AMD Hudson */ #define AZX_DCAPS_PRESET_ATI_SB \ @@ -533,6 +535,9 @@ enum { (AZX_DCAPS_NVIDIA_SNOOP | AZX_DCAPS_RIRB_DELAY | AZX_DCAPS_NO_MSI |\ AZX_DCAPS_ALIGN_BUFSIZE) +#define AZX_DCAPS_PRESET_CTHDA \ + (AZX_DCAPS_NO_MSI | AZX_DCAPS_POSFIX_LPIB | AZX_DCAPS_4K_BDLE_BOUNDARY) + static char *driver_short_names[] __devinitdata = { [AZX_DRIVER_ICH] = "HDA Intel", [AZX_DRIVER_PCH] = "HDA Intel PCH", @@ -546,6 +551,7 @@ static char *driver_short_names[] __devinitdata = { [AZX_DRIVER_NVIDIA] = "HDA NVidia", [AZX_DRIVER_TERA] = "HDA Teradici", [AZX_DRIVER_CTX] = "HDA Creative", + [AZX_DRIVER_CTHDA] = "HDA Creative", [AZX_DRIVER_GENERIC] = "HD-Audio Generic", }; @@ -783,11 +789,13 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus, { struct azx *chip = bus->private_data; unsigned long timeout; + unsigned long loopcounter; int do_poll = 0; again: timeout = jiffies + msecs_to_jiffies(1000); - for (;;) { + + for (loopcounter = 0;; loopcounter++) { if (chip->polling_mode || do_poll) { spin_lock_irq(&chip->reg_lock); azx_update_rirb(chip); @@ -803,7 +811,7 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus, } if (time_after(jiffies, timeout)) break; - if (bus->needs_damn_long_delay) + if (bus->needs_damn_long_delay || loopcounter > 3000) msleep(2); /* temporary workaround */ else { udelay(10); @@ -1283,7 +1291,8 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id) /* * set up a BDL entry */ -static int setup_bdle(struct snd_pcm_substream *substream, +static int setup_bdle(struct azx *chip, + struct snd_pcm_substream *substream, struct azx_dev *azx_dev, u32 **bdlp, int ofs, int size, int with_ioc) { @@ -1302,6 +1311,12 @@ static int setup_bdle(struct snd_pcm_substream *substream, bdl[1] = cpu_to_le32(upper_32_bits(addr)); /* program the size field of the BDL entry */ chunk = snd_pcm_sgbuf_get_chunk_size(substream, ofs, size); + /* one BDLE cannot cross 4K boundary on CTHDA chips */ + if (chip->driver_caps & AZX_DCAPS_4K_BDLE_BOUNDARY) { + u32 remain = 0x1000 - (ofs & 0xfff); + if (chunk > remain) + chunk = remain; + } bdl[2] = cpu_to_le32(chunk); /* program the IOC to enable interrupt * only when the whole fragment is processed @@ -1354,7 +1369,7 @@ static int azx_setup_periods(struct azx *chip, bdl_pos_adj[chip->dev_index]); pos_adj = 0; } else { - ofs = setup_bdle(substream, azx_dev, + ofs = setup_bdle(chip, substream, azx_dev, &bdl, ofs, pos_adj, !substream->runtime->no_period_wakeup); if (ofs < 0) @@ -1364,10 +1379,10 @@ static int azx_setup_periods(struct azx *chip, pos_adj = 0; for (i = 0; i < periods; i++) { if (i == periods - 1 && pos_adj) - ofs = setup_bdle(substream, azx_dev, &bdl, ofs, + ofs = setup_bdle(chip, substream, azx_dev, &bdl, ofs, period_bytes - pos_adj, 0); else - ofs = setup_bdle(substream, azx_dev, &bdl, ofs, + ofs = setup_bdle(chip, substream, azx_dev, &bdl, ofs, period_bytes, !substream->runtime->no_period_wakeup); if (ofs < 0) @@ -2551,6 +2566,8 @@ static struct snd_pci_quirk probe_mask_list[] __devinitdata = { /* forced codec slots */ SND_PCI_QUIRK(0x1043, 0x1262, "ASUS W5Fm", 0x103), SND_PCI_QUIRK(0x1046, 0x1262, "ASUS W5F", 0x103), + /* WinFast VP200 H (Teradici) user reported broken communication */ + SND_PCI_QUIRK(0x3a21, 0x040d, "WinFast VP200 H", 0x101), {} }; @@ -3116,6 +3133,11 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { .driver_data = AZX_DRIVER_CTX | AZX_DCAPS_CTX_WORKAROUND | AZX_DCAPS_RIRB_PRE_DELAY | AZX_DCAPS_POSFIX_LPIB }, #endif + /* CTHDA chips */ + { PCI_DEVICE(0x1102, 0x0010), + .driver_data = AZX_DRIVER_CTHDA | AZX_DCAPS_PRESET_CTHDA }, + { PCI_DEVICE(0x1102, 0x0012), + .driver_data = AZX_DRIVER_CTHDA | AZX_DCAPS_PRESET_CTHDA }, /* Vortex86MX */ { PCI_DEVICE(0x17f3, 0x3010), .driver_data = AZX_DRIVER_GENERIC }, /* VMware HDAudio */ @@ -3134,7 +3156,7 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { MODULE_DEVICE_TABLE(pci, azx_ids); /* pci_driver definition */ -static struct pci_driver driver = { +static struct pci_driver azx_driver = { .name = KBUILD_MODNAME, .id_table = azx_ids, .probe = azx_probe, @@ -3145,15 +3167,4 @@ static struct pci_driver driver = { #endif }; -static int __init alsa_card_azx_init(void) -{ - return pci_register_driver(&driver); -} - -static void __exit alsa_card_azx_exit(void) -{ - pci_unregister_driver(&driver); -} - -module_init(alsa_card_azx_init) -module_exit(alsa_card_azx_exit) +module_pci_driver(azx_driver); |