|
|
|
@@ -138,7 +138,7 @@ check_mapped_name(const struct usbmix_name_map *p, char *buf, int buflen)
|
|
|
|
|
|
|
|
|
|
/* ignore the error value if ignore_ctl_error flag is set */
|
|
|
|
|
#define filter_error(cval, err) \
|
|
|
|
|
((cval)->mixer->ignore_ctl_error ? 0 : (err))
|
|
|
|
|
((cval)->head.mixer->ignore_ctl_error ? 0 : (err))
|
|
|
|
|
|
|
|
|
|
/* check whether the control should be ignored */
|
|
|
|
|
static inline int
|
|
|
|
@@ -290,13 +290,13 @@ static int get_abs_value(struct usb_mixer_elem_info *cval, int val)
|
|
|
|
|
static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request,
|
|
|
|
|
int validx, int *value_ret)
|
|
|
|
|
{
|
|
|
|
|
struct snd_usb_audio *chip = cval->mixer->chip;
|
|
|
|
|
struct snd_usb_audio *chip = cval->head.mixer->chip;
|
|
|
|
|
unsigned char buf[2];
|
|
|
|
|
int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1;
|
|
|
|
|
int timeout = 10;
|
|
|
|
|
int idx = 0, err;
|
|
|
|
|
|
|
|
|
|
err = snd_usb_autoresume(cval->mixer->chip);
|
|
|
|
|
err = snd_usb_autoresume(chip);
|
|
|
|
|
if (err < 0)
|
|
|
|
|
return -EIO;
|
|
|
|
|
|
|
|
|
@@ -304,7 +304,7 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request,
|
|
|
|
|
while (timeout-- > 0) {
|
|
|
|
|
if (chip->shutdown)
|
|
|
|
|
break;
|
|
|
|
|
idx = snd_usb_ctrl_intf(chip) | (cval->id << 8);
|
|
|
|
|
idx = snd_usb_ctrl_intf(chip) | (cval->head.id << 8);
|
|
|
|
|
if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request,
|
|
|
|
|
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
|
|
|
|
|
validx, idx, buf, val_len) >= val_len) {
|
|
|
|
@@ -320,14 +320,14 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request,
|
|
|
|
|
|
|
|
|
|
out:
|
|
|
|
|
up_read(&chip->shutdown_rwsem);
|
|
|
|
|
snd_usb_autosuspend(cval->mixer->chip);
|
|
|
|
|
snd_usb_autosuspend(chip);
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request,
|
|
|
|
|
int validx, int *value_ret)
|
|
|
|
|
{
|
|
|
|
|
struct snd_usb_audio *chip = cval->mixer->chip;
|
|
|
|
|
struct snd_usb_audio *chip = cval->head.mixer->chip;
|
|
|
|
|
unsigned char buf[2 + 3 * sizeof(__u16)]; /* enough space for one range */
|
|
|
|
|
unsigned char *val;
|
|
|
|
|
int idx = 0, ret, size;
|
|
|
|
@@ -351,7 +351,7 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request,
|
|
|
|
|
if (chip->shutdown) {
|
|
|
|
|
ret = -ENODEV;
|
|
|
|
|
} else {
|
|
|
|
|
idx = snd_usb_ctrl_intf(chip) | (cval->id << 8);
|
|
|
|
|
idx = snd_usb_ctrl_intf(chip) | (cval->head.id << 8);
|
|
|
|
|
ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest,
|
|
|
|
|
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
|
|
|
|
|
validx, idx, buf, size);
|
|
|
|
@@ -396,7 +396,7 @@ static int get_ctl_value(struct usb_mixer_elem_info *cval, int request,
|
|
|
|
|
{
|
|
|
|
|
validx += cval->idx_off;
|
|
|
|
|
|
|
|
|
|
return (cval->mixer->protocol == UAC_VERSION_1) ?
|
|
|
|
|
return (cval->head.mixer->protocol == UAC_VERSION_1) ?
|
|
|
|
|
get_ctl_value_v1(cval, request, validx, value_ret) :
|
|
|
|
|
get_ctl_value_v2(cval, request, validx, value_ret);
|
|
|
|
|
}
|
|
|
|
@@ -427,8 +427,8 @@ int snd_usb_get_cur_mix_value(struct usb_mixer_elem_info *cval,
|
|
|
|
|
}
|
|
|
|
|
err = get_cur_mix_raw(cval, channel, value);
|
|
|
|
|
if (err < 0) {
|
|
|
|
|
if (!cval->mixer->ignore_ctl_error)
|
|
|
|
|
usb_audio_dbg(cval->mixer->chip,
|
|
|
|
|
if (!cval->head.mixer->ignore_ctl_error)
|
|
|
|
|
usb_audio_dbg(cval->head.mixer->chip,
|
|
|
|
|
"cannot get current value for control %d ch %d: err = %d\n",
|
|
|
|
|
cval->control, channel, err);
|
|
|
|
|
return err;
|
|
|
|
@@ -445,13 +445,13 @@ int snd_usb_get_cur_mix_value(struct usb_mixer_elem_info *cval,
|
|
|
|
|
int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
|
|
|
|
|
int request, int validx, int value_set)
|
|
|
|
|
{
|
|
|
|
|
struct snd_usb_audio *chip = cval->mixer->chip;
|
|
|
|
|
struct snd_usb_audio *chip = cval->head.mixer->chip;
|
|
|
|
|
unsigned char buf[2];
|
|
|
|
|
int idx = 0, val_len, err, timeout = 10;
|
|
|
|
|
|
|
|
|
|
validx += cval->idx_off;
|
|
|
|
|
|
|
|
|
|
if (cval->mixer->protocol == UAC_VERSION_1) {
|
|
|
|
|
if (cval->head.mixer->protocol == UAC_VERSION_1) {
|
|
|
|
|
val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1;
|
|
|
|
|
} else { /* UAC_VERSION_2 */
|
|
|
|
|
/* audio class v2 controls are always 2 bytes in size */
|
|
|
|
@@ -476,7 +476,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
|
|
|
|
|
while (timeout-- > 0) {
|
|
|
|
|
if (chip->shutdown)
|
|
|
|
|
break;
|
|
|
|
|
idx = snd_usb_ctrl_intf(chip) | (cval->id << 8);
|
|
|
|
|
idx = snd_usb_ctrl_intf(chip) | (cval->head.id << 8);
|
|
|
|
|
if (snd_usb_ctl_msg(chip->dev,
|
|
|
|
|
usb_sndctrlpipe(chip->dev, 0), request,
|
|
|
|
|
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
|
|
|
|
@@ -510,7 +510,7 @@ int snd_usb_set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel,
|
|
|
|
|
cval->ch_readonly & (1 << (channel - 1));
|
|
|
|
|
|
|
|
|
|
if (read_only) {
|
|
|
|
|
usb_audio_dbg(cval->mixer->chip,
|
|
|
|
|
usb_audio_dbg(cval->head.mixer->chip,
|
|
|
|
|
"%s(): channel %d of control %d is read_only\n",
|
|
|
|
|
__func__, channel, cval->control);
|
|
|
|
|
return 0;
|
|
|
|
@@ -569,10 +569,10 @@ static int check_matrix_bitmap(unsigned char *bmap,
|
|
|
|
|
* if failed, give up and free the control instance.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
int snd_usb_mixer_add_control(struct usb_mixer_interface *mixer,
|
|
|
|
|
int snd_usb_mixer_add_control(struct usb_mixer_elem_list *list,
|
|
|
|
|
struct snd_kcontrol *kctl)
|
|
|
|
|
{
|
|
|
|
|
struct usb_mixer_elem_info *cval = kctl->private_data;
|
|
|
|
|
struct usb_mixer_interface *mixer = list->mixer;
|
|
|
|
|
int err;
|
|
|
|
|
|
|
|
|
|
while (snd_ctl_find_id(mixer->chip->card, &kctl->id))
|
|
|
|
@@ -582,9 +582,9 @@ int snd_usb_mixer_add_control(struct usb_mixer_interface *mixer,
|
|
|
|
|
err);
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
cval->elem_id = &kctl->id;
|
|
|
|
|
cval->next_id_elem = mixer->id_elems[cval->id];
|
|
|
|
|
mixer->id_elems[cval->id] = cval;
|
|
|
|
|
list->kctl = kctl;
|
|
|
|
|
list->next_id_elem = mixer->id_elems[list->id];
|
|
|
|
|
mixer->id_elems[list->id] = list;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -833,7 +833,7 @@ void snd_usb_mixer_elem_free(struct snd_kcontrol *kctl)
|
|
|
|
|
static void volume_control_quirks(struct usb_mixer_elem_info *cval,
|
|
|
|
|
struct snd_kcontrol *kctl)
|
|
|
|
|
{
|
|
|
|
|
struct snd_usb_audio *chip = cval->mixer->chip;
|
|
|
|
|
struct snd_usb_audio *chip = cval->head.mixer->chip;
|
|
|
|
|
switch (chip->usb_id) {
|
|
|
|
|
case USB_ID(0x0763, 0x2030): /* M-Audio Fast Track C400 */
|
|
|
|
|
case USB_ID(0x0763, 0x2031): /* M-Audio Fast Track C600 */
|
|
|
|
@@ -958,10 +958,10 @@ static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval,
|
|
|
|
|
}
|
|
|
|
|
if (get_ctl_value(cval, UAC_GET_MAX, (cval->control << 8) | minchn, &cval->max) < 0 ||
|
|
|
|
|
get_ctl_value(cval, UAC_GET_MIN, (cval->control << 8) | minchn, &cval->min) < 0) {
|
|
|
|
|
usb_audio_err(cval->mixer->chip,
|
|
|
|
|
usb_audio_err(cval->head.mixer->chip,
|
|
|
|
|
"%d:%d: cannot get min/max values for control %d (id %d)\n",
|
|
|
|
|
cval->id, snd_usb_ctrl_intf(cval->mixer->chip),
|
|
|
|
|
cval->control, cval->id);
|
|
|
|
|
cval->head.id, snd_usb_ctrl_intf(cval->head.mixer->chip),
|
|
|
|
|
cval->control, cval->head.id);
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
}
|
|
|
|
|
if (get_ctl_value(cval, UAC_GET_RES,
|
|
|
|
@@ -1065,7 +1065,7 @@ static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol,
|
|
|
|
|
kcontrol->vd[0].access &=
|
|
|
|
|
~(SNDRV_CTL_ELEM_ACCESS_TLV_READ |
|
|
|
|
|
SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK);
|
|
|
|
|
snd_ctl_notify(cval->mixer->chip->card,
|
|
|
|
|
snd_ctl_notify(cval->head.mixer->chip->card,
|
|
|
|
|
SNDRV_CTL_EVENT_MASK_INFO,
|
|
|
|
|
&kcontrol->id);
|
|
|
|
|
}
|
|
|
|
@@ -1235,8 +1235,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
|
|
|
|
|
cval = kzalloc(sizeof(*cval), GFP_KERNEL);
|
|
|
|
|
if (!cval)
|
|
|
|
|
return;
|
|
|
|
|
cval->mixer = state->mixer;
|
|
|
|
|
cval->id = unitid;
|
|
|
|
|
snd_usb_mixer_elem_init_std(&cval->head, state->mixer, unitid);
|
|
|
|
|
cval->control = control;
|
|
|
|
|
cval->cmask = ctl_mask;
|
|
|
|
|
cval->val_type = audio_feature_info[control-1].type;
|
|
|
|
@@ -1347,14 +1346,14 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
|
|
|
|
|
range);
|
|
|
|
|
usb_audio_warn(state->chip,
|
|
|
|
|
"[%d] FU [%s] ch = %d, val = %d/%d/%d",
|
|
|
|
|
cval->id, kctl->id.name, cval->channels,
|
|
|
|
|
cval->head.id, kctl->id.name, cval->channels,
|
|
|
|
|
cval->min, cval->max, cval->res);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
usb_audio_dbg(state->chip, "[%d] FU [%s] ch = %d, val = %d/%d/%d\n",
|
|
|
|
|
cval->id, kctl->id.name, cval->channels,
|
|
|
|
|
cval->head.id, kctl->id.name, cval->channels,
|
|
|
|
|
cval->min, cval->max, cval->res);
|
|
|
|
|
snd_usb_mixer_add_control(state->mixer, kctl);
|
|
|
|
|
snd_usb_mixer_add_control(&cval->head, kctl);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@@ -1528,8 +1527,7 @@ static void build_mixer_unit_ctl(struct mixer_build *state,
|
|
|
|
|
if (!cval)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
cval->mixer = state->mixer;
|
|
|
|
|
cval->id = unitid;
|
|
|
|
|
snd_usb_mixer_elem_init_std(&cval->head, state->mixer, unitid);
|
|
|
|
|
cval->control = in_ch + 1; /* based on 1 */
|
|
|
|
|
cval->val_type = USB_MIXER_S16;
|
|
|
|
|
for (i = 0; i < num_outs; i++) {
|
|
|
|
@@ -1561,8 +1559,8 @@ static void build_mixer_unit_ctl(struct mixer_build *state,
|
|
|
|
|
append_ctl_name(kctl, " Volume");
|
|
|
|
|
|
|
|
|
|
usb_audio_dbg(state->chip, "[%d] MU [%s] ch = %d, val = %d/%d\n",
|
|
|
|
|
cval->id, kctl->id.name, cval->channels, cval->min, cval->max);
|
|
|
|
|
snd_usb_mixer_add_control(state->mixer, kctl);
|
|
|
|
|
cval->head.id, kctl->id.name, cval->channels, cval->min, cval->max);
|
|
|
|
|
snd_usb_mixer_add_control(&cval->head, kctl);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@@ -1812,8 +1810,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid,
|
|
|
|
|
cval = kzalloc(sizeof(*cval), GFP_KERNEL);
|
|
|
|
|
if (!cval)
|
|
|
|
|
return -ENOMEM;
|
|
|
|
|
cval->mixer = state->mixer;
|
|
|
|
|
cval->id = unitid;
|
|
|
|
|
snd_usb_mixer_elem_init_std(&cval->head, state->mixer, unitid);
|
|
|
|
|
cval->control = valinfo->control;
|
|
|
|
|
cval->val_type = valinfo->val_type;
|
|
|
|
|
cval->channels = 1;
|
|
|
|
@@ -1866,10 +1863,10 @@ static int build_audio_procunit(struct mixer_build *state, int unitid,
|
|
|
|
|
|
|
|
|
|
usb_audio_dbg(state->chip,
|
|
|
|
|
"[%d] PU [%s] ch = %d, val = %d/%d\n",
|
|
|
|
|
cval->id, kctl->id.name, cval->channels,
|
|
|
|
|
cval->head.id, kctl->id.name, cval->channels,
|
|
|
|
|
cval->min, cval->max);
|
|
|
|
|
|
|
|
|
|
err = snd_usb_mixer_add_control(state->mixer, kctl);
|
|
|
|
|
err = snd_usb_mixer_add_control(&cval->head, kctl);
|
|
|
|
|
if (err < 0)
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
@@ -2016,8 +2013,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid,
|
|
|
|
|
cval = kzalloc(sizeof(*cval), GFP_KERNEL);
|
|
|
|
|
if (!cval)
|
|
|
|
|
return -ENOMEM;
|
|
|
|
|
cval->mixer = state->mixer;
|
|
|
|
|
cval->id = unitid;
|
|
|
|
|
snd_usb_mixer_elem_init_std(&cval->head, state->mixer, unitid);
|
|
|
|
|
cval->val_type = USB_MIXER_U8;
|
|
|
|
|
cval->channels = 1;
|
|
|
|
|
cval->min = 1;
|
|
|
|
@@ -2088,11 +2084,8 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
usb_audio_dbg(state->chip, "[%d] SU [%s] items = %d\n",
|
|
|
|
|
cval->id, kctl->id.name, desc->bNrInPins);
|
|
|
|
|
if ((err = snd_usb_mixer_add_control(state->mixer, kctl)) < 0)
|
|
|
|
|
return err;
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
cval->head.id, kctl->id.name, desc->bNrInPins);
|
|
|
|
|
return snd_usb_mixer_add_control(&cval->head, kctl);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@@ -2237,25 +2230,21 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
|
|
|
|
|
|
|
|
|
|
void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid)
|
|
|
|
|
{
|
|
|
|
|
struct usb_mixer_elem_info *info;
|
|
|
|
|
struct usb_mixer_elem_list *list;
|
|
|
|
|
|
|
|
|
|
for (info = mixer->id_elems[unitid]; info; info = info->next_id_elem)
|
|
|
|
|
for (list = mixer->id_elems[unitid]; list; list = list->next_id_elem)
|
|
|
|
|
snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
|
|
|
|
|
info->elem_id);
|
|
|
|
|
&list->kctl->id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void snd_usb_mixer_dump_cval(struct snd_info_buffer *buffer,
|
|
|
|
|
int unitid,
|
|
|
|
|
struct usb_mixer_elem_info *cval)
|
|
|
|
|
struct usb_mixer_elem_list *list)
|
|
|
|
|
{
|
|
|
|
|
struct usb_mixer_elem_info *cval = (struct usb_mixer_elem_info *)list;
|
|
|
|
|
static char *val_types[] = {"BOOLEAN", "INV_BOOLEAN",
|
|
|
|
|
"S8", "U8", "S16", "U16"};
|
|
|
|
|
snd_iprintf(buffer, " Unit: %i\n", unitid);
|
|
|
|
|
if (cval->elem_id)
|
|
|
|
|
snd_iprintf(buffer, " Control: name=\"%s\", index=%i\n",
|
|
|
|
|
cval->elem_id->name, cval->elem_id->index);
|
|
|
|
|
snd_iprintf(buffer, " Info: id=%i, control=%i, cmask=0x%x, "
|
|
|
|
|
"channels=%i, type=\"%s\"\n", cval->id,
|
|
|
|
|
"channels=%i, type=\"%s\"\n", cval->head.id,
|
|
|
|
|
cval->control, cval->cmask, cval->channels,
|
|
|
|
|
val_types[cval->val_type]);
|
|
|
|
|
snd_iprintf(buffer, " Volume: min=%i, max=%i, dBmin=%i, dBmax=%i\n",
|
|
|
|
@@ -2267,7 +2256,7 @@ static void snd_usb_mixer_proc_read(struct snd_info_entry *entry,
|
|
|
|
|
{
|
|
|
|
|
struct snd_usb_audio *chip = entry->private_data;
|
|
|
|
|
struct usb_mixer_interface *mixer;
|
|
|
|
|
struct usb_mixer_elem_info *cval;
|
|
|
|
|
struct usb_mixer_elem_list *list;
|
|
|
|
|
int unitid;
|
|
|
|
|
|
|
|
|
|
list_for_each_entry(mixer, &chip->mixer_list, list) {
|
|
|
|
@@ -2277,9 +2266,17 @@ static void snd_usb_mixer_proc_read(struct snd_info_entry *entry,
|
|
|
|
|
mixer->ignore_ctl_error);
|
|
|
|
|
snd_iprintf(buffer, "Card: %s\n", chip->card->longname);
|
|
|
|
|
for (unitid = 0; unitid < MAX_ID_ELEMS; unitid++) {
|
|
|
|
|
for (cval = mixer->id_elems[unitid]; cval;
|
|
|
|
|
cval = cval->next_id_elem)
|
|
|
|
|
snd_usb_mixer_dump_cval(buffer, unitid, cval);
|
|
|
|
|
for (list = mixer->id_elems[unitid]; list;
|
|
|
|
|
list = list->next_id_elem) {
|
|
|
|
|
snd_iprintf(buffer, " Unit: %i\n", list->id);
|
|
|
|
|
if (list->kctl)
|
|
|
|
|
snd_iprintf(buffer,
|
|
|
|
|
" Control: name=\"%s\", index=%i\n",
|
|
|
|
|
list->kctl->id.name,
|
|
|
|
|
list->kctl->id.index);
|
|
|
|
|
if (list->dump)
|
|
|
|
|
list->dump(buffer, list);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -2287,7 +2284,7 @@ static void snd_usb_mixer_proc_read(struct snd_info_entry *entry,
|
|
|
|
|
static void snd_usb_mixer_interrupt_v2(struct usb_mixer_interface *mixer,
|
|
|
|
|
int attribute, int value, int index)
|
|
|
|
|
{
|
|
|
|
|
struct usb_mixer_elem_info *info;
|
|
|
|
|
struct usb_mixer_elem_list *list;
|
|
|
|
|
__u8 unitid = (index >> 8) & 0xff;
|
|
|
|
|
__u8 control = (value >> 8) & 0xff;
|
|
|
|
|
__u8 channel = value & 0xff;
|
|
|
|
@@ -2299,7 +2296,13 @@ static void snd_usb_mixer_interrupt_v2(struct usb_mixer_interface *mixer,
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (info = mixer->id_elems[unitid]; info; info = info->next_id_elem) {
|
|
|
|
|
for (list = mixer->id_elems[unitid]; list; list = list->next_id_elem) {
|
|
|
|
|
struct usb_mixer_elem_info *info;
|
|
|
|
|
|
|
|
|
|
if (!list->kctl)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
info = (struct usb_mixer_elem_info *)list;
|
|
|
|
|
if (info->control != control)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
@@ -2312,7 +2315,7 @@ static void snd_usb_mixer_interrupt_v2(struct usb_mixer_interface *mixer,
|
|
|
|
|
info->cached = 0;
|
|
|
|
|
|
|
|
|
|
snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
|
|
|
|
|
info->elem_id);
|
|
|
|
|
&info->head.kctl->id);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case UAC2_CS_RANGE:
|
|
|
|
@@ -2510,8 +2513,9 @@ int snd_usb_mixer_suspend(struct usb_mixer_interface *mixer)
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int restore_mixer_value(struct usb_mixer_elem_info *cval)
|
|
|
|
|
static int restore_mixer_value(struct usb_mixer_elem_list *list)
|
|
|
|
|
{
|
|
|
|
|
struct usb_mixer_elem_info *cval = (struct usb_mixer_elem_info *)list;
|
|
|
|
|
int c, err, idx;
|
|
|
|
|
|
|
|
|
|
if (cval->cmask) {
|
|
|
|
@@ -2541,19 +2545,19 @@ static int restore_mixer_value(struct usb_mixer_elem_info *cval)
|
|
|
|
|
|
|
|
|
|
int snd_usb_mixer_resume(struct usb_mixer_interface *mixer, bool reset_resume)
|
|
|
|
|
{
|
|
|
|
|
struct usb_mixer_elem_info *cval;
|
|
|
|
|
struct usb_mixer_elem_list *list;
|
|
|
|
|
int id, err;
|
|
|
|
|
|
|
|
|
|
/* FIXME: any mixer quirks? */
|
|
|
|
|
|
|
|
|
|
if (reset_resume) {
|
|
|
|
|
/* restore cached mixer values */
|
|
|
|
|
for (id = 0; id < MAX_ID_ELEMS; id++) {
|
|
|
|
|
for (cval = mixer->id_elems[id]; cval;
|
|
|
|
|
cval = cval->next_id_elem) {
|
|
|
|
|
err = restore_mixer_value(cval);
|
|
|
|
|
if (err < 0)
|
|
|
|
|
return err;
|
|
|
|
|
for (list = mixer->id_elems[id]; list;
|
|
|
|
|
list = list->next_id_elem) {
|
|
|
|
|
if (list->resume) {
|
|
|
|
|
err = list->resume(list);
|
|
|
|
|
if (err < 0)
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -2561,3 +2565,15 @@ int snd_usb_mixer_resume(struct usb_mixer_interface *mixer, bool reset_resume)
|
|
|
|
|
return snd_usb_mixer_activate(mixer);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
void snd_usb_mixer_elem_init_std(struct usb_mixer_elem_list *list,
|
|
|
|
|
struct usb_mixer_interface *mixer,
|
|
|
|
|
int unitid)
|
|
|
|
|
{
|
|
|
|
|
list->mixer = mixer;
|
|
|
|
|
list->id = unitid;
|
|
|
|
|
list->dump = snd_usb_mixer_dump_cval;
|
|
|
|
|
#ifdef CONFIG_PM
|
|
|
|
|
list->resume = restore_mixer_value;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|