Merge branch 'topic/hda-cache' into topic/hda
[pandora-kernel.git] / sound / pci / hda / hda_intel.c
index f3b5723..04f19f8 100644 (file)
@@ -312,6 +312,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 +332,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
@@ -381,6 +383,7 @@ struct azx {
 
        /* HD codec */
        unsigned short codec_mask;
+       int  codec_probe_mask; /* copied from probe_mask option */
        struct hda_bus *bus;
 
        /* CORB/RIRB */
@@ -603,6 +606,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))
@@ -622,8 +626,10 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus)
                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;
        }
 
@@ -643,14 +649,12 @@ 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;
-       azx_free_cmd_io(chip);
+       snd_printk(KERN_ERR "hda_intel: azx_get_response timeout (ERROR): "
+                  "last cmd=0x%08x\n", chip->last_cmd);
+       spin_lock_irq(&chip->reg_lock);
+       chip->rirb.cmds = 0; /* reset the index */
+       bus->rirb_error = 1;
+       spin_unlock_irq(&chip->reg_lock);
        return -1;
 }
 
@@ -858,13 +862,18 @@ static void azx_stream_start(struct azx *chip, struct azx_dev *azx_dev)
                      SD_CTL_DMA_START | SD_INT_MASK);
 }
 
-/* stop a stream */
-static void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev)
+/* stop DMA */
+static void azx_stream_clear(struct azx *chip, struct azx_dev *azx_dev)
 {
-       /* stop DMA */
        azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) &
                      ~(SD_CTL_DMA_START | SD_INT_MASK));
        azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK); /* to be sure */
+}
+
+/* stop a stream */
+static void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev)
+{
+       azx_stream_clear(chip, azx_dev);
        /* disable SIE */
        azx_writeb(chip, INTCTL,
                   azx_readb(chip, INTCTL) & ~(1 << azx_dev->index));
@@ -969,7 +978,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);
 
@@ -985,18 +994,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,
@@ -1075,15 +1080,13 @@ static int azx_setup_periods(struct azx *chip,
        azx_sd_writel(azx_dev, SD_BDLPL, 0);
        azx_sd_writel(azx_dev, SD_BDLPU, 0);
 
-       period_bytes = snd_pcm_lib_period_bytes(substream);
-       azx_dev->period_bytes = period_bytes;
+       period_bytes = azx_dev->period_bytes;
        periods = azx_dev->bufsize / period_bytes;
 
        /* program the initial BDL entries */
        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;
@@ -1104,7 +1107,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;
@@ -1123,24 +1125,17 @@ static int azx_setup_periods(struct azx *chip,
  error:
        snd_printk(KERN_ERR "Too many BDL entries: buffer=%d, period=%d\n",
                   azx_dev->bufsize, period_bytes);
-       /* reset */
-       azx_sd_writel(azx_dev, SD_BDLPL, 0);
-       azx_sd_writel(azx_dev, SD_BDLPU, 0);
        return -EINVAL;
 }
 
-/*
- * set up the SD for streaming
- */
-static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
+/* reset stream */
+static void azx_stream_reset(struct azx *chip, struct azx_dev *azx_dev)
 {
        unsigned char val;
        int timeout;
 
-       /* make sure the run bit is zero for SD */
-       azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) &
-                     ~SD_CTL_DMA_START);
-       /* reset stream */
+       azx_stream_clear(chip, azx_dev);
+
        azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) |
                      SD_CTL_STREAM_RESET);
        udelay(3);
@@ -1158,6 +1153,17 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
               --timeout)
                ;
 
