aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core/pcm_lib.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/core/pcm_lib.c')
-rw-r--r--sound/core/pcm_lib.c445
1 files changed, 245 insertions, 200 deletions
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index a27545b23ee9..b546ac2660f9 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -126,17 +126,6 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram
126 } 126 }
127} 127}
128 128
129#ifdef CONFIG_SND_PCM_XRUN_DEBUG
130#define xrun_debug(substream, mask) ((substream)->pstr->xrun_debug & (mask))
131#else
132#define xrun_debug(substream, mask) 0
133#endif
134
135#define dump_stack_on_xrun(substream) do { \
136 if (xrun_debug(substream, 2)) \
137 dump_stack(); \
138 } while (0)
139
140static void pcm_debug_name(struct snd_pcm_substream *substream, 129static void pcm_debug_name(struct snd_pcm_substream *substream,
141 char *name, size_t len) 130 char *name, size_t len)
142{ 131{
@@ -147,6 +136,24 @@ static void pcm_debug_name(struct snd_pcm_substream *substream,
147 substream->number); 136 substream->number);
148} 137}
149 138
139#define XRUN_DEBUG_BASIC (1<<0)
140#define XRUN_DEBUG_STACK (1<<1) /* dump also stack */
141#define XRUN_DEBUG_JIFFIESCHECK (1<<2) /* do jiffies check */
142#define XRUN_DEBUG_PERIODUPDATE (1<<3) /* full period update info */
143#define XRUN_DEBUG_HWPTRUPDATE (1<<4) /* full hwptr update info */
144#define XRUN_DEBUG_LOG (1<<5) /* show last 10 positions on err */
145#define XRUN_DEBUG_LOGONCE (1<<6) /* do above only once */
146
147#ifdef CONFIG_SND_PCM_XRUN_DEBUG
148
149#define xrun_debug(substream, mask) \
150 ((substream)->pstr->xrun_debug & (mask))
151
152#define dump_stack_on_xrun(substream) do { \
153 if (xrun_debug(substream, XRUN_DEBUG_STACK)) \
154 dump_stack(); \
155 } while (0)
156
150static void xrun(struct snd_pcm_substream *substream) 157static void xrun(struct snd_pcm_substream *substream)
151{ 158{
152 struct snd_pcm_runtime *runtime = substream->runtime; 159 struct snd_pcm_runtime *runtime = substream->runtime;
@@ -154,7 +161,7 @@ static void xrun(struct snd_pcm_substream *substream)
154 if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) 161 if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
155 snd_pcm_gettime(runtime, (struct timespec *)&runtime->status->tstamp); 162 snd_pcm_gettime(runtime, (struct timespec *)&runtime->status->tstamp);
156 snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); 163 snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
157 if (xrun_debug(substream, 1)) { 164 if (xrun_debug(substream, XRUN_DEBUG_BASIC)) {
158 char name[16]; 165 char name[16];
159 pcm_debug_name(substream, name, sizeof(name)); 166 pcm_debug_name(substream, name, sizeof(name));
160 snd_printd(KERN_DEBUG "XRUN: %s\n", name); 167 snd_printd(KERN_DEBUG "XRUN: %s\n", name);
@@ -162,32 +169,102 @@ static void xrun(struct snd_pcm_substream *substream)
162 } 169 }
163} 170}
164 171
165static snd_pcm_uframes_t 172#define hw_ptr_error(substream, fmt, args...) \
166snd_pcm_update_hw_ptr_pos(struct snd_pcm_substream *substream, 173 do { \
167 struct snd_pcm_runtime *runtime) 174 if (xrun_debug(substream, XRUN_DEBUG_BASIC)) { \
168{ 175 xrun_log_show(substream); \
176 if (printk_ratelimit()) { \
177 snd_printd("PCM: " fmt, ##args); \
178 } \
179 dump_stack_on_xrun(substream); \
180 } \
181 } while (0)
182
183#define XRUN_LOG_CNT 10
184
185struct hwptr_log_entry {
186 unsigned long jiffies;
169 snd_pcm_uframes_t pos; 187 snd_pcm_uframes_t pos;
188 snd_pcm_uframes_t period_size;
189 snd_pcm_uframes_t buffer_size;
190 snd_pcm_uframes_t old_hw_ptr;
191 snd_pcm_uframes_t hw_ptr_base;
192};
170 193
171 pos = substream->ops->pointer(substream); 194struct snd_pcm_hwptr_log {
172 if (pos == SNDRV_PCM_POS_XRUN) 195 unsigned int idx;
173 return pos; /* XRUN */ 196 unsigned int hit: 1;
174 if (pos >= runtime->buffer_size) { 197 struct hwptr_log_entry entries[XRUN_LOG_CNT];
175 if (printk_ratelimit()) { 198};
176 char name[16]; 199
177 pcm_debug_name(substream, name, sizeof(name)); 200static void xrun_log(struct snd_pcm_substream *substream,
178 snd_printd(KERN_ERR "BUG: %s, pos = 0x%lx, " 201 snd_pcm_uframes_t pos)
179 "buffer size = 0x%lx, period size = 0x%lx\n", 202{
180 name, pos, runtime->buffer_size, 203 struct snd_pcm_runtime *runtime = substream->runtime;
181 runtime->period_size); 204 struct snd_pcm_hwptr_log *log = runtime->hwptr_log;
182 } 205 struct hwptr_log_entry *entry;
183 pos = 0; 206
207 if (log == NULL) {
208 log = kzalloc(sizeof(*log), GFP_ATOMIC);
209 if (log == NULL)
210 return;
211 runtime->hwptr_log = log;
212 } else {
213 if (xrun_debug(substream, XRUN_DEBUG_LOGONCE) && log->hit)
214 return;
184 } 215 }
185 pos -= pos % runtime->min_align; 216 entry = &log->entries[log->idx];
186 return pos; 217 entry->jiffies = jiffies;
218 entry->pos = pos;
219 entry->period_size = runtime->period_size;
220 entry->buffer_size = runtime->buffer_size;;
221 entry->old_hw_ptr = runtime->status->hw_ptr;
222 entry->hw_ptr_base = runtime->hw_ptr_base;
223 log->idx = (log->idx + 1) % XRUN_LOG_CNT;
224}
225
226static void xrun_log_show(struct snd_pcm_substream *substream)
227{
228 struct snd_pcm_hwptr_log *log = substream->runtime->hwptr_log;
229 struct hwptr_log_entry *entry;
230 char name[16];
231 unsigned int idx;
232 int cnt;
233
234 if (log == NULL)
235 return;
236 if (xrun_debug(substream, XRUN_DEBUG_LOGONCE) && log->hit)
237 return;
238 pcm_debug_name(substream, name, sizeof(name));
239 for (cnt = 0, idx = log->idx; cnt < XRUN_LOG_CNT; cnt++) {
240 entry = &log->entries[idx];
241 if (entry->period_size == 0)
242 break;
243 snd_printd("hwptr log: %s: j=%lu, pos=%ld/%ld/%ld, "
244 "hwptr=%ld/%ld\n",
245 name, entry->jiffies, (unsigned long)entry->pos,
246 (unsigned long)entry->period_size,
247 (unsigned long)entry->buffer_size,
248 (unsigned long)entry->old_hw_ptr,
249 (unsigned long)entry->hw_ptr_base);
250 idx++;
251 idx %= XRUN_LOG_CNT;
252 }
253 log->hit = 1;
187} 254}
188 255
189static int snd_pcm_update_hw_ptr_post(struct snd_pcm_substream *substream, 256#else /* ! CONFIG_SND_PCM_XRUN_DEBUG */
190 struct snd_pcm_runtime *runtime) 257
258#define xrun_debug(substream, mask) 0
259#define xrun(substream) do { } while (0)
260#define hw_ptr_error(substream, fmt, args...) do { } while (0)
261#define xrun_log(substream, pos) do { } while (0)
262#define xrun_log_show(substream) do { } while (0)
263
264#endif
265
266int snd_pcm_update_state(struct snd_pcm_substream *substream,
267 struct snd_pcm_runtime *runtime)
191{ 268{
192 snd_pcm_uframes_t avail; 269 snd_pcm_uframes_t avail;
193 270
@@ -209,88 +286,94 @@ static int snd_pcm_update_hw_ptr_post(struct snd_pcm_substream *substream,
209 } 286 }
210 } 287 }
211 if (avail >= runtime->control->avail_min) 288 if (avail >= runtime->control->avail_min)
212 wake_up(&runtime->sleep); 289 wake_up(runtime->twake ? &runtime->tsleep : &runtime->sleep);
213 return 0; 290 return 0;
214} 291}
215 292
216#define hw_ptr_error(substream, fmt, args...) \ 293static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
217 do { \ 294 unsigned int in_interrupt)
218 if (xrun_debug(substream, 1)) { \
219 if (printk_ratelimit()) { \
220 snd_printd("PCM: " fmt, ##args); \
221 } \
222 dump_stack_on_xrun(substream); \
223 } \
224 } while (0)
225
226static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream)
227{ 295{
228 struct snd_pcm_runtime *runtime = substream->runtime; 296 struct snd_pcm_runtime *runtime = substream->runtime;
229 snd_pcm_uframes_t pos; 297 snd_pcm_uframes_t pos;
230 snd_pcm_uframes_t old_hw_ptr, new_hw_ptr, hw_ptr_interrupt, hw_base; 298 snd_pcm_uframes_t old_hw_ptr, new_hw_ptr, hw_base;
231 snd_pcm_sframes_t hdelta, delta; 299 snd_pcm_sframes_t hdelta, delta;
232 unsigned long jdelta; 300 unsigned long jdelta;
233 301
234 old_hw_ptr = runtime->status->hw_ptr; 302 old_hw_ptr = runtime->status->hw_ptr;
235 pos = snd_pcm_update_hw_ptr_pos(substream, runtime); 303 pos = substream->ops->pointer(substream);
236 if (pos == SNDRV_PCM_POS_XRUN) { 304 if (pos == SNDRV_PCM_POS_XRUN) {
237 xrun(substream); 305 xrun(substream);
238 return -EPIPE; 306 return -EPIPE;
239 } 307 }
240 if (xrun_debug(substream, 8)) { 308 if (pos >= runtime->buffer_size) {
241 char name[16]; 309 if (printk_ratelimit()) {
242 pcm_debug_name(substream, name, sizeof(name)); 310 char name[16];
243 snd_printd("period_update: %s: pos=0x%x/0x%x/0x%x, " 311 pcm_debug_name(substream, name, sizeof(name));
244 "hwptr=0x%lx, hw_base=0x%lx, hw_intr=0x%lx\n", 312 xrun_log_show(substream);
245 name, (unsigned int)pos, 313 snd_printd(KERN_ERR "BUG: %s, pos = %ld, "
246 (unsigned int)runtime->period_size, 314 "buffer size = %ld, period size = %ld\n",
247 (unsigned int)runtime->buffer_size, 315 name, pos, runtime->buffer_size,
248 (unsigned long)old_hw_ptr, 316 runtime->period_size);
249 (unsigned long)runtime->hw_ptr_base, 317 }
250 (unsigned long)runtime->hw_ptr_interrupt); 318 pos = 0;
251 } 319 }
320 pos -= pos % runtime->min_align;
321 if (xrun_debug(substream, XRUN_DEBUG_LOG))
322 xrun_log(substream, pos);
252 hw_base = runtime->hw_ptr_base; 323 hw_base = runtime->hw_ptr_base;
253 new_hw_ptr = hw_base + pos; 324 new_hw_ptr = hw_base + pos;
254 hw_ptr_interrupt = runtime->hw_ptr_interrupt + runtime->period_size; 325 if (in_interrupt) {
255 delta = new_hw_ptr - hw_ptr_interrupt; 326 /* we know that one period was processed */
256 if (hw_ptr_interrupt >= runtime->boundary) { 327 /* delta = "expected next hw_ptr" for in_interrupt != 0 */
257 hw_ptr_interrupt -= runtime->boundary; 328 delta = runtime->hw_ptr_interrupt + runtime->period_size;
258 if (hw_base < runtime->boundary / 2) 329 if (delta > new_hw_ptr) {
259 /* hw_base was already lapped; recalc delta */
260 delta = new_hw_ptr - hw_ptr_interrupt;
261 }
262 if (delta < 0) {
263 if (runtime->periods == 1 || new_hw_ptr < old_hw_ptr)
264 delta += runtime->buffer_size;
265 if (delta < 0) {
266 hw_ptr_error(substream,
267 "Unexpected hw_pointer value "
268 "(stream=%i, pos=%ld, intr_ptr=%ld)\n",
269 substream->stream, (long)pos,
270 (long)hw_ptr_interrupt);
271#if 1
272 /* simply skipping the hwptr update seems more
273 * robust in some cases, e.g. on VMware with
274 * inaccurate timer source
275 */
276 return 0; /* skip this update */
277#else
278 /* rebase to interrupt position */
279 hw_base = new_hw_ptr = hw_ptr_interrupt;
280 /* align hw_base to buffer_size */
281 hw_base -= hw_base % runtime->buffer_size;
282 delta = 0;
283#endif
284 } else {
285 hw_base += runtime->buffer_size; 330 hw_base += runtime->buffer_size;
286 if (hw_base >= runtime->boundary) 331 if (hw_base >= runtime->boundary)
287 hw_base = 0; 332 hw_base = 0;
288 new_hw_ptr = hw_base + pos; 333 new_hw_ptr = hw_base + pos;
334 goto __delta;
289 } 335 }
290 } 336 }
337 /* new_hw_ptr might be lower than old_hw_ptr in case when */
338 /* pointer crosses the end of the ring buffer */
339 if (new_hw_ptr < old_hw_ptr) {
340 hw_base += runtime->buffer_size;
341 if (hw_base >= runtime->boundary)
342 hw_base = 0;
343 new_hw_ptr = hw_base + pos;
344 }
345 __delta:
346 delta = (new_hw_ptr - old_hw_ptr) % runtime->boundary;
347 if (xrun_debug(substream, in_interrupt ?
348 XRUN_DEBUG_PERIODUPDATE : XRUN_DEBUG_HWPTRUPDATE)) {
349 char name[16];
350 pcm_debug_name(substream, name, sizeof(name));
351 snd_printd("%s_update: %s: pos=%u/%u/%u, "
352 "hwptr=%ld/%ld/%ld/%ld\n",
353 in_interrupt ? "period" : "hwptr",
354 name,
355 (unsigned int)pos,
356 (unsigned int)runtime->period_size,
357 (unsigned int)runtime->buffer_size,
358 (unsigned long)delta,
359 (unsigned long)old_hw_ptr,
360 (unsigned long)new_hw_ptr,
361 (unsigned long)runtime->hw_ptr_base);
362 }
363 /* something must be really wrong */
364 if (delta >= runtime->buffer_size + runtime->period_size) {
365 hw_ptr_error(substream,
366 "Unexpected hw_pointer value %s"
367 "(stream=%i, pos=%ld, new_hw_ptr=%ld, "
368 "old_hw_ptr=%ld)\n",
369 in_interrupt ? "[Q] " : "[P]",
370 substream->stream, (long)pos,
371 (long)new_hw_ptr, (long)old_hw_ptr);
372 return 0;
373 }
291 374
292 /* Do jiffies check only in xrun_debug mode */ 375 /* Do jiffies check only in xrun_debug mode */
293 if (!xrun_debug(substream, 4)) 376 if (!xrun_debug(substream, XRUN_DEBUG_JIFFIESCHECK))
294 goto no_jiffies_check; 377 goto no_jiffies_check;
295 378
296 /* Skip the jiffies check for hardwares with BATCH flag. 379 /* Skip the jiffies check for hardwares with BATCH flag.
@@ -299,7 +382,7 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream)
299 */ 382 */
300 if (runtime->hw.info & SNDRV_PCM_INFO_BATCH) 383 if (runtime->hw.info & SNDRV_PCM_INFO_BATCH)
301 goto no_jiffies_check; 384 goto no_jiffies_check;
302 hdelta = new_hw_ptr - old_hw_ptr; 385 hdelta = delta;
303 if (hdelta < runtime->delay) 386 if (hdelta < runtime->delay)
304 goto no_jiffies_check; 387 goto no_jiffies_check;
305 hdelta -= runtime->delay; 388 hdelta -= runtime->delay;
@@ -308,130 +391,68 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream)
308 delta = jdelta / 391 delta = jdelta /
309 (((runtime->period_size * HZ) / runtime->rate) 392 (((runtime->period_size * HZ) / runtime->rate)
310 + HZ/100); 393 + HZ/100);
394 /* move new_hw_ptr according jiffies not pos variable */
395 new_hw_ptr = old_hw_ptr;
396 hw_base = delta;
397 /* use loop to avoid checks for delta overflows */
398 /* the delta value is small or zero in most cases */
399 while (delta > 0) {
400 new_hw_ptr += runtime->period_size;
401 if (new_hw_ptr >= runtime->boundary)
402 new_hw_ptr -= runtime->boundary;
403 delta--;
404 }
405 /* align hw_base to buffer_size */
311 hw_ptr_error(substream, 406 hw_ptr_error(substream,
312 "hw_ptr skipping! [Q] " 407 "hw_ptr skipping! %s"
313 "(pos=%ld, delta=%ld, period=%ld, " 408 "(pos=%ld, delta=%ld, period=%ld, "
314 "jdelta=%lu/%lu/%lu)\n", 409 "jdelta=%lu/%lu/%lu, hw_ptr=%ld/%ld)\n",
410 in_interrupt ? "[Q] " : "",
315 (long)pos, (long)hdelta, 411 (long)pos, (long)hdelta,
316 (long)runtime->period_size, jdelta, 412 (long)runtime->period_size, jdelta,
317 ((hdelta * HZ) / runtime->rate), delta); 413 ((hdelta * HZ) / runtime->rate), hw_base,
318 hw_ptr_interrupt = runtime->hw_ptr_interrupt + 414 (unsigned long)old_hw_ptr,
319 runtime->period_size * delta; 415 (unsigned long)new_hw_ptr);
320 if (hw_ptr_interrupt >= runtime->boundary) 416 /* reset values to proper state */
321 hw_ptr_interrupt -= runtime->boundary;
322 /* rebase to interrupt position */
323 hw_base = new_hw_ptr = hw_ptr_interrupt;
324 /* align hw_base to buffer_size */
325 hw_base -= hw_base % runtime->buffer_size;
326 delta = 0; 417 delta = 0;
418 hw_base = new_hw_ptr - (new_hw_ptr % runtime->buffer_size);
327 } 419 }
328 no_jiffies_check: 420 no_jiffies_check:
329 if (delta > runtime->period_size + runtime->period_size / 2) { 421 if (delta > runtime->period_size + runtime->period_size / 2) {
330 hw_ptr_error(substream, 422 hw_ptr_error(substream,
331 "Lost interrupts? " 423 "Lost interrupts? %s"
332 "(stream=%i, delta=%ld, intr_ptr=%ld)\n", 424 "(stream=%i, delta=%ld, new_hw_ptr=%ld, "
425 "old_hw_ptr=%ld)\n",
426 in_interrupt ? "[Q] " : "",
333 substream->stream, (long)delta, 427 substream->stream, (long)delta,
334 (long)hw_ptr_interrupt); 428 (long)new_hw_ptr,
335 /* rebase hw_ptr_interrupt */ 429 (long)old_hw_ptr);
336 hw_ptr_interrupt =
337 new_hw_ptr - new_hw_ptr % runtime->period_size;
338 } 430 }
339 runtime->hw_ptr_interrupt = hw_ptr_interrupt; 431
432 if (runtime->status->hw_ptr == new_hw_ptr)
433 return 0;
340 434
341 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && 435 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
342 runtime->silence_size > 0) 436 runtime->silence_size > 0)
343 snd_pcm_playback_silence(substream, new_hw_ptr); 437 snd_pcm_playback_silence(substream, new_hw_ptr);
344 438
345 if (runtime->status->hw_ptr == new_hw_ptr) 439 if (in_interrupt) {
346 return 0; 440 runtime->hw_ptr_interrupt = new_hw_ptr -
347 441 (new_hw_ptr % runtime->period_size);
442 }
348 runtime->hw_ptr_base = hw_base; 443 runtime->hw_ptr_base = hw_base;
349 runtime->status->hw_ptr = new_hw_ptr; 444 runtime->status->hw_ptr = new_hw_ptr;
350 runtime->hw_ptr_jiffies = jiffies; 445 runtime->hw_ptr_jiffies = jiffies;
351 if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) 446 if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
352 snd_pcm_gettime(runtime, (struct timespec *)&runtime->status->tstamp); 447 snd_pcm_gettime(runtime, (struct timespec *)&runtime->status->tstamp);
353 448
354 return snd_pcm_update_hw_ptr_post(substream, runtime); 449 return snd_pcm_update_state(substream, runtime);
355} 450}
356 451
357/* CAUTION: call it with irq disabled */ 452/* CAUTION: call it with irq disabled */
358int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream) 453int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream)
359{ 454{
360 struct snd_pcm_runtime *runtime = substream->runtime; 455 return snd_pcm_update_hw_ptr0(substream, 0);
361 snd_pcm_uframes_t pos;
362 snd_pcm_uframes_t old_hw_ptr, new_hw_ptr, hw_base;
363 snd_pcm_sframes_t delta;
364 unsigned long jdelta;
365
366 old_hw_ptr = runtime->status->hw_ptr;
367 pos = snd_pcm_update_hw_ptr_pos(substream, runtime);
368 if (pos == SNDRV_PCM_POS_XRUN) {
369 xrun(substream);
370 return -EPIPE;
371 }
372 if (xrun_debug(substream, 16)) {
373 char name[16];
374 pcm_debug_name(substream, name, sizeof(name));
375 snd_printd("hw_update: %s: pos=0x%x/0x%x/0x%x, "
376 "hwptr=0x%lx, hw_base=0x%lx, hw_intr=0x%lx\n",
377 name, (unsigned int)pos,
378 (unsigned int)runtime->period_size,
379 (unsigned int)runtime->buffer_size,
380 (unsigned long)old_hw_ptr,
381 (unsigned long)runtime->hw_ptr_base,
382 (unsigned long)runtime->hw_ptr_interrupt);
383 }
384
385 hw_base = runtime->hw_ptr_base;
386 new_hw_ptr = hw_base + pos;
387
388 delta = new_hw_ptr - old_hw_ptr;
389 jdelta = jiffies - runtime->hw_ptr_jiffies;
390 if (delta < 0) {
391 delta += runtime->buffer_size;
392 if (delta < 0) {
393 hw_ptr_error(substream,
394 "Unexpected hw_pointer value [2] "
395 "(stream=%i, pos=%ld, old_ptr=%ld, jdelta=%li)\n",
396 substream->stream, (long)pos,
397 (long)old_hw_ptr, jdelta);
398 return 0;
399 }
400 hw_base += runtime->buffer_size;
401 if (hw_base >= runtime->boundary)
402 hw_base = 0;
403 new_hw_ptr = hw_base + pos;
404 }
405 /* Do jiffies check only in xrun_debug mode */
406 if (!xrun_debug(substream, 4))
407 goto no_jiffies_check;
408 if (delta < runtime->delay)
409 goto no_jiffies_check;
410 delta -= runtime->delay;
411 if (((delta * HZ) / runtime->rate) > jdelta + HZ/100) {
412 hw_ptr_error(substream,
413 "hw_ptr skipping! "
414 "(pos=%ld, delta=%ld, period=%ld, jdelta=%lu/%lu)\n",
415 (long)pos, (long)delta,
416 (long)runtime->period_size, jdelta,
417 ((delta * HZ) / runtime->rate));
418 return 0;
419 }
420 no_jiffies_check:
421 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
422 runtime->silence_size > 0)
423 snd_pcm_playback_silence(substream, new_hw_ptr);
424
425 if (runtime->status->hw_ptr == new_hw_ptr)
426 return 0;
427
428 runtime->hw_ptr_base = hw_base;
429 runtime->status->hw_ptr = new_hw_ptr;
430 runtime->hw_ptr_jiffies = jiffies;
431 if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
432 snd_pcm_gettime(runtime, (struct timespec *)&runtime->status->tstamp);
433
434 return snd_pcm_update_hw_ptr_post(substream, runtime);
435} 456}
436 457
437/** 458/**
@@ -745,10 +766,13 @@ int snd_interval_ratnum(struct snd_interval *i,
745 unsigned int rats_count, struct snd_ratnum *rats, 766 unsigned int rats_count, struct snd_ratnum *rats,
746 unsigned int *nump, unsigned int *denp) 767 unsigned int *nump, unsigned int *denp)
747{ 768{
748 unsigned int best_num, best_diff, best_den; 769 unsigned int best_num, best_den;
770 int best_diff;
749 unsigned int k; 771 unsigned int k;
750 struct snd_interval t; 772 struct snd_interval t;
751 int err; 773 int err;
774 unsigned int result_num, result_den;
775 int result_diff;
752 776
753 best_num = best_den = best_diff = 0; 777 best_num = best_den = best_diff = 0;
754 for (k = 0; k < rats_count; ++k) { 778 for (k = 0; k < rats_count; ++k) {
@@ -770,6 +794,8 @@ int snd_interval_ratnum(struct snd_interval *i,
770 den -= r; 794 den -= r;
771 } 795 }
772 diff = num - q * den; 796 diff = num - q * den;
797 if (diff < 0)
798 diff = -diff;
773 if (best_num == 0 || 799 if (best_num == 0 ||
774 diff * best_den < best_diff * den) { 800 diff * best_den < best_diff * den) {
775 best_diff = diff; 801 best_diff = diff;
@@ -784,6 +810,9 @@ int snd_interval_ratnum(struct snd_interval *i,
784 t.min = div_down(best_num, best_den); 810 t.min = div_down(best_num, best_den);
785 t.openmin = !!(best_num % best_den); 811 t.openmin = !!(best_num % best_den);
786 812
813 result_num = best_num;
814 result_diff = best_diff;
815 result_den = best_den;
787 best_num = best_den = best_diff = 0; 816 best_num = best_den = best_diff = 0;
788 for (k = 0; k < rats_count; ++k) { 817 for (k = 0; k < rats_count; ++k) {
789 unsigned int num = rats[k].num; 818 unsigned int num = rats[k].num;
@@ -806,6 +835,8 @@ int snd_interval_ratnum(struct snd_interval *i,
806 den += rats[k].den_step - r; 835 den += rats[k].den_step - r;
807 } 836 }
808 diff = q * den - num; 837 diff = q * den - num;
838 if (diff < 0)
839 diff = -diff;
809 if (best_num == 0 || 840 if (best_num == 0 ||
810 diff * best_den < best_diff * den) { 841 diff * best_den < best_diff * den) {
811 best_diff = diff; 842 best_diff = diff;
@@ -825,10 +856,14 @@ int snd_interval_ratnum(struct snd_interval *i,
825 return err; 856 return err;
826 857
827 if (snd_interval_single(i)) { 858 if (snd_interval_single(i)) {
859 if (best_diff * result_den < result_diff * best_den) {
860 result_num = best_num;
861 result_den = best_den;
862 }
828 if (nump) 863 if (nump)
829 *nump = best_num; 864 *nump = result_num;
830 if (denp) 865 if (denp)
831 *denp = best_den; 866 *denp = result_den;
832 } 867 }
833 return err; 868 return err;
834} 869}
@@ -1643,7 +1678,7 @@ void snd_pcm_period_elapsed(struct snd_pcm_substream *substream)
1643 1678
1644 snd_pcm_stream_lock_irqsave(substream, flags); 1679 snd_pcm_stream_lock_irqsave(substream, flags);
1645 if (!snd_pcm_running(substream) || 1680 if (!snd_pcm_running(substream) ||
1646 snd_pcm_update_hw_ptr_interrupt(substream) < 0) 1681 snd_pcm_update_hw_ptr0(substream, 1) < 0)
1647 goto _end; 1682 goto _end;
1648 1683
1649 if (substream->timer_running) 1684 if (substream->timer_running)
@@ -1674,7 +1709,7 @@ static int wait_for_avail_min(struct snd_pcm_substream *substream,
1674 long tout; 1709 long tout;
1675 1710
1676 init_waitqueue_entry(&wait, current); 1711 init_waitqueue_entry(&wait, current);
1677 add_wait_queue(&runtime->sleep, &wait); 1712 add_wait_queue(&runtime->tsleep, &wait);
1678 for (;;) { 1713 for (;;) {
1679 if (signal_pending(current)) { 1714 if (signal_pending(current)) {
1680 err = -ERESTARTSYS; 1715 err = -ERESTARTSYS;
@@ -1717,7 +1752,7 @@ static int wait_for_avail_min(struct snd_pcm_substream *substream,
1717 break; 1752 break;
1718 } 1753 }
1719 _endloop: 1754 _endloop:
1720 remove_wait_queue(&runtime->sleep, &wait); 1755 remove_wait_queue(&runtime->tsleep, &wait);
1721 *availp = avail; 1756 *availp = avail;
1722 return err; 1757 return err;
1723} 1758}
@@ -1776,6 +1811,7 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream,
1776 goto _end_unlock; 1811 goto _end_unlock;
1777 } 1812 }
1778 1813
1814 runtime->twake = 1;
1779 while (size > 0) { 1815 while (size > 0) {
1780 snd_pcm_uframes_t frames, appl_ptr, appl_ofs; 1816 snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
1781 snd_pcm_uframes_t avail; 1817 snd_pcm_uframes_t avail;
@@ -1797,15 +1833,17 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream,
1797 if (frames > cont) 1833 if (frames > cont)
1798 frames = cont; 1834 frames = cont;
1799 if (snd_BUG_ON(!frames)) { 1835 if (snd_BUG_ON(!frames)) {
1836 runtime->twake = 0;
1800 snd_pcm_stream_unlock_irq(substream); 1837 snd_pcm_stream_unlock_irq(substream);
1801 return -EINVAL; 1838 return -EINVAL;
1802 } 1839 }
1803 appl_ptr = runtime->control->appl_ptr; 1840 appl_ptr = runtime->control->appl_ptr;
1804 appl_ofs = appl_ptr % runtime->buffer_size; 1841 appl_ofs = appl_ptr % runtime->buffer_size;
1805 snd_pcm_stream_unlock_irq(substream); 1842 snd_pcm_stream_unlock_irq(substream);
1806 if ((err = transfer(substream, appl_ofs, data, offset, frames)) < 0) 1843 err = transfer(substream, appl_ofs, data, offset, frames);
1807 goto _end;
1808 snd_pcm_stream_lock_irq(substream); 1844 snd_pcm_stream_lock_irq(substream);
1845 if (err < 0)
1846 goto _end_unlock;
1809 switch (runtime->status->state) { 1847 switch (runtime->status->state) {
1810 case SNDRV_PCM_STATE_XRUN: 1848 case SNDRV_PCM_STATE_XRUN:
1811 err = -EPIPE; 1849 err = -EPIPE;
@@ -1834,8 +1872,10 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream,
1834 } 1872 }
1835 } 1873 }
1836 _end_unlock: 1874 _end_unlock:
1875 runtime->twake = 0;
1876 if (xfer > 0 && err >= 0)
1877 snd_pcm_update_state(substream, runtime);
1837 snd_pcm_stream_unlock_irq(substream); 1878 snd_pcm_stream_unlock_irq(substream);
1838 _end:
1839 return xfer > 0 ? (snd_pcm_sframes_t)xfer : err; 1879 return xfer > 0 ? (snd_pcm_sframes_t)xfer : err;
1840} 1880}
1841 1881
@@ -1993,6 +2033,7 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
1993 goto _end_unlock; 2033 goto _end_unlock;
1994 } 2034 }
1995 2035
2036 runtime->twake = 1;
1996 while (size > 0) { 2037 while (size > 0) {
1997 snd_pcm_uframes_t frames, appl_ptr, appl_ofs; 2038 snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
1998 snd_pcm_uframes_t avail; 2039 snd_pcm_uframes_t avail;
@@ -2021,15 +2062,17 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
2021 if (frames > cont) 2062 if (frames > cont)
2022 frames = cont; 2063 frames = cont;
2023 if (snd_BUG_ON(!frames)) { 2064 if (snd_BUG_ON(!frames)) {
2065 runtime->twake = 0;
2024 snd_pcm_stream_unlock_irq(substream); 2066 snd_pcm_stream_unlock_irq(substream);
2025 return -EINVAL; 2067 return -EINVAL;
2026 } 2068 }
2027 appl_ptr = runtime->control->appl_ptr; 2069 appl_ptr = runtime->control->appl_ptr;
2028 appl_ofs = appl_ptr % runtime->buffer_size; 2070 appl_ofs = appl_ptr % runtime->buffer_size;
2029 snd_pcm_stream_unlock_irq(substream); 2071 snd_pcm_stream_unlock_irq(substream);
2030 if ((err = transfer(substream, appl_ofs, data, offset, frames)) < 0) 2072 err = transfer(substream, appl_ofs, data, offset, frames);
2031 goto _end;
2032 snd_pcm_stream_lock_irq(substream); 2073 snd_pcm_stream_lock_irq(substream);
2074 if (err < 0)
2075 goto _end_unlock;
2033 switch (runtime->status->state) { 2076 switch (runtime->status->state) {
2034 case SNDRV_PCM_STATE_XRUN: 2077 case SNDRV_PCM_STATE_XRUN:
2035 err = -EPIPE; 2078 err = -EPIPE;
@@ -2052,8 +2095,10 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
2052 xfer += frames; 2095 xfer += frames;
2053 } 2096 }
2054 _end_unlock: 2097 _end_unlock:
2098 runtime->twake = 0;
2099 if (xfer > 0 && err >= 0)
2100 snd_pcm_update_state(substream, runtime);
2055 snd_pcm_stream_unlock_irq(substream); 2101 snd_pcm_stream_unlock_irq(substream);
2056 _end:
2057 return xfer > 0 ? (snd_pcm_sframes_t)xfer : err; 2102 return xfer > 0 ? (snd_pcm_sframes_t)xfer : err;
2058} 2103}
2059 2104