ALSA: hda - Fixes distorted recording on US15W chipset
[safe/jmp/linux-2.6] / sound / pci / hda / hda_intel.c
index 236b4ca..cad9b70 100644 (file)
@@ -425,7 +425,7 @@ struct azx {
        struct snd_dma_buffer posbuf;
 
        /* flags */
-       int position_fix;
+       int position_fix[2]; /* for both playback/capture streams */
        int poll_count;
        unsigned int running :1;
        unsigned int initialized :1;
@@ -1306,8 +1306,10 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
        azx_sd_writel(azx_dev, SD_BDLPU, upper_32_bits(azx_dev->bdl.addr));
 
        /* enable the position buffer */
-       if (chip->position_fix == POS_FIX_POSBUF ||
-           chip->position_fix == POS_FIX_AUTO ||
+       if (chip->position_fix[0] == POS_FIX_POSBUF ||
+           chip->position_fix[0] == POS_FIX_AUTO ||
+           chip->position_fix[1] == POS_FIX_POSBUF ||
+           chip->position_fix[1] == POS_FIX_AUTO ||
            chip->via_dmapos_patch) {
                if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE))
                        azx_writel(chip, DPLBASE,
@@ -1847,13 +1849,16 @@ static unsigned int azx_get_position(struct azx *chip,
 
        if (chip->via_dmapos_patch)
                pos = azx_via_get_position(chip, azx_dev);
-       else if (chip->position_fix == POS_FIX_POSBUF ||
-                chip->position_fix == POS_FIX_AUTO) {
-               /* use the position buffer */
-               pos = le32_to_cpu(*azx_dev->posbuf);
-       } else {
-               /* read LPIB */
-               pos = azx_sd_readl(azx_dev, SD_LPIB);
+       else {
+               int stream = azx_dev->substream->stream;
+               if (chip->position_fix[stream] == POS_FIX_POSBUF ||
+                   chip->position_fix[stream] == POS_FIX_AUTO) {
+                       /* use the position buffer */
+                       pos = le32_to_cpu(*azx_dev->posbuf);
+               } else {
+                       /* read LPIB */
+                       pos = azx_sd_readl(azx_dev, SD_LPIB);
+               }
        }
        if (pos >= azx_dev->bufsize)
                pos = 0;
@@ -1881,22 +1886,24 @@ static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream)
 static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev)
 {
        unsigned int pos;
+       int stream;
 
        if (azx_dev->start_flag &&
            time_before_eq(jiffies, azx_dev->start_jiffies))
                return -1;      /* bogus (too early) interrupt */
        azx_dev->start_flag = 0;
 
+       stream = azx_dev->substream->stream;
        pos = azx_get_position(chip, azx_dev);
-       if (chip->position_fix == POS_FIX_AUTO) {
+       if (chip->position_fix[stream] == POS_FIX_AUTO) {
                if (!pos) {
                        printk(KERN_WARNING
                               "hda-intel: Invalid position buffer, "
                               "using LPIB read method instead.\n");
-                       chip->position_fix = POS_FIX_LPIB;
+                       chip->position_fix[stream] = POS_FIX_LPIB;
                        pos = azx_get_position(chip, azx_dev);
                } else
-                       chip->position_fix = POS_FIX_POSBUF;
+                       chip->position_fix[stream] = POS_FIX_POSBUF;
        }
 
        if (!bdl_pos_adj[chip->dev_index])
@@ -2435,7 +2442,8 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
        chip->dev_index = dev;
        INIT_WORK(&chip->irq_pending_work, azx_irq_pending_work);
 
-       chip->position_fix = check_position_fix(chip, position_fix[dev]);
+       chip->position_fix[0] = chip->position_fix[1] =
+               check_position_fix(chip, position_fix[dev]);
        check_probe_mask(chip, dev);
 
        chip->single_cmd = single_cmd;