diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-07-25 21:03:45 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-07-25 21:03:45 -0400 |
commit | 9c5502189fa00ad623aed7ff006d5c2a16b121c0 (patch) | |
tree | bde834a5225ecb60597d9fb987b8b3cc03c9d746 /sound | |
parent | 051c2a9fdebdabec594c151727ce3834ff17d793 (diff) | |
parent | eb12f72ee7245ca207818b9efd10be2641494502 (diff) |
Merge tag 'sound-3.16-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound fixes from Takashi Iwai:
"Here contains only the fixes for the new FireWire bebob driver. All
fairly trivial and local fixes, so safe to apply"
* tag 'sound-3.16-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound:
ALSA: bebob: Correction for return value of special_clk_ctl_put() in error
ALSA: bebob: Correction for return value of .put callback
ALSA: bebob: Use different labels for digital input/output
ALSA: bebob: Fix a missing to unlock mutex in error handling case
Diffstat (limited to 'sound')
-rw-r--r-- | sound/firewire/bebob/bebob_maudio.c | 53 |
1 files changed, 37 insertions, 16 deletions
diff --git a/sound/firewire/bebob/bebob_maudio.c b/sound/firewire/bebob/bebob_maudio.c index 6af50eb80ea7..70faa3a32526 100644 --- a/sound/firewire/bebob/bebob_maudio.c +++ b/sound/firewire/bebob/bebob_maudio.c | |||
@@ -379,11 +379,11 @@ static int special_clk_ctl_put(struct snd_kcontrol *kctl, | |||
379 | struct special_params *params = bebob->maudio_special_quirk; | 379 | struct special_params *params = bebob->maudio_special_quirk; |
380 | int err, id; | 380 | int err, id; |
381 | 381 | ||
382 | mutex_lock(&bebob->mutex); | ||
383 | |||
384 | id = uval->value.enumerated.item[0]; | 382 | id = uval->value.enumerated.item[0]; |
385 | if (id >= ARRAY_SIZE(special_clk_labels)) | 383 | if (id >= ARRAY_SIZE(special_clk_labels)) |
386 | return 0; | 384 | return -EINVAL; |
385 | |||
386 | mutex_lock(&bebob->mutex); | ||
387 | 387 | ||
388 | err = avc_maudio_set_special_clk(bebob, id, | 388 | err = avc_maudio_set_special_clk(bebob, id, |
389 | params->dig_in_fmt, | 389 | params->dig_in_fmt, |
@@ -391,7 +391,10 @@ static int special_clk_ctl_put(struct snd_kcontrol *kctl, | |||
391 | params->clk_lock); | 391 | params->clk_lock); |
392 | mutex_unlock(&bebob->mutex); | 392 | mutex_unlock(&bebob->mutex); |
393 | 393 | ||
394 | return err >= 0; | 394 | if (err >= 0) |
395 | err = 1; | ||
396 | |||
397 | return err; | ||
395 | } | 398 | } |
396 | static struct snd_kcontrol_new special_clk_ctl = { | 399 | static struct snd_kcontrol_new special_clk_ctl = { |
397 | .name = "Clock Source", | 400 | .name = "Clock Source", |
@@ -434,8 +437,8 @@ static struct snd_kcontrol_new special_sync_ctl = { | |||
434 | .get = special_sync_ctl_get, | 437 | .get = special_sync_ctl_get, |
435 | }; | 438 | }; |
436 | 439 | ||
437 | /* Digital interface control for special firmware */ | 440 | /* Digital input interface control for special firmware */ |
438 | static char *const special_dig_iface_labels[] = { | 441 | static char *const special_dig_in_iface_labels[] = { |
439 | "S/PDIF Optical", "S/PDIF Coaxial", "ADAT Optical" | 442 | "S/PDIF Optical", "S/PDIF Coaxial", "ADAT Optical" |
440 | }; | 443 | }; |
441 | static int special_dig_in_iface_ctl_info(struct snd_kcontrol *kctl, | 444 | static int special_dig_in_iface_ctl_info(struct snd_kcontrol *kctl, |
@@ -443,13 +446,13 @@ static int special_dig_in_iface_ctl_info(struct snd_kcontrol *kctl, | |||
443 | { | 446 | { |
444 | einf->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 447 | einf->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
445 | einf->count = 1; | 448 | einf->count = 1; |
446 | einf->value.enumerated.items = ARRAY_SIZE(special_dig_iface_labels); | 449 | einf->value.enumerated.items = ARRAY_SIZE(special_dig_in_iface_labels); |
447 | 450 | ||
448 | if (einf->value.enumerated.item >= einf->value.enumerated.items) | 451 | if (einf->value.enumerated.item >= einf->value.enumerated.items) |
449 | einf->value.enumerated.item = einf->value.enumerated.items - 1; | 452 | einf->value.enumerated.item = einf->value.enumerated.items - 1; |
450 | 453 | ||
451 | strcpy(einf->value.enumerated.name, | 454 | strcpy(einf->value.enumerated.name, |
452 | special_dig_iface_labels[einf->value.enumerated.item]); | 455 | special_dig_in_iface_labels[einf->value.enumerated.item]); |
453 | 456 | ||
454 | return 0; | 457 | return 0; |
455 | } | 458 | } |
@@ -491,26 +494,36 @@ static int special_dig_in_iface_ctl_set(struct snd_kcontrol *kctl, | |||
491 | unsigned int id, dig_in_fmt, dig_in_iface; | 494 | unsigned int id, dig_in_fmt, dig_in_iface; |
492 | int err; | 495 | int err; |
493 | 496 | ||
494 | mutex_lock(&bebob->mutex); | ||
495 | |||
496 | id = uval->value.enumerated.item[0]; | 497 | id = uval->value.enumerated.item[0]; |
498 | if (id >= ARRAY_SIZE(special_dig_in_iface_labels)) | ||
499 | return -EINVAL; | ||
497 | 500 | ||
498 | /* decode user value */ | 501 | /* decode user value */ |
499 | dig_in_fmt = (id >> 1) & 0x01; | 502 | dig_in_fmt = (id >> 1) & 0x01; |
500 | dig_in_iface = id & 0x01; | 503 | dig_in_iface = id & 0x01; |
501 | 504 | ||
505 | mutex_lock(&bebob->mutex); | ||
506 | |||
502 | err = avc_maudio_set_special_clk(bebob, | 507 | err = avc_maudio_set_special_clk(bebob, |
503 | params->clk_src, | 508 | params->clk_src, |
504 | dig_in_fmt, | 509 | dig_in_fmt, |
505 | params->dig_out_fmt, | 510 | params->dig_out_fmt, |
506 | params->clk_lock); | 511 | params->clk_lock); |
507 | if ((err < 0) || (params->dig_in_fmt > 0)) /* ADAT */ | 512 | if (err < 0) |
513 | goto end; | ||
514 | |||
515 | /* For ADAT, optical interface is only available. */ | ||
516 | if (params->dig_in_fmt > 0) { | ||
517 | err = 1; | ||
508 | goto end; | 518 | goto end; |
519 | } | ||
509 | 520 | ||
521 | /* For S/PDIF, optical/coaxial interfaces are selectable. */ | ||
510 | err = avc_audio_set_selector(bebob->unit, 0x00, 0x04, dig_in_iface); | 522 | err = avc_audio_set_selector(bebob->unit, 0x00, 0x04, dig_in_iface); |
511 | if (err < 0) | 523 | if (err < 0) |
512 | dev_err(&bebob->unit->device, | 524 | dev_err(&bebob->unit->device, |
513 | "fail to set digital input interface: %d\n", err); | 525 | "fail to set digital input interface: %d\n", err); |
526 | err = 1; | ||
514 | end: | 527 | end: |
515 | special_stream_formation_set(bebob); | 528 | special_stream_formation_set(bebob); |
516 | mutex_unlock(&bebob->mutex); | 529 | mutex_unlock(&bebob->mutex); |
@@ -525,18 +538,22 @@ static struct snd_kcontrol_new special_dig_in_iface_ctl = { | |||
525 | .put = special_dig_in_iface_ctl_set | 538 | .put = special_dig_in_iface_ctl_set |
526 | }; | 539 | }; |
527 | 540 | ||
541 | /* Digital output interface control for special firmware */ | ||
542 | static char *const special_dig_out_iface_labels[] = { | ||
543 | "S/PDIF Optical and Coaxial", "ADAT Optical" | ||
544 | }; | ||
528 | static int special_dig_out_iface_ctl_info(struct snd_kcontrol *kctl, | 545 | static int special_dig_out_iface_ctl_info(struct snd_kcontrol *kctl, |
529 | struct snd_ctl_elem_info *einf) | 546 | struct snd_ctl_elem_info *einf) |
530 | { | 547 | { |
531 | einf->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 548 | einf->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
532 | einf->count = 1; | 549 | einf->count = 1; |
533 | einf->value.enumerated.items = ARRAY_SIZE(special_dig_iface_labels) - 1; | 550 | einf->value.enumerated.items = ARRAY_SIZE(special_dig_out_iface_labels); |
534 | 551 | ||
535 | if (einf->value.enumerated.item >= einf->value.enumerated.items) | 552 | if (einf->value.enumerated.item >= einf->value.enumerated.items) |
536 | einf->value.enumerated.item = einf->value.enumerated.items - 1; | 553 | einf->value.enumerated.item = einf->value.enumerated.items - 1; |
537 | 554 | ||
538 | strcpy(einf->value.enumerated.name, | 555 | strcpy(einf->value.enumerated.name, |
539 | special_dig_iface_labels[einf->value.enumerated.item + 1]); | 556 | special_dig_out_iface_labels[einf->value.enumerated.item]); |
540 | 557 | ||
541 | return 0; | 558 | return 0; |
542 | } | 559 | } |
@@ -558,16 +575,20 @@ static int special_dig_out_iface_ctl_set(struct snd_kcontrol *kctl, | |||
558 | unsigned int id; | 575 | unsigned int id; |
559 | int err; | 576 | int err; |
560 | 577 | ||
561 | mutex_lock(&bebob->mutex); | ||
562 | |||
563 | id = uval->value.enumerated.item[0]; | 578 | id = uval->value.enumerated.item[0]; |
579 | if (id >= ARRAY_SIZE(special_dig_out_iface_labels)) | ||
580 | return -EINVAL; | ||
581 | |||
582 | mutex_lock(&bebob->mutex); | ||
564 | 583 | ||
565 | err = avc_maudio_set_special_clk(bebob, | 584 | err = avc_maudio_set_special_clk(bebob, |
566 | params->clk_src, | 585 | params->clk_src, |
567 | params->dig_in_fmt, | 586 | params->dig_in_fmt, |
568 | id, params->clk_lock); | 587 | id, params->clk_lock); |
569 | if (err >= 0) | 588 | if (err >= 0) { |
570 | special_stream_formation_set(bebob); | 589 | special_stream_formation_set(bebob); |
590 | err = 1; | ||
591 | } | ||
571 | 592 | ||
572 | mutex_unlock(&bebob->mutex); | 593 | mutex_unlock(&bebob->mutex); |
573 | return err; | 594 | return err; |