]> git.ipfire.org Git - ipfire-2.x.git/blobdiff - src/patches/suse-2.6.27.31/patches.drivers/alsa-post-ga-hda-intel-cleanup
Reenabled linux-xen, added patches for Xen Kernel Version 2.6.27.31,
[ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.drivers / alsa-post-ga-hda-intel-cleanup
diff --git a/src/patches/suse-2.6.27.31/patches.drivers/alsa-post-ga-hda-intel-cleanup b/src/patches/suse-2.6.27.31/patches.drivers/alsa-post-ga-hda-intel-cleanup
new file mode 100644 (file)
index 0000000..3abc24e
--- /dev/null
@@ -0,0 +1,232 @@
+From: Takashi Iwai <tiwai@suse.de>
+Subject: ALSA: hda - clean up hda_intel.c
+Patch-mainline: 2.6.30-rc1
+References: bnc#502733
+
+Clean up hda_intel.c for error path.
+Also clean up / optimization for stream setups.
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+
+---
+ sound/pci/hda/hda_intel.c |  112 +++++++++++++++++++++++++++-------------------
+ 1 file changed, 67 insertions(+), 45 deletions(-)
+
+--- a/sound/pci/hda/hda_intel.c
++++ b/sound/pci/hda/hda_intel.c
+@@ -848,13 +848,18 @@ static void azx_stream_start(struct azx
+                     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));
+@@ -1067,8 +1072,7 @@ static int azx_setup_periods(struct azx
+       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 */
+@@ -1115,24 +1119,17 @@ static int azx_setup_periods(struct azx
+  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);
+@@ -1149,7 +1146,15 @@ static int azx_setup_controller(struct a
+       while (((val = azx_sd_readb(azx_dev, SD_CTL)) & SD_CTL_STREAM_RESET) &&
+              --timeout)
+               ;
++}
++/*
++ * 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)|
+@@ -1390,6 +1395,8 @@ static int azx_pcm_open(struct snd_pcm_s
+       runtime->private_data = azx_dev;
+       snd_pcm_set_sync(substream);
+       mutex_unlock(&chip->open_mutex);
++
++      azx_stream_reset(chip, azx_dev);
+       return 0;
+ }
+@@ -1416,6 +1423,11 @@ static int azx_pcm_close(struct snd_pcm_
+ 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));
+ }
+@@ -1430,6 +1442,9 @@ static int azx_pcm_hw_free(struct snd_pc
+       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);
+@@ -1443,23 +1458,37 @@ static int azx_pcm_prepare(struct snd_pc
+       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) {
++      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_setup_controller(chip, azx_dev);
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1;
+@@ -2373,40 +2402,30 @@ static int __devinit azx_probe(struct pc
+       }
+       err = azx_create(card, pci, dev, pci_id->driver_data, &chip);
+-      if (err < 0) {
+-              snd_card_free(card);
+-              return err;
+-      }
++      if (err < 0)
++              goto out_free;
+       card->private_data = chip;
+       /* create codec instances */
+       err = azx_codec_create(chip, model[dev], probe_mask[dev]);
+-      if (err < 0) {
+-              snd_card_free(card);
+-              return err;
+-      }
++      if (err < 0)
++              goto out_free;
+       /* create PCM streams */
+       err = azx_pcm_create(chip);
+-      if (err < 0) {
+-              snd_card_free(card);
+-              return err;
+-      }
++      if (err < 0)
++              goto out_free;
+       /* create mixer controls */
+       err = azx_mixer_create(chip);
+-      if (err < 0) {
+-              snd_card_free(card);
+-              return err;
+-      }
++      if (err < 0)
++              goto out_free;
+       snd_card_set_dev(card, &pci->dev);
+       err = snd_card_register(card);
+-      if (err < 0) {
+-              snd_card_free(card);
+-              return err;
+-      }
++      if (err < 0)
++              goto out_free;
+       pci_set_drvdata(pci, card);
+       chip->running = 1;
+@@ -2415,6 +2434,9 @@ static int __devinit azx_probe(struct pc
+       dev++;
+       return err;
++out_free:
++      snd_card_free(card);
++      return err;
+ }
+ static void __devexit azx_remove(struct pci_dev *pci)