Skip to content

Commit

Permalink
[ALSA] Test volume resolution of usb audio at initialization
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Takashi Iwai authored and Jaroslav Kysela committed Mar 31, 2006
1 parent 0b2dcd5 commit 14790f1
Showing 1 changed file with 34 additions and 3 deletions.
37 changes: 34 additions & 3 deletions sound/usb/usbmixer.c
Original file line number Diff line number Diff line change
Expand Up @@ -306,8 +306,8 @@ static int get_relative_value(struct usb_mixer_elem_info *cval, int val)
cval->res = 1;
if (val < cval->min)
return 0;
else if (val > cval->max)
return (cval->max - cval->min) / cval->res;
else if (val >= cval->max)
return (cval->max - cval->min + cval->res - 1) / cval->res;
else
return (val - cval->min) / cval->res;
}
Expand Down Expand Up @@ -670,6 +670,36 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min)
}
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;
get_cur_mix_value(cval, minchn, &saved);
for (;;) {
test = saved;
if (test < cval->max)
test += cval->res;
else
test -= cval->res;
if (test < cval->min || test > cval->max ||
set_cur_mix_value(cval, minchn, test) ||
get_cur_mix_value(cval, minchn, &check)) {
cval->res = last_valid_res;
break;
}
if (test == check)
break;
cval->res *= 2;
}
set_cur_mix_value(cval, minchn, saved);
}

cval->initialized = 1;
}
return 0;
Expand All @@ -695,7 +725,8 @@ static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol, struct snd_ctl_
if (! cval->initialized)
get_min_max(cval, 0);
uinfo->value.integer.min = 0;
uinfo->value.integer.max = (cval->max - cval->min) / cval->res;
uinfo->value.integer.max =
(cval->max - cval->min + cval->res - 1) / cval->res;
}
return 0;
}
Expand Down

0 comments on commit 14790f1

Please sign in to comment.