--- /dev/null
+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)