diff options
Diffstat (limited to 'sound/core')
-rw-r--r-- | sound/core/control.c | 64 | ||||
-rw-r--r-- | sound/core/init.c | 2 | ||||
-rw-r--r-- | sound/core/pcm_lib.c | 14 |
3 files changed, 74 insertions, 6 deletions
diff --git a/sound/core/control.c b/sound/core/control.c index a08ad57c49b6..5d98194bcad5 100644 --- a/sound/core/control.c +++ b/sound/core/control.c | |||
@@ -366,6 +366,70 @@ int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol) | |||
366 | EXPORT_SYMBOL(snd_ctl_add); | 366 | EXPORT_SYMBOL(snd_ctl_add); |
367 | 367 | ||
368 | /** | 368 | /** |
369 | * snd_ctl_replace - replace the control instance of the card | ||
370 | * @card: the card instance | ||
371 | * @kcontrol: the control instance to replace | ||
372 | * @add_on_replace: add the control if not already added | ||
373 | * | ||
374 | * Replaces the given control. If the given control does not exist | ||
375 | * and the add_on_replace flag is set, the control is added. If the | ||
376 | * control exists, it is destroyed first. | ||
377 | * | ||
378 | * Returns zero if successful, or a negative error code on failure. | ||
379 | * | ||
380 | * It frees automatically the control which cannot be added or replaced. | ||
381 | */ | ||
382 | int snd_ctl_replace(struct snd_card *card, struct snd_kcontrol *kcontrol, | ||
383 | bool add_on_replace) | ||
384 | { | ||
385 | struct snd_ctl_elem_id id; | ||
386 | unsigned int idx; | ||
387 | struct snd_kcontrol *old; | ||
388 | int ret; | ||
389 | |||
390 | if (!kcontrol) | ||
391 | return -EINVAL; | ||
392 | if (snd_BUG_ON(!card || !kcontrol->info)) { | ||
393 | ret = -EINVAL; | ||
394 | goto error; | ||
395 | } | ||
396 | id = kcontrol->id; | ||
397 | down_write(&card->controls_rwsem); | ||
398 | old = snd_ctl_find_id(card, &id); | ||
399 | if (!old) { | ||
400 | if (add_on_replace) | ||
401 | goto add; | ||
402 | up_write(&card->controls_rwsem); | ||
403 | ret = -EINVAL; | ||
404 | goto error; | ||
405 | } | ||
406 | ret = snd_ctl_remove(card, old); | ||
407 | if (ret < 0) { | ||
408 | up_write(&card->controls_rwsem); | ||
409 | goto error; | ||
410 | } | ||
411 | add: | ||
412 | if (snd_ctl_find_hole(card, kcontrol->count) < 0) { | ||
413 | up_write(&card->controls_rwsem); | ||
414 | ret = -ENOMEM; | ||
415 | goto error; | ||
416 | } | ||
417 | list_add_tail(&kcontrol->list, &card->controls); | ||
418 | card->controls_count += kcontrol->count; | ||
419 | kcontrol->id.numid = card->last_numid + 1; | ||
420 | card->last_numid += kcontrol->count; | ||
421 | up_write(&card->controls_rwsem); | ||
422 | for (idx = 0; idx < kcontrol->count; idx++, id.index++, id.numid++) | ||
423 | snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_ADD, &id); | ||
424 | return 0; | ||
425 | |||
426 | error: | ||
427 | snd_ctl_free_one(kcontrol); | ||
428 | return ret; | ||
429 | } | ||
430 | EXPORT_SYMBOL(snd_ctl_replace); | ||
431 | |||
432 | /** | ||
369 | * snd_ctl_remove - remove the control from the card and release it | 433 | * snd_ctl_remove - remove the control from the card and release it |
370 | * @card: the card instance | 434 | * @card: the card instance |
371 | * @kcontrol: the control instance to remove | 435 | * @kcontrol: the control instance to remove |
diff --git a/sound/core/init.c b/sound/core/init.c index a0080aa45ae9..30ecad41403c 100644 --- a/sound/core/init.c +++ b/sound/core/init.c | |||
@@ -514,7 +514,7 @@ static void snd_card_set_id_no_lock(struct snd_card *card, const char *nid) | |||
514 | id = card->id; | 514 | id = card->id; |
515 | 515 | ||
516 | if (*id == '\0') | 516 | if (*id == '\0') |
517 | strcpy(id, "default"); | 517 | strcpy(id, "Default"); |
518 | 518 | ||
519 | while (1) { | 519 | while (1) { |
520 | if (loops-- == 0) { | 520 | if (loops-- == 0) { |
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 64449cb8f873..abfeff1611ce 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c | |||
@@ -189,6 +189,7 @@ static void xrun(struct snd_pcm_substream *substream) | |||
189 | #define XRUN_LOG_CNT 10 | 189 | #define XRUN_LOG_CNT 10 |
190 | 190 | ||
191 | struct hwptr_log_entry { | 191 | struct hwptr_log_entry { |
192 | unsigned int in_interrupt; | ||
192 | unsigned long jiffies; | 193 | unsigned long jiffies; |
193 | snd_pcm_uframes_t pos; | 194 | snd_pcm_uframes_t pos; |
194 | snd_pcm_uframes_t period_size; | 195 | snd_pcm_uframes_t period_size; |
@@ -204,7 +205,7 @@ struct snd_pcm_hwptr_log { | |||
204 | }; | 205 | }; |
205 | 206 | ||
206 | static void xrun_log(struct snd_pcm_substream *substream, | 207 | static void xrun_log(struct snd_pcm_substream *substream, |
207 | snd_pcm_uframes_t pos) | 208 | snd_pcm_uframes_t pos, int in_interrupt) |
208 | { | 209 | { |
209 | struct snd_pcm_runtime *runtime = substream->runtime; | 210 | struct snd_pcm_runtime *runtime = substream->runtime; |
210 | struct snd_pcm_hwptr_log *log = runtime->hwptr_log; | 211 | struct snd_pcm_hwptr_log *log = runtime->hwptr_log; |
@@ -220,6 +221,7 @@ static void xrun_log(struct snd_pcm_substream *substream, | |||
220 | return; | 221 | return; |
221 | } | 222 | } |
222 | entry = &log->entries[log->idx]; | 223 | entry = &log->entries[log->idx]; |
224 | entry->in_interrupt = in_interrupt; | ||
223 | entry->jiffies = jiffies; | 225 | entry->jiffies = jiffies; |
224 | entry->pos = pos; | 226 | entry->pos = pos; |
225 | entry->period_size = runtime->period_size; | 227 | entry->period_size = runtime->period_size; |
@@ -246,9 +248,11 @@ static void xrun_log_show(struct snd_pcm_substream *substream) | |||
246 | entry = &log->entries[idx]; | 248 | entry = &log->entries[idx]; |
247 | if (entry->period_size == 0) | 249 | if (entry->period_size == 0) |
248 | break; | 250 | break; |
249 | snd_printd("hwptr log: %s: j=%lu, pos=%ld/%ld/%ld, " | 251 | snd_printd("hwptr log: %s: %sj=%lu, pos=%ld/%ld/%ld, " |
250 | "hwptr=%ld/%ld\n", | 252 | "hwptr=%ld/%ld\n", |
251 | name, entry->jiffies, (unsigned long)entry->pos, | 253 | name, entry->in_interrupt ? "[Q] " : "", |
254 | entry->jiffies, | ||
255 | (unsigned long)entry->pos, | ||
252 | (unsigned long)entry->period_size, | 256 | (unsigned long)entry->period_size, |
253 | (unsigned long)entry->buffer_size, | 257 | (unsigned long)entry->buffer_size, |
254 | (unsigned long)entry->old_hw_ptr, | 258 | (unsigned long)entry->old_hw_ptr, |
@@ -262,7 +266,7 @@ static void xrun_log_show(struct snd_pcm_substream *substream) | |||
262 | #else /* ! CONFIG_SND_PCM_XRUN_DEBUG */ | 266 | #else /* ! CONFIG_SND_PCM_XRUN_DEBUG */ |
263 | 267 | ||
264 | #define hw_ptr_error(substream, fmt, args...) do { } while (0) | 268 | #define hw_ptr_error(substream, fmt, args...) do { } while (0) |
265 | #define xrun_log(substream, pos) do { } while (0) | 269 | #define xrun_log(substream, pos, in_interrupt) do { } while (0) |
266 | #define xrun_log_show(substream) do { } while (0) | 270 | #define xrun_log_show(substream) do { } while (0) |
267 | 271 | ||
268 | #endif | 272 | #endif |
@@ -326,7 +330,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, | |||
326 | } | 330 | } |
327 | pos -= pos % runtime->min_align; | 331 | pos -= pos % runtime->min_align; |
328 | if (xrun_debug(substream, XRUN_DEBUG_LOG)) | 332 | if (xrun_debug(substream, XRUN_DEBUG_LOG)) |
329 | xrun_log(substream, pos); | 333 | xrun_log(substream, pos, in_interrupt); |
330 | hw_base = runtime->hw_ptr_base; | 334 | hw_base = runtime->hw_ptr_base; |
331 | new_hw_ptr = hw_base + pos; | 335 | new_hw_ptr = hw_base + pos; |
332 | if (in_interrupt) { | 336 | if (in_interrupt) { |