ALSA: hda - Reset CORB/RIRB at retrying the verb communication
[safe/jmp/linux-2.6] / sound / pci / hda / hda_intel.c
index 30829ee..3fc75e2 100644 (file)
@@ -128,8 +128,11 @@ 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
@@ -312,6 +315,8 @@ struct azx_dev {
        unsigned int period_bytes; /* size of the period in bytes */
        unsigned int frags;     /* number for period in the play buffer */
        unsigned int fifo_size; /* FIFO size */
+       unsigned long start_jiffies;    /* start + minimum jiffies */
+       unsigned long min_jiffies;      /* minimum jiffies before position is valid */
 
        void __iomem *sd_addr;  /* stream descriptor pointer */
 
@@ -330,7 +335,7 @@ struct azx_dev {
        unsigned int opened :1;
        unsigned int running :1;
        unsigned int irq_pending :1;
-       unsigned int irq_ignore :1;
+       unsigned int start_flag: 1;     /* stream full start flag */
        /*
         * For VIA:
         *  A flag to ensure DMA position is 0
@@ -517,6 +522,7 @@ static void azx_init_cmd_io(struct azx *chip)
        /* 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));
 
@@ -528,7 +534,6 @@ static void azx_init_cmd_io(struct azx *chip)
        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)
@@ -604,6 +609,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))
@@ -617,19 +623,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;
@@ -644,14 +652,14 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus)
                return -1;
        }
 
-       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;
+       snd_printk(KERN_ERR SFX "azx_get_response timeout (ERROR): "
+                  "last cmd=0x%08x\n", chip->last_cmd);
+       /* re-initialize CORB/RIRB */
+       spin_lock_irq(&chip->reg_lock);
+       bus->rirb_error = 1;
        azx_free_cmd_io(chip);
+       azx_init_cmd_io(chip);
+       spin_unlock_irq(&chip->reg_lock);
        return -1;
 }
 
@@ -773,7 +781,7 @@ 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;
        }
 
@@ -783,7 +791,7 @@ static int azx_reset(struct azx *chip)
        /* 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;
@@ -951,12 +959,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;
@@ -975,7 +983,7 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id)
        struct azx *chip = dev_id;
        struct azx_dev *azx_dev;
        u32 status;
-       int i;
+       int i, ok;
 
        spin_lock(&chip->reg_lock);
 
@@ -991,18 +999,14 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id)
                        azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK);
                        if (!azx_dev->substream || !azx_dev->running)
                                continue;
-                       /* ignore the first dummy IRQ (due to pos_adj) */
-                       if (azx_dev->irq_ignore) {
-                               azx_dev->irq_ignore = 0;
-                               continue;
-                       }
                        /* check whether this IRQ is really acceptable */
-                       if (azx_position_ok(chip, azx_dev)) {
+                       ok = azx_position_ok(chip, azx_dev);
+                       if (ok == 1) {
                                azx_dev->irq_pending = 0;
                                spin_unlock(&chip->reg_lock);
                                snd_pcm_period_elapsed(azx_dev->substream);
                                spin_lock(&chip->reg_lock);
-                       } else if (chip->bus && chip->bus->workq) {
+                       } else if (ok == 0 && chip->bus && chip->bus->workq) {
                                /* bogus IRQ, process it later */
                                azx_dev->irq_pending = 1;
                                queue_work(chip->bus->workq,
@@ -1088,7 +1092,6 @@ static int azx_setup_periods(struct azx *chip,
        bdl = (u32 *)azx_dev->bdl.area;
        ofs = 0;
        azx_dev->frags = 0;
-       azx_dev->irq_ignore = 0;
        pos_adj = bdl_pos_adj[chip->dev_index];
        if (pos_adj > 0) {
                struct snd_pcm_runtime *runtime = substream->runtime;
@@ -1101,7 +1104,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 {
@@ -1109,7 +1112,6 @@ static int azx_setup_periods(struct azx *chip,
                                         &bdl, ofs, pos_adj, 1);
                        if (ofs < 0)
                                goto error;
-                       azx_dev->irq_ignore = 1;
                }
        } else
                pos_adj = 0;
@@ -1126,7 +1128,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;
 }
@@ -1155,6 +1157,9 @@ static void azx_stream_reset(struct azx *chip, struct azx_dev *azx_dev)
        while (((val = azx_sd_readb(azx_dev, SD_CTL)) & SD_CTL_STREAM_RESET) &&
               --timeout)
                ;
+
+       /* reset first position - may not be synced with hw at this time */
+       *azx_dev->posbuf = 0;
 }
 
 /*
@@ -1216,7 +1221,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;
 }
 
@@ -1271,8 +1276,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
@@ -1409,7 +1414,6 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
        snd_pcm_set_sync(substream);
        mutex_unlock(&chip->open_mutex);
 
-       azx_stream_reset(chip, azx_dev);
        return 0;
 }
 
@@ -1474,6 +1478,7 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
        unsigned int bufsize, period_bytes, format_val;
        int err;
 
+       azx_stream_reset(chip, azx_dev);
        format_val = snd_hda_calc_stream_format(runtime->rate,
                                                runtime->channels,
                                                runtime->format,
@@ -1488,7 +1493,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 ||
@@ -1502,6 +1507,8 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
                        return err;
        }
 
+       azx_dev->min_jiffies = (runtime->period_size * HZ) /
+                                               (runtime->rate * 2);
        azx_setup_controller(chip, azx_dev);
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
                azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1;
@@ -1518,13 +1525,14 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
        struct azx *chip = apcm->chip;
        struct azx_dev *azx_dev;
        struct snd_pcm_substream *s;
-       int start, nsync = 0, sbits = 0;
+       int rstart = 0, start, nsync = 0, sbits = 0;
        int nwait, timeout;
 
        switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+               rstart = 1;
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
        case SNDRV_PCM_TRIGGER_RESUME:
-       case SNDRV_PCM_TRIGGER_START:
                start = 1;
                break;
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
@@ -1554,6 +1562,10 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
                if (s->pcm->card != substream->pcm->card)
                        continue;
                azx_dev = get_azx_dev(s);
+               if (rstart) {
+                       azx_dev->start_flag = 1;
+                       azx_dev->start_jiffies = jiffies + azx_dev->min_jiffies;
+               }
                if (start)
                        azx_stream_start(chip, azx_dev);
                else
@@ -1703,6 +1715,11 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev)
 {
        unsigned int pos;
 
+       if (azx_dev->start_flag &&
+           time_before_eq(jiffies, azx_dev->start_jiffies))
+               return -1;      /* bogus (too early) interrupt */
+       azx_dev->start_flag = 0;
+
        pos = azx_get_position(chip, azx_dev);
        if (chip->position_fix == POS_FIX_AUTO) {
                if (!pos) {
@@ -1819,7 +1836,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;
@@ -2253,18 +2270,18 @@ 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;
 
        /* allow 64bit DMA address if supported by H/W */
-       if ((gcap & 0x01) && !pci_set_dma_mask(pci, DMA_64BIT_MASK))
-               pci_set_consistent_dma_mask(pci, DMA_64BIT_MASK);
+       if ((gcap & 0x01) && !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_32BIT_MASK);
-               pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK);
+               pci_set_dma_mask(pci, DMA_BIT_MASK(32));
+               pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(32));
        }
 
        /* read number of streams from GCAP register instead of using
@@ -2297,7 +2314,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;
        }
 
@@ -2347,9 +2364,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;
@@ -2502,6 +2521,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,