/[pkgs]/rpms/kernel/F-10/alsa-rewrite-hw_ptr-updaters.patch
ViewVC logotype

Contents of /rpms/kernel/F-10/alsa-rewrite-hw_ptr-updaters.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (show annotations) (download) (as text)
Wed Mar 25 19:45:52 2009 UTC (8 months ago) by cebbert
Branch: MAIN
CVS Tags: kernel-2_6_29-13_fc10, kernel-2_6_29_3-60_fc10, kernel-2_6_29_6-99_fc10, kernel-2_6_29_1-38_fc10, kernel-2_6_29_2-45_rc1_fc10, kernel-2_6_29_2-48_rc1_fc10, kernel-2_6_29-10_fc10, kernel-2_6_29_5-88_fc10, kernel-2_6_29_2-55_fc10, kernel-2_6_29_1-41_fc10, kernel-2_6_29_1-42_fc10, kernel-2_6_29_1-36_fc10, kernel-2_6_29_5-84_fc10, kernel-2_6_29_2-52_fc10, kernel-2_6_29_4-75_fc10, kernel-2_6_29_4-80_fc10, kernel-2_6_29_1-30_fc10, kernel-2_6_29_6-93_fc10, kernel-2_6_29_6-97_fc10, kernel-2_6_29_4-72_fc10, kernel-2_6_29_1-15_fc10, HEAD
File MIME type: text/x-patch
Copy alsa-rewrite-hw_ptr-updaters.patch from F11:
  snd_pcm_update_hw_ptr() tries to detect the unexpected hwptr
  jumps more strictly to avoid the position mess-up, which often
  results in the bad quality I/O with pulseaudio.