+       /* reset first position - may not be synced with hw at this time */
+       *azx_dev->posbuf = 0;
+}
+
+/*
+ * set up the SD for streaming
+ */
+static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
+{
+       /* make sure the run bit is zero for SD */
+       azx_stream_clear(chip, azx_dev);
        /* program the stream_tag */
        azx_sd_writel(azx_dev, SD_CTL,
                      (azx_sd_readl(azx_dev, SD_CTL) & ~SD_CTL_STREAM_TAG_MASK)|
@@ -1228,7 +1234,6 @@ static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] __devinitdata = {
 };
 
 static int __devinit azx_codec_create(struct azx *chip, const char *model,
-                                     unsigned int codec_probe_mask,
                                      int no_init)
 {
        struct hda_bus_template bus_temp;
@@ -1261,7 +1266,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model,
 
        /* First try to probe all given codec slots */
        for (c = 0; c < max_slots; c++) {
-               if ((chip->codec_mask & (1 << c)) & codec_probe_mask) {
+               if ((chip->codec_mask & (1 << c)) & chip->codec_probe_mask) {
                        if (probe_codec(chip, c) < 0) {
                                /* Some BIOSen give you wrong codec addresses
                                 * that don't exist
@@ -1285,7 +1290,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model,
 
        /* Then create codec instances */
        for (c = 0; c < max_slots; c++) {
-               if ((chip->codec_mask & (1 << c)) & codec_probe_mask) {
+               if ((chip->codec_mask & (1 << c)) & chip->codec_probe_mask) {
                        struct hda_codec *codec;
                        err = snd_hda_codec_new(chip->bus, c, !no_init, &codec);
                        if (err < 0)
@@ -1403,6 +1408,7 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
        runtime->private_data = azx_dev;
        snd_pcm_set_sync(substream);
        mutex_unlock(&chip->open_mutex);
+
        return 0;
 }
 
@@ -1429,6 +1435,11 @@ static int azx_pcm_close(struct snd_pcm_substream *substream)
 static int azx_pcm_hw_params(struct snd_pcm_substream *substream,
                             struct snd_pcm_hw_params *hw_params)
 {
+       struct azx_dev *azx_dev = get_azx_dev(substream);
+
+       azx_dev->bufsize = 0;
+       azx_dev->period_bytes = 0;
+       azx_dev->format_val = 0;
        return snd_pcm_lib_malloc_pages(substream,
                                        params_buffer_bytes(hw_params));
 }
@@ -1443,6 +1454,9 @@ static int azx_pcm_hw_free(struct snd_pcm_substream *substream)
        azx_sd_writel(azx_dev, SD_BDLPL, 0);
        azx_sd_writel(azx_dev, SD_BDLPU, 0);
        azx_sd_writel(azx_dev, SD_CTL, 0);
+       azx_dev->bufsize = 0;
+       azx_dev->period_bytes = 0;
+       azx_dev->format_val = 0;
 
        hinfo->ops.cleanup(hinfo, apcm->codec, substream);
 
@@ -1456,23 +1470,40 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
        struct azx_dev *azx_dev = get_azx_dev(substream);
        struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream];
        struct snd_pcm_runtime *runtime = substream->runtime;
+       unsigned int bufsize, period_bytes, format_val;
+       int err;
 
-       azx_dev->bufsize = snd_pcm_lib_buffer_bytes(substream);
-       azx_dev->format_val = snd_hda_calc_stream_format(runtime->rate,
-                                                        runtime->channels,
-                                                        runtime->format,
-                                                        hinfo->maxbps);
-       if (!azx_dev->format_val) {
+       azx_stream_reset(chip, azx_dev);
+       format_val = snd_hda_calc_stream_format(runtime->rate,
+                                               runtime->channels,
+                                               runtime->format,
+                                               hinfo->maxbps);
+       if (!format_val) {
                snd_printk(KERN_ERR SFX
                           "invalid format_val, rate=%d, ch=%d, format=%d\n",
                           runtime->rate, runtime->channels, runtime->format);
                return -EINVAL;
        }
 
+       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",
-                   azx_dev->bufsize, azx_dev->format_val);
-       if (azx_setup_periods(chip, substream, azx_dev) < 0)
-               return -EINVAL;
+                   bufsize, format_val);
+
+       if (bufsize != azx_dev->bufsize ||
+           period_bytes != azx_dev->period_bytes ||
+           format_val != azx_dev->format_val) {
+               azx_dev->bufsize = bufsize;
+               azx_dev->period_bytes = period_bytes;
+               azx_dev->format_val = format_val;
+               err = azx_setup_periods(chip, substream, azx_dev);
+               if (err < 0)
+                       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;
@@ -1489,13 +1520,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:
@@ -1525,6 +1557,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
@@ -1674,6 +1710,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) {
@@ -1790,7 +1831,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;
@@ -2100,25 +2141,36 @@ static struct snd_pci_quirk probe_mask_list[] __devinitdata = {
        SND_PCI_QUIRK(0x1028, 0x20ac, "Dell Studio Desktop", 0x01),
        /* including bogus ALC268 in slot#2 that conflicts with ALC888 */
        SND_PCI_QUIRK(0x17c0, 0x4085, "Medion MD96630", 0x01),
-       /* conflict of ALC268 in slot#3 (digital I/O); a temporary fix */
-       SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba laptop", 0x03),
+       /* forced codec slots */
+       SND_PCI_QUIRK(0x1046, 0x1262, "ASUS W5F", 0x103),
        {}
 };
 
+#define AZX_FORCE_CODEC_MASK   0x100
+
 static void __devinit check_probe_mask(struct azx *chip, int dev)
 {
        const struct snd_pci_quirk *q;
 
-       if (probe_mask[dev] == -1) {
+       chip->codec_probe_mask = probe_mask[dev];
+       if (chip->codec_probe_mask == -1) {
                q = snd_pci_quirk_lookup(chip->pci, probe_mask_list);
                if (q) {
                        printk(KERN_INFO
                               "hda_intel: probe_mask set to 0x%x "
                               "for device %04x:%04x\n",
                               q->value, q->subvendor, q->subdevice);
-                       probe_mask[dev] = q->value;
+                       chip->codec_probe_mask = q->value;
                }
        }
+
+       /* check forced option */
+       if (chip->codec_probe_mask != -1 &&
+           (chip->codec_probe_mask & AZX_FORCE_CODEC_MASK)) {
+               chip->codec_mask = chip->codec_probe_mask & 0xff;
+               printk(KERN_INFO "hda_intel: codec_mask forced to 0x%x\n",
+                      chip->codec_mask);
+       }
 }
 
 
@@ -2220,11 +2272,11 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
                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
@@ -2307,9 +2359,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;
@@ -2347,10 +2401,10 @@ static int __devinit azx_probe(struct pci_dev *pci,
                return -ENOENT;
        }
 
-       card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-       if (!card) {
+       err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+       if (err < 0) {
                snd_printk(KERN_ERR SFX "Error creating card!\n");
-               return -ENOMEM;
+               return err;
        }
 
        err = azx_create(card, pci, dev, pci_id->driver_data, &chip);
@@ -2359,8 +2413,7 @@ static int __devinit azx_probe(struct pci_dev *pci,
        card->private_data = chip;
 
        /* create codec instances */
-       err = azx_codec_create(chip, model[dev], probe_mask[dev],
-                              probe_only[dev]);
+       err = azx_codec_create(chip, model[dev], probe_only[dev]);
        if (err < 0)
                goto out_free;
 
@@ -2457,12 +2510,17 @@ static struct pci_device_id azx_ids[] = {
        { PCI_DEVICE(0x10de, 0x0ac1), .driver_data = AZX_DRIVER_NVIDIA },
        { PCI_DEVICE(0x10de, 0x0ac2), .driver_data = AZX_DRIVER_NVIDIA },
        { PCI_DEVICE(0x10de, 0x0ac3), .driver_data = AZX_DRIVER_NVIDIA },
-       { PCI_DEVICE(0x10de, 0x0bd4), .driver_data = AZX_DRIVER_NVIDIA },
-       { PCI_DEVICE(0x10de, 0x0bd5), .driver_data = AZX_DRIVER_NVIDIA },
-       { PCI_DEVICE(0x10de, 0x0bd6), .driver_data = AZX_DRIVER_NVIDIA },
-       { PCI_DEVICE(0x10de, 0x0bd7), .driver_data = AZX_DRIVER_NVIDIA },
+       { PCI_DEVICE(0x10de, 0x0d94), .driver_data = AZX_DRIVER_NVIDIA },
+       { PCI_DEVICE(0x10de, 0x0d95), .driver_data = AZX_DRIVER_NVIDIA },
+       { PCI_DEVICE(0x10de, 0x0d96), .driver_data = AZX_DRIVER_NVIDIA },
+       { PCI_DEVICE(0x10de, 0x0d97), .driver_data = AZX_DRIVER_NVIDIA },
        /* Teradici */
        { PCI_DEVICE(0x6549, 0x1200), .driver_data = AZX_DRIVER_TERA },
+       /* Creative X-Fi (CA0110-IBG) */
+       { PCI_DEVICE(PCI_VENDOR_ID_CREATIVE, PCI_ANY_ID),
+         .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
+         .class_mask = 0xffffff,
+         .driver_data = AZX_DRIVER_GENERIC },
        /* 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,