diff options
author | Takashi Iwai <tiwai@suse.de> | 2009-06-10 07:26:31 +0200 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2009-06-10 07:26:31 +0200 |
commit | 81ad969dbf8b10c3e79c5811b8328c054c21ef39 (patch) | |
tree | 88f9d582d9c88dcb65f203160ee5701c1514ccb6 /sound/pci/hda/hda_intel.c | |
parent | 2f0dabcc5f5fde67c64a6f71e9fb369aed39d56f (diff) | |
parent | f03ecf50534a81b06544c58a713076d59d54baf9 (diff) |
Merge branch 'topic/hda' into for-linus
* topic/hda: (51 commits)
ALSA: hda - Fix the previous tagra-8ch patch
ALSA: hda - Add 7.1 support for MSI GX620
ALSA: support Sony Vaio TT
ALSA: hda_intel: fix build error when !PM
ALSA: hda - More Aspire 8930G fixes
ALSA: hda - Acer Aspire 8930G support
ALSA: hda - Limit codec-verb retry to limited hardwares
ALSA: hda - Add codec bus reset and verb-retry at critical errors
ALSA: hda - Reorder and clean-up ALC268 quirk table
ALSA: hda - fix audio on LG R510
ALSA: hda - Macbook[Pro] 5 6ch support
ALSA: hda-intel: improve initialization for ALC262_HP_BPC model
ALSA: hda - Jack Mode changes for Sigmatel boards
ALSA: hda - Support NVIDIA 8 channel HDMI audio
ALSA: hda - Fix a typo in the previous patch
ALSA: hda - Fix reverted LED setup for HP
ALSA: hda - Add more register bits definitions
ALSA: hda - Always sync writes in single_cmd mode
ALSA: hda - Support sync after writing a verb
ALSA: hda - Allow concurrent RIRB access in single_cmd mode
...
Diffstat (limited to 'sound/pci/hda/hda_intel.c')
-rw-r--r-- | sound/pci/hda/hda_intel.c | 197 |
1 files changed, 133 insertions, 64 deletions
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 3128e1a6bc6..4e9ea708027 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -128,21 +128,33 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6}," "{ULI, M5461}}"); MODULE_DESCRIPTION("Intel HDA driver"); +#ifdef CONFIG_SND_VERBOSE_PRINTK +#define SFX /* nop */ +#else #define SFX "hda-intel: " - +#endif /* * registers */ #define ICH6_REG_GCAP 0x00 +#define ICH6_GCAP_64OK (1 << 0) /* 64bit address support */ +#define ICH6_GCAP_NSDO (3 << 1) /* # of serial data out signals */ +#define ICH6_GCAP_BSS (31 << 3) /* # of bidirectional streams */ +#define ICH6_GCAP_ISS (15 << 8) /* # of input streams */ +#define ICH6_GCAP_OSS (15 << 12) /* # of output streams */ #define ICH6_REG_VMIN 0x02 #define ICH6_REG_VMAJ 0x03 #define ICH6_REG_OUTPAY 0x04 #define ICH6_REG_INPAY 0x06 #define ICH6_REG_GCTL 0x08 +#define ICH6_GCTL_RESET (1 << 0) /* controller reset */ +#define ICH6_GCTL_FCNTRL (1 << 1) /* flush control */ +#define ICH6_GCTL_UNSOL (1 << 8) /* accept unsol. response enable */ #define ICH6_REG_WAKEEN 0x0c #define ICH6_REG_STATESTS 0x0e #define ICH6_REG_GSTS 0x10 +#define ICH6_GSTS_FSTS (1 << 1) /* flush status */ #define ICH6_REG_INTCTL 0x20 #define ICH6_REG_INTSTS 0x24 #define ICH6_REG_WALCLK 0x30 @@ -150,17 +162,27 @@ MODULE_DESCRIPTION("Intel HDA driver"); #define ICH6_REG_CORBLBASE 0x40 #define ICH6_REG_CORBUBASE 0x44 #define ICH6_REG_CORBWP 0x48 -#define ICH6_REG_CORBRP 0x4A +#define ICH6_REG_CORBRP 0x4a +#define ICH6_CORBRP_RST (1 << 15) /* read pointer reset */ #define ICH6_REG_CORBCTL 0x4c +#define ICH6_CORBCTL_RUN (1 << 1) /* enable DMA */ +#define ICH6_CORBCTL_CMEIE (1 << 0) /* enable memory error irq */ #define ICH6_REG_CORBSTS 0x4d +#define ICH6_CORBSTS_CMEI (1 << 0) /* memory error indication */ #define ICH6_REG_CORBSIZE 0x4e #define ICH6_REG_RIRBLBASE 0x50 #define ICH6_REG_RIRBUBASE 0x54 #define ICH6_REG_RIRBWP 0x58 +#define ICH6_RIRBWP_RST (1 << 15) /* write pointer reset */ #define ICH6_REG_RINTCNT 0x5a #define ICH6_REG_RIRBCTL 0x5c +#define ICH6_RBCTL_IRQ_EN (1 << 0) /* enable IRQ */ +#define ICH6_RBCTL_DMA_EN (1 << 1) /* enable DMA */ +#define ICH6_RBCTL_OVERRUN_EN (1 << 2) /* enable overrun irq */ #define ICH6_REG_RIRBSTS 0x5d +#define ICH6_RBSTS_IRQ (1 << 0) /* response irq */ +#define ICH6_RBSTS_OVERRUN (1 << 2) /* overrun irq */ #define ICH6_REG_RIRBSIZE 0x5e #define ICH6_REG_IC 0x60 @@ -257,16 +279,6 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; #define ICH6_INT_CTRL_EN 0x40000000 /* controller interrupt enable bit */ #define ICH6_INT_GLOBAL_EN 0x80000000 /* global interrupt enable bit */ -/* GCTL unsolicited response enable bit */ -#define ICH6_GCTL_UREN (1<<8) - -/* GCTL reset bit */ -#define ICH6_GCTL_RESET (1<<0) - -/* CORB/RIRB control, read/write pointer */ -#define ICH6_RBCTL_DMA_EN 0x02 /* enable DMA */ -#define ICH6_RBCTL_IRQ_EN 0x01 /* enable IRQ */ -#define ICH6_RBRWP_CLR 0x8000 /* read/write pointer clear */ /* below are so far hardcoded - should read registers in future */ #define ICH6_MAX_CORB_ENTRIES 256 #define ICH6_MAX_RIRB_ENTRIES 256 @@ -512,25 +524,25 @@ static void azx_init_cmd_io(struct azx *chip) /* set the corb write pointer to 0 */ azx_writew(chip, CORBWP, 0); /* reset the corb hw read pointer */ - azx_writew(chip, CORBRP, ICH6_RBRWP_CLR); + azx_writew(chip, CORBRP, ICH6_CORBRP_RST); /* enable corb dma */ - azx_writeb(chip, CORBCTL, ICH6_RBCTL_DMA_EN); + azx_writeb(chip, CORBCTL, ICH6_CORBCTL_RUN); /* RIRB set up */ chip->rirb.addr = chip->rb.addr + 2048; chip->rirb.buf = (u32 *)(chip->rb.area + 2048); + chip->rirb.wp = chip->rirb.rp = chip->rirb.cmds = 0; azx_writel(chip, RIRBLBASE, (u32)chip->rirb.addr); azx_writel(chip, RIRBUBASE, upper_32_bits(chip->rirb.addr)); /* set the rirb size to 256 entries (ULI requires explicitly) */ azx_writeb(chip, RIRBSIZE, 0x02); /* reset the rirb hw write pointer */ - azx_writew(chip, RIRBWP, ICH6_RBRWP_CLR); + azx_writew(chip, RIRBWP, ICH6_RIRBWP_RST); /* set N=1, get RIRB response interrupt for new entry */ azx_writew(chip, RINTCNT, 1); /* enable rirb dma and response irq */ azx_writeb(chip, RIRBCTL, ICH6_RBCTL_DMA_EN | ICH6_RBCTL_IRQ_EN); - chip->rirb.rp = chip->rirb.cmds = 0; } static void azx_free_cmd_io(struct azx *chip) @@ -606,6 +618,7 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus) } if (!chip->rirb.cmds) { smp_rmb(); + bus->rirb_error = 0; return chip->rirb.res; /* the last value */ } if (time_after(jiffies, timeout)) @@ -619,19 +632,21 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus) } if (chip->msi) { - snd_printk(KERN_WARNING "hda_intel: No response from codec, " + snd_printk(KERN_WARNING SFX "No response from codec, " "disabling MSI: last cmd=0x%08x\n", chip->last_cmd); free_irq(chip->irq, chip); chip->irq = -1; pci_disable_msi(chip->pci); chip->msi = 0; - if (azx_acquire_irq(chip, 1) < 0) + if (azx_acquire_irq(chip, 1) < 0) { + bus->rirb_error = 1; return -1; + } goto again; } if (!chip->polling_mode) { - snd_printk(KERN_WARNING "hda_intel: azx_get_response timeout, " + snd_printk(KERN_WARNING SFX "azx_get_response timeout, " "switching to polling mode: last cmd=0x%08x\n", chip->last_cmd); chip->polling_mode = 1; @@ -646,14 +661,23 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus) return -1; } + /* a fatal communication error; need either to reset or to fallback + * to the single_cmd mode + */ + bus->rirb_error = 1; + if (bus->allow_bus_reset && !bus->response_reset && !bus->in_reset) { + bus->response_reset = 1; + return -1; /* give a chance to retry */ + } + snd_printk(KERN_ERR "hda_intel: azx_get_response timeout, " "switching to single_cmd mode: last cmd=0x%08x\n", chip->last_cmd); - chip->rirb.rp = azx_readb(chip, RIRBWP); - chip->rirb.cmds = 0; - /* switch to single_cmd mode */ chip->single_cmd = 1; + bus->response_reset = 0; + /* re-initialize CORB/RIRB */ azx_free_cmd_io(chip); + azx_init_cmd_io(chip); return -1; } @@ -667,12 +691,34 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus) * I left the codes, however, for debugging/testing purposes. */ +/* receive a response */ +static int azx_single_wait_for_response(struct azx *chip) +{ + int timeout = 50; + + while (timeout--) { + /* check IRV busy bit */ + if (azx_readw(chip, IRS) & ICH6_IRS_VALID) { + /* reuse rirb.res as the response return value */ + chip->rirb.res = azx_readl(chip, IR); + return 0; + } + udelay(1); + } + if (printk_ratelimit()) + snd_printd(SFX "get_response timeout: IRS=0x%x\n", + azx_readw(chip, IRS)); + chip->rirb.res = -1; + return -EIO; +} + /* send a command */ static int azx_single_send_cmd(struct hda_bus *bus, u32 val) { struct azx *chip = bus->private_data; int timeout = 50; + bus->rirb_error = 0; while (timeout--) { /* check ICB busy bit */ if (!((azx_readw(chip, IRS) & ICH6_IRS_BUSY))) { @@ -682,7 +728,7 @@ static int azx_single_send_cmd(struct hda_bus *bus, u32 val) azx_writel(chip, IC, val); azx_writew(chip, IRS, azx_readw(chip, IRS) | ICH6_IRS_BUSY); - return 0; + return azx_single_wait_for_response(chip); } udelay(1); } @@ -696,18 +742,7 @@ static int azx_single_send_cmd(struct hda_bus *bus, u32 val) static unsigned int azx_single_get_response(struct hda_bus *bus) { struct azx *chip = bus->private_data; - int timeout = 50; - - while (timeout--) { - /* check IRV busy bit */ - if (azx_readw(chip, IRS) & ICH6_IRS_VALID) - return azx_readl(chip, IR); - udelay(1); - } - if (printk_ratelimit()) - snd_printd(SFX "get_response timeout: IRS=0x%x\n", - azx_readw(chip, IRS)); - return (unsigned int)-1; + return chip->rirb.res; } /* @@ -775,17 +810,17 @@ static int azx_reset(struct azx *chip) /* check to see if controller is ready */ if (!azx_readb(chip, GCTL)) { - snd_printd("azx_reset: controller not ready!\n"); + snd_printd(SFX "azx_reset: controller not ready!\n"); return -EBUSY; } /* Accept unsolicited responses */ - azx_writel(chip, GCTL, azx_readl(chip, GCTL) | ICH6_GCTL_UREN); + azx_writel(chip, GCTL, azx_readl(chip, GCTL) | ICH6_GCTL_UNSOL); /* detect codecs */ if (!chip->codec_mask) { chip->codec_mask = azx_readw(chip, STATESTS); - snd_printdd("codec_mask = 0x%x\n", chip->codec_mask); + snd_printdd(SFX "codec_mask = 0x%x\n", chip->codec_mask); } return 0; @@ -895,8 +930,7 @@ static void azx_init_chip(struct azx *chip) azx_int_enable(chip); /* initialize the codec command I/O */ - if (!chip->single_cmd) - azx_init_cmd_io(chip); + azx_init_cmd_io(chip); /* program the position buffer */ azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr); @@ -953,12 +987,12 @@ static void azx_init_pci(struct azx *chip) case AZX_DRIVER_SCH: pci_read_config_word(chip->pci, INTEL_SCH_HDA_DEVC, &snoop); if (snoop & INTEL_SCH_HDA_DEVC_NOSNOOP) { - pci_write_config_word(chip->pci, INTEL_SCH_HDA_DEVC, \ + pci_write_config_word(chip->pci, INTEL_SCH_HDA_DEVC, snoop & (~INTEL_SCH_HDA_DEVC_NOSNOOP)); pci_read_config_word(chip->pci, INTEL_SCH_HDA_DEVC, &snoop); - snd_printdd("HDA snoop disabled, enabling ... %s\n",\ - (snoop & INTEL_SCH_HDA_DEVC_NOSNOOP) \ + snd_printdd(SFX "HDA snoop disabled, enabling ... %s\n", + (snoop & INTEL_SCH_HDA_DEVC_NOSNOOP) ? "Failed" : "OK"); } break; @@ -1012,7 +1046,7 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id) /* clear rirb int */ status = azx_readb(chip, RIRBSTS); if (status & RIRB_INT_MASK) { - if (!chip->single_cmd && (status & RIRB_INT_RESPONSE)) + if (status & RIRB_INT_RESPONSE) azx_update_rirb(chip); azx_writeb(chip, RIRBSTS, RIRB_INT_MASK); } @@ -1098,7 +1132,7 @@ static int azx_setup_periods(struct azx *chip, pos_align; pos_adj = frames_to_bytes(runtime, pos_adj); if (pos_adj >= period_bytes) { - snd_printk(KERN_WARNING "Too big adjustment %d\n", + snd_printk(KERN_WARNING SFX "Too big adjustment %d\n", bdl_pos_adj[chip->dev_index]); pos_adj = 0; } else { @@ -1122,7 +1156,7 @@ static int azx_setup_periods(struct azx *chip, return 0; error: - snd_printk(KERN_ERR "Too many BDL entries: buffer=%d, period=%d\n", + snd_printk(KERN_ERR SFX "Too many BDL entries: buffer=%d, period=%d\n", azx_dev->bufsize, period_bytes); return -EINVAL; } @@ -1215,7 +1249,7 @@ static int probe_codec(struct azx *chip, int addr) chip->probing = 0; if (res == -1) return -EIO; - snd_printdd("hda_intel: codec #%d probed OK\n", addr); + snd_printdd(SFX "codec #%d probed OK\n", addr); return 0; } @@ -1223,6 +1257,26 @@ static int azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec, struct hda_pcm *cpcm); static void azx_stop_chip(struct azx *chip); +static void azx_bus_reset(struct hda_bus *bus) +{ + struct azx *chip = bus->private_data; + + bus->in_reset = 1; + azx_stop_chip(chip); + azx_init_chip(chip); +#ifdef CONFIG_PM + if (chip->initialized) { + int i; + + for (i = 0; i < AZX_MAX_PCMS; i++) + snd_pcm_suspend_all(chip->pcm[i]); + snd_hda_suspend(chip->bus); + snd_hda_resume(chip->bus); + } +#endif + bus->in_reset = 0; +} + /* * Codec initialization */ @@ -1246,6 +1300,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model, bus_temp.ops.command = azx_send_cmd; bus_temp.ops.get_response = azx_get_response; bus_temp.ops.attach_pcm = azx_attach_pcm_stream; + bus_temp.ops.bus_reset = azx_bus_reset; #ifdef CONFIG_SND_HDA_POWER_SAVE bus_temp.power_save = &power_save; bus_temp.ops.pm_notify = azx_power_notify; @@ -1270,8 +1325,8 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model, /* Some BIOSen give you wrong codec addresses * that don't exist */ - snd_printk(KERN_WARNING - "hda_intel: Codec #%d probe error; " + snd_printk(KERN_WARNING SFX + "Codec #%d probe error; " "disabling it...\n", c); chip->codec_mask &= ~(1 << c); /* More badly, accessing to a non-existing @@ -1487,7 +1542,7 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) bufsize = snd_pcm_lib_buffer_bytes(substream); period_bytes = snd_pcm_lib_period_bytes(substream); - snd_printdd("azx_pcm_prepare: bufsize=0x%x, format=0x%x\n", + snd_printdd(SFX "azx_pcm_prepare: bufsize=0x%x, format=0x%x\n", bufsize, format_val); if (bufsize != azx_dev->bufsize || @@ -1830,7 +1885,7 @@ azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec, &pcm); if (err < 0) return err; - strcpy(pcm->name, cpcm->name); + strlcpy(pcm->name, cpcm->name, sizeof(pcm->name)); apcm = kzalloc(sizeof(*apcm), GFP_KERNEL); if (apcm == NULL) return -ENOMEM; @@ -1973,7 +2028,7 @@ static int azx_suspend(struct pci_dev *pci, pm_message_t state) for (i = 0; i < AZX_MAX_PCMS; i++) snd_pcm_suspend_all(chip->pcm[i]); if (chip->initialized) - snd_hda_suspend(chip->bus, state); + snd_hda_suspend(chip->bus); azx_stop_chip(chip); if (chip->irq >= 0) { free_irq(chip->irq, chip); @@ -2265,14 +2320,14 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, synchronize_irq(chip->irq); gcap = azx_readw(chip, GCAP); - snd_printdd("chipset global capabilities = 0x%x\n", gcap); + snd_printdd(SFX "chipset global capabilities = 0x%x\n", gcap); /* ATI chips seems buggy about 64bit DMA addresses */ if (chip->driver_type == AZX_DRIVER_ATI) - gcap &= ~0x01; + gcap &= ~ICH6_GCAP_64OK; /* allow 64bit DMA address if supported by H/W */ - if ((gcap & 0x01) && !pci_set_dma_mask(pci, DMA_BIT_MASK(64))) + if ((gcap & ICH6_GCAP_64OK) && !pci_set_dma_mask(pci, DMA_BIT_MASK(64))) pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(64)); else { pci_set_dma_mask(pci, DMA_BIT_MASK(32)); @@ -2309,7 +2364,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, chip->azx_dev = kcalloc(chip->num_streams, sizeof(*chip->azx_dev), GFP_KERNEL); if (!chip->azx_dev) { - snd_printk(KERN_ERR "cannot malloc azx_dev\n"); + snd_printk(KERN_ERR SFX "cannot malloc azx_dev\n"); goto errout; } @@ -2332,11 +2387,9 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, goto errout; } /* allocate CORB/RIRB */ - if (!chip->single_cmd) { - err = azx_alloc_cmd_io(chip); - if (err < 0) - goto errout; - } + err = azx_alloc_cmd_io(chip); + if (err < 0) + goto errout; /* initialize streams */ azx_init_stream(chip); @@ -2359,9 +2412,11 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, } strcpy(card->driver, "HDA-Intel"); - strcpy(card->shortname, driver_short_names[chip->driver_type]); - sprintf(card->longname, "%s at 0x%lx irq %i", - card->shortname, chip->addr, chip->irq); + strlcpy(card->shortname, driver_short_names[chip->driver_type], + sizeof(card->shortname)); + snprintf(card->longname, sizeof(card->longname), + "%s at 0x%lx irq %i", + card->shortname, chip->addr, chip->irq); *rchip = chip; return 0; @@ -2514,6 +2569,20 @@ static struct pci_device_id azx_ids[] = { { PCI_DEVICE(0x10de, 0x0d97), .driver_data = AZX_DRIVER_NVIDIA }, /* Teradici */ { PCI_DEVICE(0x6549, 0x1200), .driver_data = AZX_DRIVER_TERA }, + /* Creative X-Fi (CA0110-IBG) */ +#if !defined(CONFIG_SND_CTXFI) && !defined(CONFIG_SND_CTXFI_MODULE) + /* the following entry conflicts with snd-ctxfi driver, + * as ctxfi driver mutates from HD-audio to native mode with + * a special command sequence. + */ + { PCI_DEVICE(PCI_VENDOR_ID_CREATIVE, PCI_ANY_ID), + .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8, + .class_mask = 0xffffff, + .driver_data = AZX_DRIVER_GENERIC }, +#else + /* this entry seems still valid -- i.e. without emu20kx chip */ + { PCI_DEVICE(0x1102, 0x0009), .driver_data = AZX_DRIVER_GENERIC }, +#endif /* AMD Generic, PCI class code and Vendor ID for HD Audio */ { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_ANY_ID), .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8, |