Skip to content

Commit 7549ac9

Browse files
CassivsGabriellisgregkh
authored andcommitted
ALSA: usb-audio: Update US-16x08 EQ/comp shadow state after successful writes
commit a440c17 upstream. snd_us16x08_comp_put() and snd_us16x08_eq_put() update their software stores before sending the USB write. If the transfer fails, later get callbacks report a value the hardware never accepted. Build the outgoing message from the current store plus the pending value, then commit the store only after a successful write. Fixes: d2bb390 ("ALSA: usb-audio: Tascam US-16x08 DSP mixer quirk") Cc: stable@vger.kernel.org Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com> Signed-off-by: Takashi Iwai <tiwai@suse.de> Link: https://patch.msgid.link/20260419-usb-write-error-propagation-v1-4-5a3bd4a673ae@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent ae602c0 commit 7549ac9

1 file changed

Lines changed: 52 additions & 26 deletions

File tree

sound/usb/mixer_us16x08.c

Lines changed: 52 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,7 @@ static int snd_us16x08_comp_put(struct snd_kcontrol *kcontrol,
436436
int index = ucontrol->id.index;
437437
char buf[sizeof(comp_msg)];
438438
int val_idx, val;
439+
int threshold, ratio, attack, release, gain, switch_on;
439440
int err;
440441

441442
val = ucontrol->value.integer.value[0];
@@ -448,36 +449,61 @@ static int snd_us16x08_comp_put(struct snd_kcontrol *kcontrol,
448449
/* new control value incl. bias*/
449450
val_idx = elem->head.id - SND_US16X08_ID_COMP_BASE;
450451

451-
store->val[val_idx][index] = ucontrol->value.integer.value[0];
452+
threshold = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_THRESHOLD)]
453+
[index];
454+
ratio = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_RATIO)][index];
455+
attack = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_ATTACK)][index];
456+
release = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_RELEASE)]
457+
[index];
458+
gain = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_GAIN)][index];
459+
switch_on = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_SWITCH)]
460+
[index];
461+
462+
switch (val_idx) {
463+
case COMP_STORE_IDX(SND_US16X08_ID_COMP_THRESHOLD):
464+
threshold = val;
465+
break;
466+
case COMP_STORE_IDX(SND_US16X08_ID_COMP_RATIO):
467+
ratio = val;
468+
break;
469+
case COMP_STORE_IDX(SND_US16X08_ID_COMP_ATTACK):
470+
attack = val;
471+
break;
472+
case COMP_STORE_IDX(SND_US16X08_ID_COMP_RELEASE):
473+
release = val;
474+
break;
475+
case COMP_STORE_IDX(SND_US16X08_ID_COMP_GAIN):
476+
gain = val;
477+
break;
478+
case COMP_STORE_IDX(SND_US16X08_ID_COMP_SWITCH):
479+
switch_on = val;
480+
break;
481+
}
452482

453483
/* prepare compressor URB message from template */
454484
memcpy(buf, comp_msg, sizeof(comp_msg));
455485

456486
/* place comp values in message buffer watch bias! */
457-
buf[8] = store->val[
458-
COMP_STORE_IDX(SND_US16X08_ID_COMP_THRESHOLD)][index]
459-
- SND_US16X08_COMP_THRESHOLD_BIAS;
460-
buf[11] = ratio_map[store->val[
461-
COMP_STORE_IDX(SND_US16X08_ID_COMP_RATIO)][index]];
462-
buf[14] = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_ATTACK)][index]
463-
+ SND_US16X08_COMP_ATTACK_BIAS;
464-
buf[17] = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_RELEASE)][index]
465-
+ SND_US16X08_COMP_RELEASE_BIAS;
466-
buf[20] = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_GAIN)][index];
467-
buf[26] = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_SWITCH)][index];
487+
buf[8] = threshold - SND_US16X08_COMP_THRESHOLD_BIAS;
488+
buf[11] = ratio_map[ratio];
489+
buf[14] = attack + SND_US16X08_COMP_ATTACK_BIAS;
490+
buf[17] = release + SND_US16X08_COMP_RELEASE_BIAS;
491+
buf[20] = gain;
492+
buf[26] = switch_on;
468493

469494
/* place channel selector in message buffer */
470495
buf[5] = index + 1;
471496

472497
err = snd_us16x08_send_urb(chip, buf, sizeof(comp_msg));
473498

474-
if (err > 0) {
475-
elem->cached |= 1 << index;
476-
elem->cache_val[index] = val;
477-
} else {
499+
if (err < 0) {
478500
usb_audio_dbg(chip, "Failed to set compressor, err:%d\n", err);
501+
return err;
479502
}
480503

504+
store->val[val_idx][index] = val;
505+
elem->cached |= 1 << index;
506+
elem->cache_val[index] = val;
481507
return 1;
482508
}
483509

@@ -579,11 +605,10 @@ static int snd_us16x08_eq_put(struct snd_kcontrol *kcontrol,
579605
/* copy URB buffer from EQ template */
580606
memcpy(buf, eqs_msq, sizeof(eqs_msq));
581607

582-
store->val[b_idx][p_idx][index] = val;
583-
buf[20] = store->val[b_idx][3][index];
584-
buf[17] = store->val[b_idx][2][index];
585-
buf[14] = store->val[b_idx][1][index];
586-
buf[11] = store->val[b_idx][0][index];
608+
buf[20] = p_idx == 3 ? val : store->val[b_idx][3][index];
609+
buf[17] = p_idx == 2 ? val : store->val[b_idx][2][index];
610+
buf[14] = p_idx == 1 ? val : store->val[b_idx][1][index];
611+
buf[11] = p_idx == 0 ? val : store->val[b_idx][0][index];
587612

588613
/* place channel index in URB buffer */
589614
buf[5] = index + 1;
@@ -593,14 +618,15 @@ static int snd_us16x08_eq_put(struct snd_kcontrol *kcontrol,
593618

594619
err = snd_us16x08_send_urb(chip, buf, sizeof(eqs_msq));
595620

596-
if (err > 0) {
597-
/* store new value in EQ band cache */
598-
elem->cached |= 1 << index;
599-
elem->cache_val[index] = val;
600-
} else {
621+
if (err < 0) {
601622
usb_audio_dbg(chip, "Failed to set eq param, err:%d\n", err);
623+
return err;
602624
}
603625

626+
store->val[b_idx][p_idx][index] = val;
627+
/* store new value in EQ band cache */
628+
elem->cached |= 1 << index;
629+
elem->cache_val[index] = val;
604630
return 1;
605631
}
606632

0 commit comments

Comments
 (0)