From: Rong Zhang Date: Fri, 10 Apr 2026 17:49:03 +0000 (+0800) Subject: ALSA: usb-audio: Move volume control resolution check into a function X-Git-Tag: v7.1-rc1~166^2~9^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e3ad86a82868fcde16f213240a60891c2d7bbec4;p=thirdparty%2Fkernel%2Flinux.git 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 Link: https://lore.kernel.org/r/87o6jsk3vs.wl-tiwai@suse.de Signed-off-by: Rong Zhang Link: https://patch.msgid.link/20260411-uac-sticky-mixer-v1-2-29d62717befd@rong.moe Signed-off-by: Takashi Iwai --- diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index e5993364c8250..e77c2d78a782a 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -1232,6 +1232,38 @@ static void init_cur_mix_raw(struct usb_mixer_elem_info *cval, int ch, int idx) snd_usb_set_cur_mix_value(cval, ch, idx, cval->min); } +/* + * 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 */ @@ -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; }