diff options
Diffstat (limited to 'sound/core')
-rw-r--r-- | sound/core/init.c | 61 | ||||
-rw-r--r-- | sound/core/oss/pcm_oss.c | 5 | ||||
-rw-r--r-- | sound/core/pcm_lib.c | 20 | ||||
-rw-r--r-- | sound/core/pcm_native.c | 6 |
4 files changed, 64 insertions, 28 deletions
diff --git a/sound/core/init.c b/sound/core/init.c index fd56afe846e..d5d40d78c40 100644 --- a/sound/core/init.c +++ b/sound/core/init.c | |||
@@ -152,15 +152,8 @@ int snd_card_create(int idx, const char *xid, | |||
152 | card = kzalloc(sizeof(*card) + extra_size, GFP_KERNEL); | 152 | card = kzalloc(sizeof(*card) + extra_size, GFP_KERNEL); |
153 | if (!card) | 153 | if (!card) |
154 | return -ENOMEM; | 154 | return -ENOMEM; |
155 | if (xid) { | 155 | if (xid) |
156 | if (!snd_info_check_reserved_words(xid)) { | ||
157 | snd_printk(KERN_ERR | ||
158 | "given id string '%s' is reserved.\n", xid); | ||
159 | err = -EBUSY; | ||
160 | goto __error; | ||
161 | } | ||
162 | strlcpy(card->id, xid, sizeof(card->id)); | 156 | strlcpy(card->id, xid, sizeof(card->id)); |
163 | } | ||
164 | err = 0; | 157 | err = 0; |
165 | mutex_lock(&snd_card_mutex); | 158 | mutex_lock(&snd_card_mutex); |
166 | if (idx < 0) { | 159 | if (idx < 0) { |
@@ -483,22 +476,28 @@ int snd_card_free(struct snd_card *card) | |||
483 | 476 | ||
484 | EXPORT_SYMBOL(snd_card_free); | 477 | EXPORT_SYMBOL(snd_card_free); |
485 | 478 | ||
486 | static void choose_default_id(struct snd_card *card) | 479 | static void snd_card_set_id_no_lock(struct snd_card *card, const char *nid) |
487 | { | 480 | { |
488 | int i, len, idx_flag = 0, loops = SNDRV_CARDS; | 481 | int i, len, idx_flag = 0, loops = SNDRV_CARDS; |
489 | char *id, *spos; | 482 | const char *spos, *src; |
483 | char *id; | ||
490 | 484 | ||
491 | id = spos = card->shortname; | 485 | if (nid == NULL) { |
492 | while (*id != '\0') { | 486 | id = card->shortname; |
493 | if (*id == ' ') | 487 | spos = src = id; |
494 | spos = id + 1; | 488 | while (*id != '\0') { |
495 | id++; | 489 | if (*id == ' ') |
490 | spos = id + 1; | ||
491 | id++; | ||
492 | } | ||
493 | } else { | ||
494 | spos = src = nid; | ||
496 | } | 495 | } |
497 | id = card->id; | 496 | id = card->id; |
498 | while (*spos != '\0' && !isalnum(*spos)) | 497 | while (*spos != '\0' && !isalnum(*spos)) |
499 | spos++; | 498 | spos++; |
500 | if (isdigit(*spos)) | 499 | if (isdigit(*spos)) |
501 | *id++ = isalpha(card->shortname[0]) ? card->shortname[0] : 'D'; | 500 | *id++ = isalpha(src[0]) ? src[0] : 'D'; |
502 | while (*spos != '\0' && (size_t)(id - card->id) < sizeof(card->id) - 1) { | 501 | while (*spos != '\0' && (size_t)(id - card->id) < sizeof(card->id) - 1) { |
503 | if (isalnum(*spos)) | 502 | if (isalnum(*spos)) |
504 | *id++ = *spos; | 503 | *id++ = *spos; |
@@ -513,7 +512,7 @@ static void choose_default_id(struct snd_card *card) | |||
513 | 512 | ||
514 | while (1) { | 513 | while (1) { |
515 | if (loops-- == 0) { | 514 | if (loops-- == 0) { |
516 | snd_printk(KERN_ERR "unable to choose default card id (%s)\n", id); | 515 | snd_printk(KERN_ERR "unable to set card id (%s)\n", id); |
517 | strcpy(card->id, card->proc_root->name); | 516 | strcpy(card->id, card->proc_root->name); |
518 | return; | 517 | return; |
519 | } | 518 | } |
@@ -539,14 +538,33 @@ static void choose_default_id(struct snd_card *card) | |||
539 | spos = id + len - 2; | 538 | spos = id + len - 2; |
540 | if ((size_t)len <= sizeof(card->id) - 2) | 539 | if ((size_t)len <= sizeof(card->id) - 2) |
541 | spos++; | 540 | spos++; |
542 | *spos++ = '_'; | 541 | *(char *)spos++ = '_'; |
543 | *spos++ = '1'; | 542 | *(char *)spos++ = '1'; |
544 | *spos++ = '\0'; | 543 | *(char *)spos++ = '\0'; |
545 | idx_flag++; | 544 | idx_flag++; |
546 | } | 545 | } |
547 | } | 546 | } |
548 | } | 547 | } |
549 | 548 | ||
549 | /** | ||
550 | * snd_card_set_id - set card identification name | ||
551 | * @card: soundcard structure | ||
552 | * @nid: new identification string | ||
553 | * | ||
554 | * This function sets the card identification and checks for name | ||
555 | * collisions. | ||
556 | */ | ||
557 | void snd_card_set_id(struct snd_card *card, const char *nid) | ||
558 | { | ||
559 | /* check if user specified own card->id */ | ||
560 | if (card->id[0] != '\0') | ||
561 | return; | ||
562 | mutex_lock(&snd_card_mutex); | ||
563 | snd_card_set_id_no_lock(card, nid); | ||
564 | mutex_unlock(&snd_card_mutex); | ||
565 | } | ||
566 | EXPORT_SYMBOL(snd_card_set_id); | ||
567 | |||
550 | #ifndef CONFIG_SYSFS_DEPRECATED | 568 | #ifndef CONFIG_SYSFS_DEPRECATED |
551 | static ssize_t | 569 | static ssize_t |
552 | card_id_show_attr(struct device *dev, | 570 | card_id_show_attr(struct device *dev, |
@@ -640,8 +658,7 @@ int snd_card_register(struct snd_card *card) | |||
640 | mutex_unlock(&snd_card_mutex); | 658 | mutex_unlock(&snd_card_mutex); |
641 | return 0; | 659 | return 0; |
642 | } | 660 | } |
643 | if (card->id[0] == '\0') | 661 | snd_card_set_id_no_lock(card, card->id[0] == '\0' ? NULL : card->id); |
644 | choose_default_id(card); | ||
645 | snd_cards[card->number] = card; | 662 | snd_cards[card->number] = card; |
646 | mutex_unlock(&snd_card_mutex); | 663 | mutex_unlock(&snd_card_mutex); |
647 | init_info_for_card(card); | 664 | init_info_for_card(card); |
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index dda000b9684..dbe406b8259 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/time.h> | 31 | #include <linux/time.h> |
32 | #include <linux/vmalloc.h> | 32 | #include <linux/vmalloc.h> |
33 | #include <linux/moduleparam.h> | 33 | #include <linux/moduleparam.h> |
34 | #include <linux/math64.h> | ||
34 | #include <linux/string.h> | 35 | #include <linux/string.h> |
35 | #include <sound/core.h> | 36 | #include <sound/core.h> |
36 | #include <sound/minors.h> | 37 | #include <sound/minors.h> |
@@ -617,9 +618,7 @@ static long snd_pcm_oss_bytes(struct snd_pcm_substream *substream, long frames) | |||
617 | #else | 618 | #else |
618 | { | 619 | { |
619 | u64 bsize = (u64)runtime->oss.buffer_bytes * (u64)bytes; | 620 | u64 bsize = (u64)runtime->oss.buffer_bytes * (u64)bytes; |
620 | u32 rem; | 621 | return div_u64(bsize, buffer_size); |
621 | div64_32(&bsize, buffer_size, &rem); | ||
622 | return (long)bsize; | ||
623 | } | 622 | } |
624 | #endif | 623 | #endif |
625 | } | 624 | } |
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 63d088f2265..a7482874c45 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c | |||
@@ -22,6 +22,7 @@ | |||
22 | 22 | ||
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/time.h> | 24 | #include <linux/time.h> |
25 | #include <linux/math64.h> | ||
25 | #include <sound/core.h> | 26 | #include <sound/core.h> |
26 | #include <sound/control.h> | 27 | #include <sound/control.h> |
27 | #include <sound/info.h> | 28 | #include <sound/info.h> |
@@ -249,6 +250,17 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream) | |||
249 | new_hw_ptr = hw_base + pos; | 250 | new_hw_ptr = hw_base + pos; |
250 | } | 251 | } |
251 | } | 252 | } |
253 | |||
254 | /* Do jiffies check only in xrun_debug mode */ | ||
255 | if (!xrun_debug(substream)) | ||
256 | goto no_jiffies_check; | ||
257 | |||
258 | /* Skip the jiffies check for hardwares with BATCH flag. | ||
259 | * Such hardware usually just increases the position at each IRQ, | ||
260 | * thus it can't give any strange position. | ||
261 | */ | ||
262 | if (runtime->hw.info & SNDRV_PCM_INFO_BATCH) | ||
263 | goto no_jiffies_check; | ||
252 | hdelta = new_hw_ptr - old_hw_ptr; | 264 | hdelta = new_hw_ptr - old_hw_ptr; |
253 | jdelta = jiffies - runtime->hw_ptr_jiffies; | 265 | jdelta = jiffies - runtime->hw_ptr_jiffies; |
254 | if (((hdelta * HZ) / runtime->rate) > jdelta + HZ/100) { | 266 | if (((hdelta * HZ) / runtime->rate) > jdelta + HZ/100) { |
@@ -272,6 +284,7 @@ static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream) | |||
272 | hw_base -= hw_base % runtime->buffer_size; | 284 | hw_base -= hw_base % runtime->buffer_size; |
273 | delta = 0; | 285 | delta = 0; |
274 | } | 286 | } |
287 | no_jiffies_check: | ||
275 | if (delta > runtime->period_size + runtime->period_size / 2) { | 288 | if (delta > runtime->period_size + runtime->period_size / 2) { |
276 | hw_ptr_error(substream, | 289 | hw_ptr_error(substream, |
277 | "Lost interrupts? " | 290 | "Lost interrupts? " |
@@ -329,7 +342,9 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream) | |||
329 | hw_base = 0; | 342 | hw_base = 0; |
330 | new_hw_ptr = hw_base + pos; | 343 | new_hw_ptr = hw_base + pos; |
331 | } | 344 | } |
332 | if (((delta * HZ) / runtime->rate) > jdelta + HZ/100) { | 345 | /* Do jiffies check only in xrun_debug mode */ |
346 | if (xrun_debug(substream) && | ||
347 | ((delta * HZ) / runtime->rate) > jdelta + HZ/100) { | ||
333 | hw_ptr_error(substream, | 348 | hw_ptr_error(substream, |
334 | "hw_ptr skipping! " | 349 | "hw_ptr skipping! " |
335 | "(pos=%ld, delta=%ld, period=%ld, jdelta=%lu/%lu)\n", | 350 | "(pos=%ld, delta=%ld, period=%ld, jdelta=%lu/%lu)\n", |
@@ -438,7 +453,7 @@ static inline unsigned int muldiv32(unsigned int a, unsigned int b, | |||
438 | *r = 0; | 453 | *r = 0; |
439 | return UINT_MAX; | 454 | return UINT_MAX; |
440 | } | 455 | } |
441 | div64_32(&n, c, r); | 456 | n = div_u64_rem(n, c, r); |
442 | if (n >= UINT_MAX) { | 457 | if (n >= UINT_MAX) { |
443 | *r = 0; | 458 | *r = 0; |
444 | return UINT_MAX; | 459 | return UINT_MAX; |
@@ -1471,7 +1486,6 @@ static int snd_pcm_lib_ioctl_reset(struct snd_pcm_substream *substream, | |||
1471 | runtime->status->hw_ptr %= runtime->buffer_size; | 1486 | runtime->status->hw_ptr %= runtime->buffer_size; |
1472 | else | 1487 | else |
1473 | runtime->status->hw_ptr = 0; | 1488 | runtime->status->hw_ptr = 0; |
1474 | runtime->hw_ptr_jiffies = jiffies; | ||
1475 | snd_pcm_stream_unlock_irqrestore(substream, flags); | 1489 | snd_pcm_stream_unlock_irqrestore(substream, flags); |
1476 | return 0; | 1490 | return 0; |
1477 | } | 1491 | } |
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index cb769d415db..45dc53fcfa2 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c | |||
@@ -849,6 +849,7 @@ static void snd_pcm_post_start(struct snd_pcm_substream *substream, int state) | |||
849 | { | 849 | { |
850 | struct snd_pcm_runtime *runtime = substream->runtime; | 850 | struct snd_pcm_runtime *runtime = substream->runtime; |
851 | snd_pcm_trigger_tstamp(substream); | 851 | snd_pcm_trigger_tstamp(substream); |
852 | runtime->hw_ptr_jiffies = jiffies; | ||
852 | runtime->status->state = state; | 853 | runtime->status->state = state; |
853 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && | 854 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && |
854 | runtime->silence_size > 0) | 855 | runtime->silence_size > 0) |
@@ -962,6 +963,11 @@ static int snd_pcm_do_pause(struct snd_pcm_substream *substream, int push) | |||
962 | { | 963 | { |
963 | if (substream->runtime->trigger_master != substream) | 964 | if (substream->runtime->trigger_master != substream) |
964 | return 0; | 965 | return 0; |
966 | /* The jiffies check in snd_pcm_update_hw_ptr*() is done by | ||
967 | * a delta betwen the current jiffies, this gives a large enough | ||
968 | * delta, effectively to skip the check once. | ||
969 | */ | ||
970 | substream->runtime->hw_ptr_jiffies = jiffies - HZ * 1000; | ||
965 | return substream->ops->trigger(substream, | 971 | return substream->ops->trigger(substream, |
966 | push ? SNDRV_PCM_TRIGGER_PAUSE_PUSH : | 972 | push ? SNDRV_PCM_TRIGGER_PAUSE_PUSH : |
967 | SNDRV_PCM_TRIGGER_PAUSE_RELEASE); | 973 | SNDRV_PCM_TRIGGER_PAUSE_RELEASE); |