summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRong Zhang <i@rong.moe>2026-04-11 01:49:03 +0800
committerTakashi Iwai <tiwai@suse.de>2026-04-11 10:02:53 +0200
commite3ad86a82868fcde16f213240a60891c2d7bbec4 (patch)
tree0497816263c2b6b416d058cfb8b334b7543efd33
parent4f55a85cd4fc988712965f710ba1475e7ba3292a (diff)
ALSA: usb-audio: Move volume control resolution check into a function
get_min_max_with_quirks() is too lengthy and hard to read. Move the volume control resolution check code into a function as it's relatively self-contained. Suggested-by: Takashi Iwai <tiwai@suse.de> Link: https://lore.kernel.org/r/87o6jsk3vs.wl-tiwai@suse.de Signed-off-by: Rong Zhang <i@rong.moe> Link: https://patch.msgid.link/20260411-uac-sticky-mixer-v1-2-29d62717befd@rong.moe Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/usb/mixer.c65
1 files changed, 39 insertions, 26 deletions
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index e5993364c825..e77c2d78a782 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -1233,6 +1233,38 @@ static void init_cur_mix_raw(struct usb_mixer_elem_info *cval, int ch, int idx)
}
/*
+ * Additional checks for the proper resolution
+ *
+ * Some devices report smaller resolutions than actually reacting.
+ * They don't return errors but simply clip to the lower aligned value.
+ */
+static void check_volume_control_res(struct usb_mixer_elem_info *cval,
+ int channel, int saved)
+{
+ int last_valid_res = cval->res;
+ int test, check;
+
+ for (;;) {
+ test = saved;
+ if (test < cval->max)
+ test += cval->res;
+ else
+ test -= cval->res;
+
+ if (test < cval->min || test > cval->max ||
+ snd_usb_set_cur_mix_value(cval, channel, 0, test) ||
+ get_cur_mix_raw(cval, channel, &check)) {
+ cval->res = last_valid_res;
+ break;
+ }
+ if (test == check)
+ break;
+
+ cval->res *= 2;
+ }
+}
+
+/*
* retrieve the minimum and maximum values for the specified control
*/
static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval,
@@ -1287,37 +1319,18 @@ static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval,
if (cval->res == 0)
cval->res = 1;
- /* Additional checks for the proper resolution
- *
- * Some devices report smaller resolutions than actually
- * reacting. They don't return errors but simply clip
- * to the lower aligned value.
- */
if (cval->min + cval->res < cval->max) {
- int last_valid_res = cval->res;
- int saved, test, check;
+ int saved;
+
if (get_cur_mix_raw(cval, minchn, &saved) < 0)
- goto no_res_check;
- for (;;) {
- test = saved;
- if (test < cval->max)
- test += cval->res;
- else
- test -= cval->res;
- if (test < cval->min || test > cval->max ||
- snd_usb_set_cur_mix_value(cval, minchn, 0, test) ||
- get_cur_mix_raw(cval, minchn, &check)) {
- cval->res = last_valid_res;
- break;
- }
- if (test == check)
- break;
- cval->res *= 2;
- }
+ goto no_checks;
+
+ check_volume_control_res(cval, minchn, saved);
+
snd_usb_set_cur_mix_value(cval, minchn, 0, saved);
}
-no_res_check:
+no_checks:
cval->initialized = 1;
}