summaryrefslogtreecommitdiff
path: root/sound/usb/mixer.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/usb/mixer.c')
-rw-r--r--sound/usb/mixer.c79
1 files changed, 59 insertions, 20 deletions
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index b004b2e63a5d..428d581f988f 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -1446,13 +1446,11 @@ static int mixer_ctl_master_bool_get(struct snd_kcontrol *kcontrol,
return 0;
}
-/* get the connectors status and report it as boolean type */
-static int mixer_ctl_connector_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
+static int get_connector_value(struct usb_mixer_elem_info *cval,
+ char *name, int *val)
{
- struct usb_mixer_elem_info *cval = kcontrol->private_data;
struct snd_usb_audio *chip = cval->head.mixer->chip;
- int idx = 0, validx, ret, val;
+ int idx = 0, validx, ret;
validx = cval->control << 8 | 0;
@@ -1467,21 +1465,24 @@ static int mixer_ctl_connector_get(struct snd_kcontrol *kcontrol,
ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), UAC2_CS_CUR,
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
validx, idx, &uac2_conn, sizeof(uac2_conn));
- val = !!uac2_conn.bNrChannels;
+ if (val)
+ *val = !!uac2_conn.bNrChannels;
} else { /* UAC_VERSION_3 */
struct uac3_insertion_ctl_blk uac3_conn;
ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), UAC2_CS_CUR,
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
validx, idx, &uac3_conn, sizeof(uac3_conn));
- val = !!uac3_conn.bmConInserted;
+ if (val)
+ *val = !!uac3_conn.bmConInserted;
}
snd_usb_unlock_shutdown(chip);
if (ret < 0) {
- if (strstr(kcontrol->id.name, "Speaker")) {
- ucontrol->value.integer.value[0] = 1;
+ if (name && strstr(name, "Speaker")) {
+ if (val)
+ *val = 1;
return 0;
}
error:
@@ -1491,6 +1492,21 @@ error:
return filter_error(cval, ret);
}
+ return ret;
+}
+
+/* get the connectors status and report it as boolean type */
+static int mixer_ctl_connector_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct usb_mixer_elem_info *cval = kcontrol->private_data;
+ int ret, val;
+
+ ret = get_connector_value(cval, kcontrol->id.name, &val);
+
+ if (ret < 0)
+ return ret;
+
ucontrol->value.integer.value[0] = val;
return 0;
}
@@ -2710,7 +2726,6 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid,
#define MAX_ITEM_NAME_LEN 64
for (i = 0; i < desc->bNrInPins; i++) {
struct usb_audio_term iterm;
- len = 0;
namelist[i] = kmalloc(MAX_ITEM_NAME_LEN, GFP_KERNEL);
if (!namelist[i]) {
err = -ENOMEM;
@@ -3615,20 +3630,43 @@ static int restore_mixer_value(struct usb_mixer_elem_list *list)
return 0;
}
+static int default_mixer_resume(struct usb_mixer_elem_list *list)
+{
+ struct usb_mixer_elem_info *cval = mixer_elem_list_to_info(list);
+
+ /* get connector value to "wake up" the USB audio */
+ if (cval->val_type == USB_MIXER_BOOLEAN && cval->channels == 1)
+ get_connector_value(cval, NULL, NULL);
+
+ return 0;
+}
+
+static int default_mixer_reset_resume(struct usb_mixer_elem_list *list)
+{
+ int err = default_mixer_resume(list);
+
+ if (err < 0)
+ return err;
+ return restore_mixer_value(list);
+}
+
int snd_usb_mixer_resume(struct usb_mixer_interface *mixer, bool reset_resume)
{
struct usb_mixer_elem_list *list;
+ usb_mixer_elem_resume_func_t f;
int id, err;
- if (reset_resume) {
- /* restore cached mixer values */
- for (id = 0; id < MAX_ID_ELEMS; id++) {
- for_each_mixer_elem(list, mixer, id) {
- if (list->resume) {
- err = list->resume(list);
- if (err < 0)
- return err;
- }
+ /* restore cached mixer values */
+ for (id = 0; id < MAX_ID_ELEMS; id++) {
+ for_each_mixer_elem(list, mixer, id) {
+ if (reset_resume)
+ f = list->reset_resume;
+ else
+ f = list->resume;
+ if (f) {
+ err = f(list);
+ if (err < 0)
+ return err;
}
}
}
@@ -3647,6 +3685,7 @@ void snd_usb_mixer_elem_init_std(struct usb_mixer_elem_list *list,
list->id = unitid;
list->dump = snd_usb_mixer_dump_cval;
#ifdef CONFIG_PM
- list->resume = restore_mixer_value;
+ list->resume = default_mixer_resume;
+ list->reset_resume = default_mixer_reset_resume;
#endif
}