summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/sound/pcm.h2
-rw-r--r--sound/core/pcm_lib.c23
-rw-r--r--sound/pci/sis7019.c16
3 files changed, 25 insertions, 16 deletions
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 07fd630db88d..304025b23520 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -317,7 +317,7 @@ struct snd_pcm_runtime {
struct snd_pcm_mmap_control *control;
/* -- locking / scheduling -- */
- unsigned int twake: 1; /* do transfer (!poll) wakeup */
+ snd_pcm_uframes_t twake; /* do transfer (!poll) wakeup if non-zero */
wait_queue_head_t sleep; /* poll sleep */
wait_queue_head_t tsleep; /* transfer sleep */
struct fasync_struct *fasync;
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index e9d98be190c5..bcf95d3ff5c7 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -287,8 +287,11 @@ int snd_pcm_update_state(struct snd_pcm_substream *substream,
return -EPIPE;
}
}
- if (avail >= runtime->control->avail_min)
- wake_up(runtime->twake ? &runtime->tsleep : &runtime->sleep);
+ if (runtime->twake) {
+ if (avail >= runtime->twake)
+ wake_up(&runtime->tsleep);
+ } else if (avail >= runtime->control->avail_min)
+ wake_up(&runtime->sleep);
return 0;
}
@@ -1707,7 +1710,7 @@ EXPORT_SYMBOL(snd_pcm_period_elapsed);
* The available space is stored on availp. When err = 0 and avail = 0
* on the capture stream, it indicates the stream is in DRAINING state.
*/
-static int wait_for_avail_min(struct snd_pcm_substream *substream,
+static int wait_for_avail(struct snd_pcm_substream *substream,
snd_pcm_uframes_t *availp)
{
struct snd_pcm_runtime *runtime = substream->runtime;
@@ -1757,7 +1760,7 @@ static int wait_for_avail_min(struct snd_pcm_substream *substream,
avail = snd_pcm_playback_avail(runtime);
else
avail = snd_pcm_capture_avail(runtime);
- if (avail >= runtime->control->avail_min)
+ if (avail >= runtime->twake)
break;
}
_endloop:
@@ -1820,7 +1823,7 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream,
goto _end_unlock;
}
- runtime->twake = 1;
+ runtime->twake = runtime->control->avail_min ? : 1;
while (size > 0) {
snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
snd_pcm_uframes_t avail;
@@ -1833,7 +1836,9 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream,
err = -EAGAIN;
goto _end_unlock;
}
- err = wait_for_avail_min(substream, &avail);
+ runtime->twake = min_t(snd_pcm_uframes_t, size,
+ runtime->control->avail_min ? : 1);
+ err = wait_for_avail(substream, &avail);
if (err < 0)
goto _end_unlock;
}
@@ -2042,7 +2047,7 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
goto _end_unlock;
}
- runtime->twake = 1;
+ runtime->twake = runtime->control->avail_min ? : 1;
while (size > 0) {
snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
snd_pcm_uframes_t avail;
@@ -2060,7 +2065,9 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
err = -EAGAIN;
goto _end_unlock;
}
- err = wait_for_avail_min(substream, &avail);
+ runtime->twake = min_t(snd_pcm_uframes_t, size,
+ runtime->control->avail_min ? : 1);
+ err = wait_for_avail(substream, &avail);
if (err < 0)
goto _end_unlock;
if (!avail)
diff --git a/sound/pci/sis7019.c b/sound/pci/sis7019.c
index 9cc1b5aa0148..1b8f6742b5fa 100644
--- a/sound/pci/sis7019.c
+++ b/sound/pci/sis7019.c
@@ -264,11 +264,13 @@ static void sis_update_voice(struct voice *voice)
* if using small periods.
*
* If we're less than 9 samples behind, we're on target.
+ * Otherwise, shorten the next vperiod by the amount we've
+ * been delayed.
*/
if (sync > -9)
voice->vperiod = voice->sync_period_size + 1;
else
- voice->vperiod = voice->sync_period_size - 4;
+ voice->vperiod = voice->sync_period_size + sync + 10;
if (voice->vperiod < voice->buffer_size) {
sis_update_sso(voice, voice->vperiod);
@@ -736,7 +738,7 @@ static void sis_prepare_timing_voice(struct voice *voice,
period_size = buffer_size;
/* Initially, we want to interrupt just a bit behind the end of
- * the period we're clocking out. 10 samples seems to give a good
+ * the period we're clocking out. 12 samples seems to give a good
* delay.
*
* We want to spread our interrupts throughout the virtual period,
@@ -747,7 +749,7 @@ static void sis_prepare_timing_voice(struct voice *voice,
*
* This is all moot if we don't need to use virtual periods.
*/
- vperiod = runtime->period_size + 10;
+ vperiod = runtime->period_size + 12;
if (vperiod > period_size) {
u16 tail = vperiod % period_size;
u16 quarter_period = period_size / 4;
@@ -776,7 +778,7 @@ static void sis_prepare_timing_voice(struct voice *voice,
*/
timing->flags |= VOICE_SYNC_TIMING;
timing->sync_base = voice->ctrl_base;
- timing->sync_cso = runtime->period_size - 1;
+ timing->sync_cso = runtime->period_size;
timing->sync_period_size = runtime->period_size;
timing->sync_buffer_size = runtime->buffer_size;
timing->period_size = period_size;
@@ -1047,7 +1049,7 @@ static int sis_chip_free(struct sis7019 *sis)
/* Reset the chip, and disable all interrputs.
*/
outl(SIS_GCR_SOFTWARE_RESET, sis->ioport + SIS_GCR);
- udelay(10);
+ udelay(25);
outl(0, sis->ioport + SIS_GCR);
outl(0, sis->ioport + SIS_GIER);
@@ -1083,7 +1085,7 @@ static int sis_chip_init(struct sis7019 *sis)
/* Reset the audio controller
*/
outl(SIS_GCR_SOFTWARE_RESET, io + SIS_GCR);
- udelay(10);
+ udelay(25);
outl(0, io + SIS_GCR);
/* Get the AC-link semaphore, and reset the codecs
@@ -1096,7 +1098,7 @@ static int sis_chip_init(struct sis7019 *sis)
return -EIO;
outl(SIS_AC97_CMD_CODEC_COLD_RESET, io + SIS_AC97_CMD);
- udelay(10);
+ udelay(250);
count = 0xffff;
while ((inw(io + SIS_AC97_STATUS) & SIS_AC97_STATUS_BUSY) && --count)