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 | |
| 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
| -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; |
