diff options
author | Takashi Iwai <tiwai@suse.de> | 2009-03-18 10:09:13 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2009-03-19 07:53:58 -0400 |
commit | 97b71c94d691728b82052e9c4d6286fbc9965d7f (patch) | |
tree | b4a705037721a468234e13bd104e2f00f7940de8 /sound | |
parent | 4a1007934591fd0dcdf13454a6faebfcbe1a4ee6 (diff) |
ALSA: hda - Don't reset BDL unnecessarily
So far, the prepare callback is called multiple times, BDL entries
are reset and re-programmed at each time.
This patch adds the check to avoid the reset of BDL entries when the
same parameters are used.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/pci/hda/hda_intel.c | 46 |
1 files changed, 32 insertions, 14 deletions
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 6bcf5af6edce..ba97795d89c4 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -1076,8 +1076,7 @@ static int azx_setup_periods(struct azx *chip, | |||
1076 | azx_sd_writel(azx_dev, SD_BDLPL, 0); | 1076 | azx_sd_writel(azx_dev, SD_BDLPL, 0); |
1077 | azx_sd_writel(azx_dev, SD_BDLPU, 0); | 1077 | azx_sd_writel(azx_dev, SD_BDLPU, 0); |
1078 | 1078 | ||
1079 | period_bytes = snd_pcm_lib_period_bytes(substream); | 1079 | period_bytes = azx_dev->period_bytes; |
1080 | azx_dev->period_bytes = period_bytes; | ||
1081 | periods = azx_dev->bufsize / period_bytes; | 1080 | periods = azx_dev->bufsize / period_bytes; |
1082 | 1081 | ||
1083 | /* program the initial BDL entries */ | 1082 | /* program the initial BDL entries */ |
@@ -1124,9 +1123,6 @@ static int azx_setup_periods(struct azx *chip, | |||
1124 | error: | 1123 | error: |
1125 | snd_printk(KERN_ERR "Too many BDL entries: buffer=%d, period=%d\n", | 1124 | snd_printk(KERN_ERR "Too many BDL entries: buffer=%d, period=%d\n", |
1126 | azx_dev->bufsize, period_bytes); | 1125 | azx_dev->bufsize, period_bytes); |
1127 | /* reset */ | ||
1128 | azx_sd_writel(azx_dev, SD_BDLPL, 0); | ||
1129 | azx_sd_writel(azx_dev, SD_BDLPU, 0); | ||
1130 | return -EINVAL; | 1126 | return -EINVAL; |
1131 | } | 1127 | } |
1132 | 1128 | ||
@@ -1429,6 +1425,11 @@ static int azx_pcm_close(struct snd_pcm_substream *substream) | |||
1429 | static int azx_pcm_hw_params(struct snd_pcm_substream *substream, | 1425 | static int azx_pcm_hw_params(struct snd_pcm_substream *substream, |
1430 | struct snd_pcm_hw_params *hw_params) | 1426 | struct snd_pcm_hw_params *hw_params) |
1431 | { | 1427 | { |
1428 | struct azx_dev *azx_dev = get_azx_dev(substream); | ||
1429 | |||
1430 | azx_dev->bufsize = 0; | ||
1431 | azx_dev->period_bytes = 0; | ||
1432 | azx_dev->format_val = 0; | ||
1432 | return snd_pcm_lib_malloc_pages(substream, | 1433 | return snd_pcm_lib_malloc_pages(substream, |
1433 | params_buffer_bytes(hw_params)); | 1434 | params_buffer_bytes(hw_params)); |
1434 | } | 1435 | } |
@@ -1443,6 +1444,9 @@ static int azx_pcm_hw_free(struct snd_pcm_substream *substream) | |||
1443 | azx_sd_writel(azx_dev, SD_BDLPL, 0); | 1444 | azx_sd_writel(azx_dev, SD_BDLPL, 0); |
1444 | azx_sd_writel(azx_dev, SD_BDLPU, 0); | 1445 | azx_sd_writel(azx_dev, SD_BDLPU, 0); |
1445 | azx_sd_writel(azx_dev, SD_CTL, 0); | 1446 | azx_sd_writel(azx_dev, SD_CTL, 0); |
1447 | azx_dev->bufsize = 0; | ||
1448 | azx_dev->period_bytes = 0; | ||
1449 | azx_dev->format_val = 0; | ||
1446 | 1450 | ||
1447 | hinfo->ops.cleanup(hinfo, apcm->codec, substream); | 1451 | hinfo->ops.cleanup(hinfo, apcm->codec, substream); |
1448 | 1452 | ||
@@ -1456,23 +1460,37 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) | |||
1456 | struct azx_dev *azx_dev = get_azx_dev(substream); | 1460 | struct azx_dev *azx_dev = get_azx_dev(substream); |
1457 | struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream]; | 1461 | struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream]; |
1458 | struct snd_pcm_runtime *runtime = substream->runtime; | 1462 | struct snd_pcm_runtime *runtime = substream->runtime; |
1463 | unsigned int bufsize, period_bytes, format_val; | ||
1464 | int err; | ||
1459 | 1465 | ||
1460 | azx_dev->bufsize = snd_pcm_lib_buffer_bytes(substream); | 1466 | format_val = snd_hda_calc_stream_format(runtime->rate, |
1461 | azx_dev->format_val = snd_hda_calc_stream_format(runtime->rate, | 1467 | runtime->channels, |
1462 | runtime->channels, | 1468 | runtime->format, |
1463 | runtime->format, | 1469 | hinfo->maxbps); |
1464 | hinfo->maxbps); | 1470 | if (!format_val) { |
1465 | if (!azx_dev->format_val) { | ||
1466 | snd_printk(KERN_ERR SFX | 1471 | snd_printk(KERN_ERR SFX |
1467 | "invalid format_val, rate=%d, ch=%d, format=%d\n", | 1472 | "invalid format_val, rate=%d, ch=%d, format=%d\n", |
1468 | runtime->rate, runtime->channels, runtime->format); | 1473 | runtime->rate, runtime->channels, runtime->format); |
1469 | return -EINVAL; | 1474 | return -EINVAL; |
1470 | } | 1475 | } |
1471 | 1476 | ||
1477 | bufsize = snd_pcm_lib_buffer_bytes(substream); | ||
1478 | period_bytes = snd_pcm_lib_period_bytes(substream); | ||
1479 | |||
1472 | snd_printdd("azx_pcm_prepare: bufsize=0x%x, format=0x%x\n", | 1480 | snd_printdd("azx_pcm_prepare: bufsize=0x%x, format=0x%x\n", |
1473 | azx_dev->bufsize, azx_dev->format_val); | 1481 | bufsize, format_val); |
1474 | if (azx_setup_periods(chip, substream, azx_dev) < 0) | 1482 | |
1475 | return -EINVAL; | 1483 | if (bufsize != azx_dev->bufsize || |
1484 | period_bytes != azx_dev->period_bytes || | ||
1485 | format_val != azx_dev->format_val) { | ||
1486 | azx_dev->bufsize = bufsize; | ||
1487 | azx_dev->period_bytes = period_bytes; | ||
1488 | azx_dev->format_val = format_val; | ||
1489 | err = azx_setup_periods(chip, substream, azx_dev); | ||
1490 | if (err < 0) | ||
1491 | return err; | ||
1492 | } | ||
1493 | |||
1476 | azx_setup_controller(chip, azx_dev); | 1494 | azx_setup_controller(chip, azx_dev); |
1477 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 1495 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
1478 | azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1; | 1496 | azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1; |