aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2009-03-18 10:09:13 -0400
committerTakashi Iwai <tiwai@suse.de>2009-03-19 07:53:58 -0400
commit97b71c94d691728b82052e9c4d6286fbc9965d7f (patch)
treeb4a705037721a468234e13bd104e2f00f7940de8 /sound/pci
parent4a1007934591fd0dcdf13454a6faebfcbe1a4ee6 (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/pci')
-rw-r--r--sound/pci/hda/hda_intel.c46
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)
1429static int azx_pcm_hw_params(struct snd_pcm_substream *substream, 1425static 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;