aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core
diff options
context:
space:
mode:
Diffstat (limited to 'sound/core')
-rw-r--r--sound/core/init.c61
-rw-r--r--sound/core/oss/pcm_oss.c5
-rw-r--r--sound/core/pcm_lib.c20
-rw-r--r--sound/core/pcm_native.c6
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
484EXPORT_SYMBOL(snd_card_free); 477EXPORT_SYMBOL(snd_card_free);
485 478
486static void choose_default_id(struct snd_card *card) 479static 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 */
557void 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}
566EXPORT_SYMBOL(snd_card_set_id);
567
550#ifndef CONFIG_SYSFS_DEPRECATED 568#ifndef CONFIG_SYSFS_DEPRECATED
551static ssize_t 569static ssize_t
552card_id_show_attr(struct device *dev, 570card_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);