Loading sound/usb/usbmixer.c +70 −52 Original line number Original line Diff line number Diff line Loading @@ -110,6 +110,8 @@ struct mixer_build { const struct usbmix_selector_map *selector_map; const struct usbmix_selector_map *selector_map; }; }; #define MAX_CHANNELS 10 /* max logical channels */ struct usb_mixer_elem_info { struct usb_mixer_elem_info { struct usb_mixer_interface *mixer; struct usb_mixer_interface *mixer; struct usb_mixer_elem_info *next_id_elem; /* list of controls with same id */ 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 channels; int val_type; int val_type; int min, max, res; int min, max, res; int cached; int cache_val[MAX_CHANNELS]; u8 initialized; u8 initialized; }; }; Loading Loading @@ -181,8 +185,6 @@ enum { USB_PROC_DCR_RELEASE = 6, USB_PROC_DCR_RELEASE = 6, }; }; #define MAX_CHANNELS 10 /* max logical channels */ /* /* * manual mapping of mixer names * 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 */ /* 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); 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 * 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); 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) { if (cval->min + cval->res < cval->max) { int last_valid_res = cval->res; int last_valid_res = cval->res; int saved, test, check; int saved, test, check; get_cur_mix_value(cval, minchn, &saved); get_cur_mix_raw(cval, minchn, &saved); for (;;) { for (;;) { test = saved; test = saved; if (test < cval->max) if (test < cval->max) Loading @@ -726,8 +760,8 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min) else else test -= cval->res; test -= cval->res; if (test < cval->min || test > cval->max || if (test < cval->min || test > cval->max || set_cur_mix_value(cval, minchn, test) || set_cur_mix_value(cval, minchn, 0, test) || get_cur_mix_value(cval, minchn, &check)) { get_cur_mix_raw(cval, minchn, &check)) { cval->res = last_valid_res; cval->res = last_valid_res; break; break; } } Loading @@ -735,7 +769,7 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min) break; break; cval->res *= 2; cval->res *= 2; } } set_cur_mix_value(cval, minchn, saved); set_cur_mix_value(cval, minchn, 0, saved); } } cval->initialized = 1; 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; struct usb_mixer_elem_info *cval = kcontrol->private_data; int c, cnt, val, err; int c, cnt, val, err; ucontrol->value.integer.value[0] = cval->min; if (cval->cmask) { if (cval->cmask) { cnt = 0; cnt = 0; for (c = 0; c < MAX_CHANNELS; c++) { for (c = 0; c < MAX_CHANNELS; c++) { if (cval->cmask & (1 << c)) { if (!(cval->cmask & (1 << c))) err = get_cur_mix_value(cval, c + 1, &val); continue; if (err < 0) { err = get_cur_mix_value(cval, c + 1, cnt, &val); if (cval->mixer->ignore_ctl_error) { if (err < 0) ucontrol->value.integer.value[0] = cval->min; return cval->mixer->ignore_ctl_error ? 0 : err; 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; } val = get_relative_value(cval, val); val = get_relative_value(cval, val); ucontrol->value.integer.value[cnt] = val; ucontrol->value.integer.value[cnt] = val; cnt++; cnt++; } } } return 0; } else { } else { /* master channel */ /* master channel */ err = get_cur_mix_value(cval, 0, &val); err = get_cur_mix_value(cval, 0, 0, &val); if (err < 0) { if (err < 0) if (cval->mixer->ignore_ctl_error) { return cval->mixer->ignore_ctl_error ? 0 : err; 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; } val = get_relative_value(cval, val); val = get_relative_value(cval, val); ucontrol->value.integer.value[0] = 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) { if (cval->cmask) { cnt = 0; cnt = 0; for (c = 0; c < MAX_CHANNELS; c++) { for (c = 0; c < MAX_CHANNELS; c++) { if (cval->cmask & (1 << c)) { if (!(cval->cmask & (1 << c))) err = get_cur_mix_value(cval, c + 1, &oval); continue; if (err < 0) { err = get_cur_mix_value(cval, c + 1, cnt, &oval); if (cval->mixer->ignore_ctl_error) if (err < 0) return 0; return cval->mixer->ignore_ctl_error ? 0 : err; return err; } val = ucontrol->value.integer.value[cnt]; val = ucontrol->value.integer.value[cnt]; val = get_abs_value(cval, val); val = get_abs_value(cval, val); if (oval != val) { if (oval != val) { set_cur_mix_value(cval, c + 1, val); set_cur_mix_value(cval, c + 1, cnt, val); changed = 1; changed = 1; } } get_cur_mix_value(cval, c + 1, &val); cnt++; cnt++; } } } } else { } else { /* master channel */ /* master channel */ err = get_cur_mix_value(cval, 0, &oval); err = get_cur_mix_value(cval, 0, 0, &oval); if (err < 0 && cval->mixer->ignore_ctl_error) return 0; if (err < 0) if (err < 0) return err; return cval->mixer->ignore_ctl_error ? 0 : err; val = ucontrol->value.integer.value[0]; val = ucontrol->value.integer.value[0]; val = get_abs_value(cval, val); val = get_abs_value(cval, val); if (val != oval) { if (val != oval) { set_cur_mix_value(cval, 0, val); set_cur_mix_value(cval, 0, 0, val); changed = 1; changed = 1; } } } } Loading Loading
sound/usb/usbmixer.c +70 −52 Original line number Original line Diff line number Diff line Loading @@ -110,6 +110,8 @@ struct mixer_build { const struct usbmix_selector_map *selector_map; const struct usbmix_selector_map *selector_map; }; }; #define MAX_CHANNELS 10 /* max logical channels */ struct usb_mixer_elem_info { struct usb_mixer_elem_info { struct usb_mixer_interface *mixer; struct usb_mixer_interface *mixer; struct usb_mixer_elem_info *next_id_elem; /* list of controls with same id */ 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 channels; int val_type; int val_type; int min, max, res; int min, max, res; int cached; int cache_val[MAX_CHANNELS]; u8 initialized; u8 initialized; }; }; Loading Loading @@ -181,8 +185,6 @@ enum { USB_PROC_DCR_RELEASE = 6, USB_PROC_DCR_RELEASE = 6, }; }; #define MAX_CHANNELS 10 /* max logical channels */ /* /* * manual mapping of mixer names * 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 */ /* 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); 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 * 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); 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) { if (cval->min + cval->res < cval->max) { int last_valid_res = cval->res; int last_valid_res = cval->res; int saved, test, check; int saved, test, check; get_cur_mix_value(cval, minchn, &saved); get_cur_mix_raw(cval, minchn, &saved); for (;;) { for (;;) { test = saved; test = saved; if (test < cval->max) if (test < cval->max) Loading @@ -726,8 +760,8 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min) else else test -= cval->res; test -= cval->res; if (test < cval->min || test > cval->max || if (test < cval->min || test > cval->max || set_cur_mix_value(cval, minchn, test) || set_cur_mix_value(cval, minchn, 0, test) || get_cur_mix_value(cval, minchn, &check)) { get_cur_mix_raw(cval, minchn, &check)) { cval->res = last_valid_res; cval->res = last_valid_res; break; break; } } Loading @@ -735,7 +769,7 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min) break; break; cval->res *= 2; cval->res *= 2; } } set_cur_mix_value(cval, minchn, saved); set_cur_mix_value(cval, minchn, 0, saved); } } cval->initialized = 1; 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; struct usb_mixer_elem_info *cval = kcontrol->private_data; int c, cnt, val, err; int c, cnt, val, err; ucontrol->value.integer.value[0] = cval->min; if (cval->cmask) { if (cval->cmask) { cnt = 0; cnt = 0; for (c = 0; c < MAX_CHANNELS; c++) { for (c = 0; c < MAX_CHANNELS; c++) { if (cval->cmask & (1 << c)) { if (!(cval->cmask & (1 << c))) err = get_cur_mix_value(cval, c + 1, &val); continue; if (err < 0) { err = get_cur_mix_value(cval, c + 1, cnt, &val); if (cval->mixer->ignore_ctl_error) { if (err < 0) ucontrol->value.integer.value[0] = cval->min; return cval->mixer->ignore_ctl_error ? 0 : err; 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; } val = get_relative_value(cval, val); val = get_relative_value(cval, val); ucontrol->value.integer.value[cnt] = val; ucontrol->value.integer.value[cnt] = val; cnt++; cnt++; } } } return 0; } else { } else { /* master channel */ /* master channel */ err = get_cur_mix_value(cval, 0, &val); err = get_cur_mix_value(cval, 0, 0, &val); if (err < 0) { if (err < 0) if (cval->mixer->ignore_ctl_error) { return cval->mixer->ignore_ctl_error ? 0 : err; 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; } val = get_relative_value(cval, val); val = get_relative_value(cval, val); ucontrol->value.integer.value[0] = 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) { if (cval->cmask) { cnt = 0; cnt = 0; for (c = 0; c < MAX_CHANNELS; c++) { for (c = 0; c < MAX_CHANNELS; c++) { if (cval->cmask & (1 << c)) { if (!(cval->cmask & (1 << c))) err = get_cur_mix_value(cval, c + 1, &oval); continue; if (err < 0) { err = get_cur_mix_value(cval, c + 1, cnt, &oval); if (cval->mixer->ignore_ctl_error) if (err < 0) return 0; return cval->mixer->ignore_ctl_error ? 0 : err; return err; } val = ucontrol->value.integer.value[cnt]; val = ucontrol->value.integer.value[cnt]; val = get_abs_value(cval, val); val = get_abs_value(cval, val); if (oval != val) { if (oval != val) { set_cur_mix_value(cval, c + 1, val); set_cur_mix_value(cval, c + 1, cnt, val); changed = 1; changed = 1; } } get_cur_mix_value(cval, c + 1, &val); cnt++; cnt++; } } } } else { } else { /* master channel */ /* master channel */ err = get_cur_mix_value(cval, 0, &oval); err = get_cur_mix_value(cval, 0, 0, &oval); if (err < 0 && cval->mixer->ignore_ctl_error) return 0; if (err < 0) if (err < 0) return err; return cval->mixer->ignore_ctl_error ? 0 : err; val = ucontrol->value.integer.value[0]; val = ucontrol->value.integer.value[0]; val = get_abs_value(cval, val); val = get_abs_value(cval, val); if (val != oval) { if (val != oval) { set_cur_mix_value(cval, 0, val); set_cur_mix_value(cval, 0, 0, val); changed = 1; changed = 1; } } } } Loading