[ALSA] Test volume resolution of usb audio at initialization

Test the volume of usb audio whether actually it works and adjusts
the resolution value according to it.

Some USB audio devices report a lower resolution than it reacts.
The only possible check is to write and read a volume value.

Signed-off-by: Takashi Iwai <tiwai@suse.de>

authored by Takashi Iwai and committed by Jaroslav Kysela 14790f1c 0b2dcd5d

+34 -3
+34 -3
sound/usb/usbmixer.c
··· 306 306 cval->res = 1; 307 307 if (val < cval->min) 308 308 return 0; 309 - else if (val > cval->max) 310 - return (cval->max - cval->min) / cval->res; 309 + else if (val >= cval->max) 310 + return (cval->max - cval->min + cval->res - 1) / cval->res; 311 311 else 312 312 return (val - cval->min) / cval->res; 313 313 } ··· 670 670 } 671 671 if (cval->res == 0) 672 672 cval->res = 1; 673 + 674 + /* Additional checks for the proper resolution 675 + * 676 + * Some devices report smaller resolutions than actually 677 + * reacting. They don't return errors but simply clip 678 + * to the lower aligned value. 679 + */ 680 + if (cval->min + cval->res < cval->max) { 681 + int last_valid_res = cval->res; 682 + int saved, test, check; 683 + get_cur_mix_value(cval, minchn, &saved); 684 + for (;;) { 685 + test = saved; 686 + if (test < cval->max) 687 + test += cval->res; 688 + else 689 + test -= cval->res; 690 + if (test < cval->min || test > cval->max || 691 + set_cur_mix_value(cval, minchn, test) || 692 + get_cur_mix_value(cval, minchn, &check)) { 693 + cval->res = last_valid_res; 694 + break; 695 + } 696 + if (test == check) 697 + break; 698 + cval->res *= 2; 699 + } 700 + set_cur_mix_value(cval, minchn, saved); 701 + } 702 + 673 703 cval->initialized = 1; 674 704 } 675 705 return 0; ··· 725 695 if (! cval->initialized) 726 696 get_min_max(cval, 0); 727 697 uinfo->value.integer.min = 0; 728 - uinfo->value.integer.max = (cval->max - cval->min) / cval->res; 698 + uinfo->value.integer.max = 699 + (cval->max - cval->min + cval->res - 1) / cval->res; 729 700 } 730 701 return 0; 731 702 }