A control element for digital input interface includes two settings; one is for digital format (S/PDIF or ADAT), another is for interface (optical or coaxial).
The setting for interface is meaningful just for S/PDIF, therefore to consider recovery at failure of a operation for the second setting, a operation for the first setting should be for interface, not digital format.
Additionally, this commit changes special_dig_in_iface_ctl_get() to reduce needless processing for the interface when the digital format is ADAT.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- sound/firewire/bebob/bebob_maudio.c | 70 +++++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 30 deletions(-)
diff --git a/sound/firewire/bebob/bebob_maudio.c b/sound/firewire/bebob/bebob_maudio.c index acfe94a..7899b56 100644 --- a/sound/firewire/bebob/bebob_maudio.c +++ b/sound/firewire/bebob/bebob_maudio.c @@ -471,21 +471,24 @@ static int special_dig_in_iface_ctl_get(struct snd_kcontrol *kctl,
mutex_lock(&bebob->mutex);
- err = avc_audio_get_selector(bebob->unit, 0x00, 0x04, - &dig_in_iface); - if (err < 0) { - dev_err(&bebob->unit->device, - "fail to get digital input interface: %d\n", err); - goto end; + /* For ADAT, optical interface is only available. */ + if (params->dig_in_fmt > 0) { + err = 0; + dig_in_iface = 0; + } else { + err = avc_audio_get_selector(bebob->unit, 0x00, 0x04, + &dig_in_iface); + if (err < 0) { + dev_err(&bebob->unit->device, + "fail to get digital input interface: %d\n", + err); + goto end; + } }
/* encoded id for user value */ val = (params->dig_in_fmt << 1) | (dig_in_iface & 0x01);
- /* for ADAT Optical */ - if (val > 2) - val = 2; - uval->value.enumerated.item[0] = val; end: mutex_unlock(&bebob->mutex); @@ -497,7 +500,7 @@ static int special_dig_in_iface_ctl_set(struct snd_kcontrol *kctl, struct snd_bebob *bebob = snd_kcontrol_chip(kctl); struct special_params *params = bebob->maudio_special_quirk; unsigned int id, dig_in_fmt, dig_in_iface; - int err; + int err = 0;
id = uval->value.enumerated.item[0]; if (id >= ARRAY_SIZE(special_dig_in_iface_labels)) @@ -509,29 +512,36 @@ static int special_dig_in_iface_ctl_set(struct snd_kcontrol *kctl,
mutex_lock(&bebob->mutex);
- err = avc_maudio_set_special_clk(bebob, - params->clk_src, - dig_in_fmt, - params->dig_out_fmt, - params->clk_lock); - if (err < 0) { - dev_err(&bebob->unit->device, - "fail to change clock source: %d\n", err); - goto end; - } - - /* For ADAT, optical interface is only available. */ - if (params->dig_in_fmt > 0) { + /* For S/PDIF, optical/coaxial interfaces are selectable. */ + if (dig_in_fmt == 0) { + if (amdtp_stream_running(&bebob->rx_stream)) + goto end; + + err = avc_audio_set_selector(bebob->unit, 0x00, 0x04, + dig_in_iface); + if (err < 0) { + dev_err(&bebob->unit->device, + "fail to change digital input interface: %d\n", + err); + goto end; + } err = 1; - goto end; }
- err = avc_audio_set_selector(bebob->unit, 0x00, 0x04, dig_in_iface); - if (err < 0) - dev_err(&bebob->unit->device, - "fail to set digital input interface: %d\n", err); - else + if (params->dig_in_fmt != dig_in_fmt) { + err = avc_maudio_set_special_clk(bebob, + params->clk_src, + dig_in_fmt, + params->dig_out_fmt, + params->clk_lock); + if (err < 0) { + dev_err(&bebob->unit->device, + "fail to change digital input format: %d\n", + err); + goto end; + } err = 1; + } end: mutex_unlock(&bebob->mutex); return err;