Loading sound/usb/usbmixer.c +70 −52 Original line number Diff line number Diff line Loading @@ -110,6 +110,8 @@ struct mixer_build { const struct usbmix_selector_map *selector_map; }; #define MAX_CHANNELS 10 /* max logical channels */ struct usb_mixer_elem_info { struct usb_mixer_interface *mixer; struct usb_mixer_elem_info *next_id_elem; /* list of controls with same id */ Loading @@ -120,6 +122,8 @@ struct usb_mixer_elem_info { int channels; int val_type; int min, max, res; int cached; int cache_val[MAX_CHANNELS]; u8 initialized; }; Loading Loading @@ -181,8 +185,6 @@ enum { USB_PROC_DCR_RELEASE = 6, }; #define MAX_CHANNELS 10 /* max logical channels */ /* * manual mapping of mixer names Loading Loading @@ -376,11 +378,35 @@ static int get_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int * } /* channel = 0: master, 1 = first channel */ static inline int get_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, int *value) static inline int get_cur_mix_raw(struct usb_mixer_elem_info *cval, int channel, int *value) { return get_ctl_value(cval, GET_CUR, (cval->control << 8) | channel, value); } static int get_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, int index, int *value) { int err; if (cval->cached & (1 << channel)) { *value = cval->cache_val[index]; return 0; } err = get_cur_mix_raw(cval, channel, value); if (err < 0) { if (!cval->mixer->ignore_ctl_error) snd_printd(KERN_ERR "cannot get current value for " "control %d ch %d: err = %d\n", cval->control, channel, err); return err; } cval->cached |= 1 << channel; cval->cache_val[index] = *value; return 0; } /* * set a mixer value */ Loading Loading @@ -412,9 +438,17 @@ static int set_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int v return set_ctl_value(cval, SET_CUR, validx, value); } static inline int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, int value) static int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, int index, int value) { return set_ctl_value(cval, SET_CUR, (cval->control << 8) | channel, value); int err; err = set_ctl_value(cval, SET_CUR, (cval->control << 8) | channel, value); if (err < 0) return err; cval->cached |= 1 << channel; cval->cache_val[index] = value; return 0; } /* Loading Loading @@ -718,7 +752,7 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min) if (cval->min + cval->res < cval->max) { int last_valid_res = cval->res; int saved, test, check; get_cur_mix_value(cval, minchn, &saved); get_cur_mix_raw(cval, minchn, &saved); for (;;) { test = saved; if (test < cval->max) Loading @@ -726,8 +760,8 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min) 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)) { set_cur_mix_value(cval, minchn, 0, test) || get_cur_mix_raw(cval, minchn, &check)) { cval->res = last_valid_res; break; } Loading @@ -735,7 +769,7 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min) break; cval->res *= 2; } set_cur_mix_value(cval, minchn, saved); set_cur_mix_value(cval, minchn, 0, saved); } cval->initialized = 1; Loading Loading @@ -775,35 +809,25 @@ static int mixer_ctl_feature_get(struct snd_kcontrol *kcontrol, struct snd_ctl_e struct usb_mixer_elem_info *cval = kcontrol->private_data; int c, cnt, val, err; ucontrol->value.integer.value[0] = cval->min; if (cval->cmask) { cnt = 0; for (c = 0; c < MAX_CHANNELS; c++) { if (cval->cmask & (1 << c)) { err = get_cur_mix_value(cval, c + 1, &val); if (err < 0) { if (cval->mixer->ignore_ctl_error) { ucontrol->value.integer.value[0] = cval->min; return 0; } snd_printd(KERN_ERR "cannot get current value for control %d ch %d: err = %d\n", cval->control, c + 1, err); return err; } if (!(cval->cmask & (1 << c))) continue; err = get_cur_mix_value(cval, c + 1, cnt, &val); if (err < 0) return cval->mixer->ignore_ctl_error ? 0 : err; val = get_relative_value(cval, val); ucontrol->value.integer.value[cnt] = val; cnt++; } } return 0; } else { /* master channel */ err = get_cur_mix_value(cval, 0, &val); if (err < 0) { if (cval->mixer->ignore_ctl_error) { ucontrol->value.integer.value[0] = cval->min; return 0; } snd_printd(KERN_ERR "cannot get current value for control %d master ch: err = %d\n", cval->control, err); return err; } err = get_cur_mix_value(cval, 0, 0, &val); if (err < 0) return cval->mixer->ignore_ctl_error ? 0 : err; val = get_relative_value(cval, val); ucontrol->value.integer.value[0] = val; } Loading @@ -820,34 +844,28 @@ static int mixer_ctl_feature_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e if (cval->cmask) { cnt = 0; for (c = 0; c < MAX_CHANNELS; c++) { if (cval->cmask & (1 << c)) { err = get_cur_mix_value(cval, c + 1, &oval); if (err < 0) { if (cval->mixer->ignore_ctl_error) return 0; return err; } if (!(cval->cmask & (1 << c))) continue; err = get_cur_mix_value(cval, c + 1, cnt, &oval); if (err < 0) return cval->mixer->ignore_ctl_error ? 0 : err; val = ucontrol->value.integer.value[cnt]; val = get_abs_value(cval, val); if (oval != val) { set_cur_mix_value(cval, c + 1, val); set_cur_mix_value(cval, c + 1, cnt, val); changed = 1; } get_cur_mix_value(cval, c + 1, &val); cnt++; } } } else { /* master channel */ err = get_cur_mix_value(cval, 0, &oval); if (err < 0 && cval->mixer->ignore_ctl_error) return 0; err = get_cur_mix_value(cval, 0, 0, &oval); if (err < 0) return err; return cval->mixer->ignore_ctl_error ? 0 : err; val = ucontrol->value.integer.value[0]; val = get_abs_value(cval, val); if (val != oval) { set_cur_mix_value(cval, 0, val); set_cur_mix_value(cval, 0, 0, val); changed = 1; } } Loading Loading
sound/usb/usbmixer.c +70 −52 Original line number Diff line number Diff line Loading @@ -110,6 +110,8 @@ struct mixer_build { const struct usbmix_selector_map *selector_map; }; #define MAX_CHANNELS 10 /* max logical channels */ struct usb_mixer_elem_info { struct usb_mixer_interface *mixer; struct usb_mixer_elem_info *next_id_elem; /* list of controls with same id */ Loading @@ -120,6 +122,8 @@ struct usb_mixer_elem_info { int channels; int val_type; int min, max, res; int cached; int cache_val[MAX_CHANNELS]; u8 initialized; }; Loading Loading @@ -181,8 +185,6 @@ enum { USB_PROC_DCR_RELEASE = 6, }; #define MAX_CHANNELS 10 /* max logical channels */ /* * manual mapping of mixer names Loading Loading @@ -376,11 +378,35 @@ static int get_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int * } /* channel = 0: master, 1 = first channel */ static inline int get_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, int *value) static inline int get_cur_mix_raw(struct usb_mixer_elem_info *cval, int channel, int *value) { return get_ctl_value(cval, GET_CUR, (cval->control << 8) | channel, value); } static int get_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, int index, int *value) { int err; if (cval->cached & (1 << channel)) { *value = cval->cache_val[index]; return 0; } err = get_cur_mix_raw(cval, channel, value); if (err < 0) { if (!cval->mixer->ignore_ctl_error) snd_printd(KERN_ERR "cannot get current value for " "control %d ch %d: err = %d\n", cval->control, channel, err); return err; } cval->cached |= 1 << channel; cval->cache_val[index] = *value; return 0; } /* * set a mixer value */ Loading Loading @@ -412,9 +438,17 @@ static int set_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int v return set_ctl_value(cval, SET_CUR, validx, value); } static inline int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, int value) static int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, int index, int value) { return set_ctl_value(cval, SET_CUR, (cval->control << 8) | channel, value); int err; err = set_ctl_value(cval, SET_CUR, (cval->control << 8) | channel, value); if (err < 0) return err; cval->cached |= 1 << channel; cval->cache_val[index] = value; return 0; } /* Loading Loading @@ -718,7 +752,7 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min) if (cval->min + cval->res < cval->max) { int last_valid_res = cval->res; int saved, test, check; get_cur_mix_value(cval, minchn, &saved); get_cur_mix_raw(cval, minchn, &saved); for (;;) { test = saved; if (test < cval->max) Loading @@ -726,8 +760,8 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min) 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)) { set_cur_mix_value(cval, minchn, 0, test) || get_cur_mix_raw(cval, minchn, &check)) { cval->res = last_valid_res; break; } Loading @@ -735,7 +769,7 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min) break; cval->res *= 2; } set_cur_mix_value(cval, minchn, saved); set_cur_mix_value(cval, minchn, 0, saved); } cval->initialized = 1; Loading Loading @@ -775,35 +809,25 @@ static int mixer_ctl_feature_get(struct snd_kcontrol *kcontrol, struct snd_ctl_e struct usb_mixer_elem_info *cval = kcontrol->private_data; int c, cnt, val, err; ucontrol->value.integer.value[0] = cval->min; if (cval->cmask) { cnt = 0; for (c = 0; c < MAX_CHANNELS; c++) { if (cval->cmask & (1 << c)) { err = get_cur_mix_value(cval, c + 1, &val); if (err < 0) { if (cval->mixer->ignore_ctl_error) { ucontrol->value.integer.value[0] = cval->min; return 0; } snd_printd(KERN_ERR "cannot get current value for control %d ch %d: err = %d\n", cval->control, c + 1, err); return err; } if (!(cval->cmask & (1 << c))) continue; err = get_cur_mix_value(cval, c + 1, cnt, &val); if (err < 0) return cval->mixer->ignore_ctl_error ? 0 : err; val = get_relative_value(cval, val); ucontrol->value.integer.value[cnt] = val; cnt++; } } return 0; } else { /* master channel */ err = get_cur_mix_value(cval, 0, &val); if (err < 0) { if (cval->mixer->ignore_ctl_error) { ucontrol->value.integer.value[0] = cval->min; return 0; } snd_printd(KERN_ERR "cannot get current value for control %d master ch: err = %d\n", cval->control, err); return err; } err = get_cur_mix_value(cval, 0, 0, &val); if (err < 0) return cval->mixer->ignore_ctl_error ? 0 : err; val = get_relative_value(cval, val); ucontrol->value.integer.value[0] = val; } Loading @@ -820,34 +844,28 @@ static int mixer_ctl_feature_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e if (cval->cmask) { cnt = 0; for (c = 0; c < MAX_CHANNELS; c++) { if (cval->cmask & (1 << c)) { err = get_cur_mix_value(cval, c + 1, &oval); if (err < 0) { if (cval->mixer->ignore_ctl_error) return 0; return err; } if (!(cval->cmask & (1 << c))) continue; err = get_cur_mix_value(cval, c + 1, cnt, &oval); if (err < 0) return cval->mixer->ignore_ctl_error ? 0 : err; val = ucontrol->value.integer.value[cnt]; val = get_abs_value(cval, val); if (oval != val) { set_cur_mix_value(cval, c + 1, val); set_cur_mix_value(cval, c + 1, cnt, val); changed = 1; } get_cur_mix_value(cval, c + 1, &val); cnt++; } } } else { /* master channel */ err = get_cur_mix_value(cval, 0, &oval); if (err < 0 && cval->mixer->ignore_ctl_error) return 0; err = get_cur_mix_value(cval, 0, 0, &oval); if (err < 0) return err; return cval->mixer->ignore_ctl_error ? 0 : err; val = ucontrol->value.integer.value[0]; val = get_abs_value(cval, val); if (val != oval) { set_cur_mix_value(cval, 0, val); set_cur_mix_value(cval, 0, 0, val); changed = 1; } } Loading