diff options
-rw-r--r-- | include/sound/pcm.h | 2 | ||||
-rw-r--r-- | sound/core/pcm_lib.c | 23 | ||||
-rw-r--r-- | sound/pci/sis7019.c | 16 |
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 { | |||
317 | struct snd_pcm_mmap_control *control; | 317 | struct snd_pcm_mmap_control *control; |
318 | 318 | ||
319 | /* -- locking / scheduling -- */ | 319 | /* -- locking / scheduling -- */ |
320 | unsigned int twake: 1; /* do transfer (!poll) wakeup */ | 320 | snd_pcm_uframes_t twake; /* do transfer (!poll) wakeup if non-zero */ |
321 | wait_queue_head_t sleep; /* poll sleep */ | 321 | wait_queue_head_t sleep; /* poll sleep */ |
322 | wait_queue_head_t tsleep; /* transfer sleep */ | 322 | wait_queue_head_t tsleep; /* transfer sleep */ |
323 | struct fasync_struct *fasync; | 323 | 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, | |||
287 | return -EPIPE; | 287 | return -EPIPE; |
288 | } | 288 | } |
289 | } | 289 | } |
290 | if (avail >= runtime->control->avail_min) | 290 | if (runtime->twake) { |
291 | wake_up(runtime->twake ? &runtime->tsleep : &runtime->sleep); | 291 | if (avail >= runtime->twake) |
292 | wake_up(&runtime->tsleep); | ||
293 | } else if (avail >= runtime->control->avail_min) | ||
294 | wake_up(&runtime->sleep); | ||
292 | return 0; | 295 | return 0; |
293 | } | 296 | } |
294 | 297 | ||
@@ -1707,7 +1710,7 @@ EXPORT_SYMBOL(snd_pcm_period_elapsed); | |||
1707 | * The available space is stored on availp. When err = 0 and avail = 0 | 1710 | * The available space is stored on availp. When err = 0 and avail = 0 |
1708 | * on the capture stream, it indicates the stream is in DRAINING state. | 1711 | * on the capture stream, it indicates the stream is in DRAINING state. |
1709 | */ | 1712 | */ |
1710 | static int wait_for_avail_min(struct snd_pcm_substream *substream, | 1713 | static int wait_for_avail(struct snd_pcm_substream *substream, |
1711 | snd_pcm_uframes_t *availp) | 1714 | snd_pcm_uframes_t *availp) |
1712 | { | 1715 | { |
1713 | struct snd_pcm_runtime *runtime = substream->runtime; | 1716 | struct snd_pcm_runtime *runtime = substream->runtime; |
@@ -1757,7 +1760,7 @@ static int wait_for_avail_min(struct snd_pcm_substream *substream, | |||
1757 | avail = snd_pcm_playback_avail(runtime); | 1760 | avail = snd_pcm_playback_avail(runtime); |
1758 | else | 1761 | else |
1759 | avail = snd_pcm_capture_avail(runtime); | 1762 | avail = snd_pcm_capture_avail(runtime); |
1760 | if (avail >= runtime->control->avail_min) | 1763 | if (avail >= runtime->twake) |
1761 | break; | 1764 | break; |
1762 | } | 1765 | } |
1763 | _endloop: | 1766 | _endloop: |
@@ -1820,7 +1823,7 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream, | |||
1820 | goto _end_unlock; | 1823 | goto _end_unlock; |
1821 | } | 1824 | } |
1822 | 1825 | ||
1823 | runtime->twake = 1; | 1826 | runtime->twake = runtime->control->avail_min ? : 1; |
1824 | while (size > 0) { | 1827 | while (size > 0) { |
1825 | snd_pcm_uframes_t frames, appl_ptr, appl_ofs; | 1828 | snd_pcm_uframes_t frames, appl_ptr, appl_ofs; |
1826 | snd_pcm_uframes_t avail; | 1829 | snd_pcm_uframes_t avail; |
@@ -1833,7 +1836,9 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream, | |||
1833 | err = -EAGAIN; | 1836 | err = -EAGAIN; |
1834 | goto _end_unlock; | 1837 | goto _end_unlock; |
1835 | } | 1838 | } |
1836 | err = wait_for_avail_min(substream, &avail); | 1839 | runtime->twake = min_t(snd_pcm_uframes_t, size, |
1840 | runtime->control->avail_min ? : 1); | ||
1841 | err = wait_for_avail(substream, &avail); | ||
1837 | if (err < 0) | 1842 | if (err < 0) |
1838 | goto _end_unlock; | 1843 | goto _end_unlock; |
1839 | } | 1844 | } |
@@ -2042,7 +2047,7 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream, | |||
2042 | goto _end_unlock; | 2047 | goto _end_unlock; |
2043 | } | 2048 | } |
2044 | 2049 | ||
2045 | runtime->twake = 1; | 2050 | runtime->twake = runtime->control->avail_min ? : 1; |
2046 | while (size > 0) { | 2051 | while (size > 0) { |
2047 | snd_pcm_uframes_t frames, appl_ptr, appl_ofs; | 2052 | snd_pcm_uframes_t frames, appl_ptr, appl_ofs; |
2048 | snd_pcm_uframes_t avail; | 2053 | snd_pcm_uframes_t avail; |
@@ -2060,7 +2065,9 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream, | |||
2060 | err = -EAGAIN; | 2065 | err = -EAGAIN; |
2061 | goto _end_unlock; | 2066 | goto _end_unlock; |
2062 | } | 2067 | } |
2063 | err = wait_for_avail_min(substream, &avail); | 2068 | runtime->twake = min_t(snd_pcm_uframes_t, size, |
2069 | runtime->control->avail_min ? : 1); | ||
2070 | err = wait_for_avail(substream, &avail); | ||
2064 | if (err < 0) | 2071 | if (err < 0) |
2065 | goto _end_unlock; | 2072 | goto _end_unlock; |
2066 | if (!avail) | 2073 | 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) | |||
264 | * if using small periods. | 264 | * if using small periods. |
265 | * | 265 | * |
266 | * If we're less than 9 samples behind, we're on target. | 266 | * If we're less than 9 samples behind, we're on target. |
267 | * Otherwise, shorten the next vperiod by the amount we've | ||
268 | * been delayed. | ||
267 | */ | 269 | */ |
268 | if (sync > -9) | 270 | if (sync > -9) |
269 | voice->vperiod = voice->sync_period_size + 1; | 271 | voice->vperiod = voice->sync_period_size + 1; |
270 | else | 272 | else |
271 | voice->vperiod = voice->sync_period_size - 4; | 273 | voice->vperiod = voice->sync_period_size + sync + 10; |
272 | 274 | ||
273 | if (voice->vperiod < voice->buffer_size) { | 275 | if (voice->vperiod < voice->buffer_size) { |
274 | sis_update_sso(voice, voice->vperiod); | 276 | sis_update_sso(voice, voice->vperiod); |
@@ -736,7 +738,7 @@ static void sis_prepare_timing_voice(struct voice *voice, | |||
736 | period_size = buffer_size; | 738 | period_size = buffer_size; |
737 | 739 | ||
738 | /* Initially, we want to interrupt just a bit behind the end of | 740 | /* Initially, we want to interrupt just a bit behind the end of |
739 | * the period we're clocking out. 10 samples seems to give a good | 741 | * the period we're clocking out. 12 samples seems to give a good |
740 | * delay. | 742 | * delay. |
741 | * | 743 | * |
742 | * We want to spread our interrupts throughout the virtual period, | 744 | * We want to spread our interrupts throughout the virtual period, |
@@ -747,7 +749,7 @@ static void sis_prepare_timing_voice(struct voice *voice, | |||
747 | * | 749 | * |
748 | * This is all moot if we don't need to use virtual periods. | 750 | * This is all moot if we don't need to use virtual periods. |
749 | */ | 751 | */ |
750 | vperiod = runtime->period_size + 10; | 752 | vperiod = runtime->period_size + 12; |
751 | if (vperiod > period_size) { | 753 | if (vperiod > period_size) { |
752 | u16 tail = vperiod % period_size; | 754 | u16 tail = vperiod % period_size; |
753 | u16 quarter_period = period_size / 4; | 755 | u16 quarter_period = period_size / 4; |
@@ -776,7 +778,7 @@ static void sis_prepare_timing_voice(struct voice *voice, | |||
776 | */ | 778 | */ |
777 | timing->flags |= VOICE_SYNC_TIMING; | 779 | timing->flags |= VOICE_SYNC_TIMING; |
778 | timing->sync_base = voice->ctrl_base; | 780 | timing->sync_base = voice->ctrl_base; |
779 | timing->sync_cso = runtime->period_size - 1; | 781 | timing->sync_cso = runtime->period_size; |
780 | timing->sync_period_size = runtime->period_size; | 782 | timing->sync_period_size = runtime->period_size; |
781 | timing->sync_buffer_size = runtime->buffer_size; | 783 | timing->sync_buffer_size = runtime->buffer_size; |
782 | timing->period_size = period_size; | 784 | timing->period_size = period_size; |
@@ -1047,7 +1049,7 @@ static int sis_chip_free(struct sis7019 *sis) | |||
1047 | /* Reset the chip, and disable all interrputs. | 1049 | /* Reset the chip, and disable all interrputs. |
1048 | */ | 1050 | */ |
1049 | outl(SIS_GCR_SOFTWARE_RESET, sis->ioport + SIS_GCR); | 1051 | outl(SIS_GCR_SOFTWARE_RESET, sis->ioport + SIS_GCR); |
1050 | udelay(10); | 1052 | udelay(25); |
1051 | outl(0, sis->ioport + SIS_GCR); | 1053 | outl(0, sis->ioport + SIS_GCR); |
1052 | outl(0, sis->ioport + SIS_GIER); | 1054 | outl(0, sis->ioport + SIS_GIER); |
1053 | 1055 | ||
@@ -1083,7 +1085,7 @@ static int sis_chip_init(struct sis7019 *sis) | |||
1083 | /* Reset the audio controller | 1085 | /* Reset the audio controller |
1084 | */ | 1086 | */ |
1085 | outl(SIS_GCR_SOFTWARE_RESET, io + SIS_GCR); | 1087 | outl(SIS_GCR_SOFTWARE_RESET, io + SIS_GCR); |
1086 | udelay(10); | 1088 | udelay(25); |
1087 | outl(0, io + SIS_GCR); | 1089 | outl(0, io + SIS_GCR); |
1088 | 1090 | ||
1089 | /* Get the AC-link semaphore, and reset the codecs | 1091 | /* Get the AC-link semaphore, and reset the codecs |
@@ -1096,7 +1098,7 @@ static int sis_chip_init(struct sis7019 *sis) | |||
1096 | return -EIO; | 1098 | return -EIO; |
1097 | 1099 | ||
1098 | outl(SIS_AC97_CMD_CODEC_COLD_RESET, io + SIS_AC97_CMD); | 1100 | outl(SIS_AC97_CMD_CODEC_COLD_RESET, io + SIS_AC97_CMD); |
1099 | udelay(10); | 1101 | udelay(250); |
1100 | 1102 | ||
1101 | count = 0xffff; | 1103 | count = 0xffff; |
1102 | while ((inw(io + SIS_AC97_STATUS) & SIS_AC97_STATUS_BUSY) && --count) | 1104 | while ((inw(io + SIS_AC97_STATUS) & SIS_AC97_STATUS_BUSY) && --count) |