1 From: Takashi Iwai <tiwai@suse.de>
2 Date: Tue, 3 Mar 2009 16:00:15 +0000 (+0100)
3 Subject: ALSA: Rewrite hw_ptr updaters
4 X-Git-Url: http://git.alsa-project.org/?p=alsa-kernel.git;a=commitdiff_plain;h=070397989dc29a6067cb51989ab3d5efc82a6790
5
6 ALSA: Rewrite hw_ptr updaters
7
8 Clean up and improve snd_pcm_update_hw_ptr*() functions.
9
10 snd_pcm_update_hw_ptr() tries to detect the unexpected hwptr jumps
11 more strictly to avoid the position mess-up, which often results in
12 the bad quality I/O with pulseaudio.
13
14 The hw-ptr skip error messages are printed when xrun proc is set to
15 non-zero.
16
17 Signed-off-by: Takashi Iwai <tiwai@suse.de>
18 Signed-off-by: Jaroslav Kysela <perex@perex.cz>
19 ---
20
21 diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
22 index 9216910..86ac9ae 100644
23 --- a/sound/core/pcm_lib.c
24 +++ b/sound/core/pcm_lib.c
25 @@ -125,19 +125,27 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram
26 }
27 }
28
29 +#ifdef CONFIG_SND_PCM_XRUN_DEBUG
30 +#define xrun_debug(substream) ((substream)->pstr->xrun_debug)
31 +#else
32 +#define xrun_debug(substream) 0
33 +#endif
34 +
35 +#define dump_stack_on_xrun(substream) do { \
36 + if (xrun_debug(substream) > 1) \
37 + dump_stack(); \
38 + } while (0)
39 +
40 static void xrun(struct snd_pcm_substream *substream)
41 {
42 snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
43 -#ifdef CONFIG_SND_PCM_XRUN_DEBUG
44 - if (substream->pstr->xrun_debug) {
45 + if (xrun_debug(substream)) {
46 snd_printd(KERN_DEBUG "XRUN: pcmC%dD%d%c\n",
47 substream->pcm->card->number,
48 substream->pcm->device,
49 substream->stream ? 'c' : 'p');
50 - if (substream->pstr->xrun_debug > 1)
51 - dump_stack();
52 + dump_stack_on_xrun(substream);
53 }
54 -#endif
55 }
56
57 static inline snd_pcm_uframes_t snd_pcm_update_hw_ptr_pos(struct snd_pcm_substream *substream,
58 @@ -182,11 +190,21 @@ static inline int snd_pcm_update_hw_ptr_post(struct snd_pcm_substream *substream
59 return 0;
60 }
61
62 +#define hw_ptr_error(substream, fmt, args...) \
63 + do { \
64 + if (xrun_debug(substream)) { \
65 + if (printk_ratelimit()) { \
66 + snd_printd("hda_codec: " fmt, ##args); \
67 + } \
68 + dump_stack_on_xrun(substream); \
69 + } \
70 + } while (0)
71 +
72 static inline int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream)
73 {
74 struct snd_pcm_runtime *runtime = substream->runtime;
75 snd_pcm_uframes_t pos;
76 - snd_pcm_uframes_t new_hw_ptr, hw_ptr_interrupt;
77 + snd_pcm_uframes_t new_hw_ptr, hw_ptr_interrupt, hw_base;
78 snd_pcm_sframes_t delta;
79
80 pos = snd_pcm_update_hw_ptr_pos(substream, runtime);
81 @@ -194,36 +212,47 @@ static inline int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *subs
82 xrun(substream);
83 return -EPIPE;
84 }
85 - if (runtime->period_size == runtime->buffer_size)
86 - goto __next_buf;
87 - new_hw_ptr = runtime->hw_ptr_base + pos;
88 + hw_base = runtime->hw_ptr_base;
89 + new_hw_ptr = hw_base + pos;
90 hw_ptr_interrupt = runtime->hw_ptr_interrupt + runtime->period_size;
91 -
92 - delta = hw_ptr_interrupt - new_hw_ptr;
93 - if (delta > 0) {
94 - if ((snd_pcm_uframes_t)delta < runtime->buffer_size / 2) {
95 -#ifdef CONFIG_SND_PCM_XRUN_DEBUG
96 - if (runtime->periods > 1 && substream->pstr->xrun_debug) {
97 - snd_printd(KERN_ERR "Unexpected hw_pointer value [1] (stream = %i, delta: -%ld, max jitter = %ld): wrong interrupt acknowledge?\n", substream->stream, (long) delta, runtime->buffer_size / 2);
98 - if (substream->pstr->xrun_debug > 1)
99 - dump_stack();
100 - }
101 -#endif
102 - return 0;
103 + delta = new_hw_ptr - hw_ptr_interrupt;
104 + if (hw_ptr_interrupt == runtime->boundary)
105 + hw_ptr_interrupt = 0;
106 + if (delta < 0) {
107 + delta += runtime->buffer_size;
108 + if (delta < 0) {
109 + hw_ptr_error(substream,
110 + "Unexpected hw_pointer value "
111 + "(stream=%i, pos=%ld, intr_ptr=%ld)\n",
112 + substream->stream, (long)pos,
113 + (long)hw_ptr_interrupt);
114 + /* rebase to interrupt position */
115 + hw_base = new_hw_ptr = hw_ptr_interrupt;
116 + delta = 0;
117 + } else {
118 + hw_base += runtime->buffer_size;
119 + if (hw_base == runtime->boundary)
120 + hw_base = 0;
121 + new_hw_ptr = hw_base + pos;
122 }
123 - __next_buf:
124 - runtime->hw_ptr_base += runtime->buffer_size;
125 - if (runtime->hw_ptr_base == runtime->boundary)
126 - runtime->hw_ptr_base = 0;
127 - new_hw_ptr = runtime->hw_ptr_base + pos;
128 }
129 -
130 + if (delta > runtime->period_size) {
131 + hw_ptr_error(substream,
132 + "Lost interrupts? "
133 + "(stream=%i, delta=%ld, intr_ptr=%ld)\n",
134 + substream->stream, (long)delta,
135 + (long)hw_ptr_interrupt);
136 + /* rebase hw_ptr_interrupt */
137 + hw_ptr_interrupt =
138 + new_hw_ptr - new_hw_ptr % runtime->period_size;
139 + }
140 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
141 runtime->silence_size > 0)
142 snd_pcm_playback_silence(substream, new_hw_ptr);
143
144 + runtime->hw_ptr_base = hw_base;
145 runtime->status->hw_ptr = new_hw_ptr;
146 - runtime->hw_ptr_interrupt = new_hw_ptr - new_hw_ptr % runtime->period_size;
147 + runtime->hw_ptr_interrupt = hw_ptr_interrupt;
148
149 return snd_pcm_update_hw_ptr_post(substream, runtime);
150 }
151 @@ -233,7 +262,7 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream)
152 {
153 struct snd_pcm_runtime *runtime = substream->runtime;
154 snd_pcm_uframes_t pos;
155 - snd_pcm_uframes_t old_hw_ptr, new_hw_ptr;
156 + snd_pcm_uframes_t old_hw_ptr, new_hw_ptr, hw_base;
157 snd_pcm_sframes_t delta;
158
159 old_hw_ptr = runtime->status->hw_ptr;
160 @@ -242,29 +271,38 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream)
161 xrun(substream);
162 return -EPIPE;
163 }
164 - new_hw_ptr = runtime->hw_ptr_base + pos;
165 -
166 - delta = old_hw_ptr - new_hw_ptr;
167 - if (delta > 0) {
168 - if ((snd_pcm_uframes_t)delta < runtime->buffer_size / 2) {
169 -#ifdef CONFIG_SND_PCM_XRUN_DEBUG
170 - if (runtime->periods > 2 && substream->pstr->xrun_debug) {
171 - snd_printd(KERN_ERR "Unexpected hw_pointer value [2] (stream = %i, delta: -%ld, max jitter = %ld): wrong interrupt acknowledge?\n", substream->stream, (long) delta, runtime->buffer_size / 2);
172 - if (substream->pstr->xrun_debug > 1)
173 - dump_stack();
174 - }
175 -#endif
176 + hw_base = runtime->hw_ptr_base;
177 + new_hw_ptr = hw_base + pos;
178 +
179 + delta = new_hw_ptr - old_hw_ptr;
180 + if (delta < 0) {
181 + delta += runtime->buffer_size;
182 + if (delta < 0) {
183 + hw_ptr_error(substream,
184 + "Unexpected hw_pointer value [2] "
185 + "(stream=%i, pos=%ld, old_ptr=%ld)\n",
186 + substream->stream, (long)pos,
187 + (long)old_hw_ptr);
188 return 0;
189 }
190 - runtime->hw_ptr_base += runtime->buffer_size;
191 - if (runtime->hw_ptr_base == runtime->boundary)
192 - runtime->hw_ptr_base = 0;
193 - new_hw_ptr = runtime->hw_ptr_base + pos;
194 + hw_base += runtime->buffer_size;
195 + if (hw_base == runtime->boundary)
196 + hw_base = 0;
197 + new_hw_ptr = hw_base + pos;
198 + }
199 + if (delta > runtime->period_size && runtime->periods > 1) {
200 + hw_ptr_error(substream,
201 + "hw_ptr skipping! "
202 + "(pos=%ld, delta=%ld, period=%ld)\n",
203 + (long)pos, (long)delta,
204 + (long)runtime->period_size);
205 + return 0;
206 }
207 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
208 runtime->silence_size > 0)
209 snd_pcm_playback_silence(substream, new_hw_ptr);
210
211 + runtime->hw_ptr_base = hw_base;
212 runtime->status->hw_ptr = new_hw_ptr;
213
214 return snd_pcm_update_hw_ptr_post(substream, runtime);

admin@fedoraproject.org
ViewVC Help
Powered by ViewVC 1.1.2