Update Linux to v5.4.148
Sourced from [1]
[1] https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.4.148.tar.gz
Change-Id: Ib3d26c5ba9b022e2e03533005c4fed4d7c30b61b
Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index 6cd4ff0..67eb129 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -576,8 +576,9 @@
* if failed, give up and free the control instance.
*/
-int snd_usb_mixer_add_control(struct usb_mixer_elem_list *list,
- struct snd_kcontrol *kctl)
+int snd_usb_mixer_add_list(struct usb_mixer_elem_list *list,
+ struct snd_kcontrol *kctl,
+ bool is_std_info)
{
struct usb_mixer_interface *mixer = list->mixer;
int err;
@@ -591,6 +592,7 @@
return err;
}
list->kctl = kctl;
+ list->is_std_info = is_std_info;
list->next_id_elem = mixer->id_elems[list->id];
mixer->id_elems[list->id] = list;
return 0;
@@ -897,6 +899,15 @@
return 0;
}
+static int parse_term_effect_unit(struct mixer_build *state,
+ struct usb_audio_term *term,
+ void *p1, int id)
+{
+ term->type = UAC3_EFFECT_UNIT << 16; /* virtual type */
+ term->id = id;
+ return 0;
+}
+
static int parse_term_uac2_clock_source(struct mixer_build *state,
struct usb_audio_term *term,
void *p1, int id)
@@ -981,8 +992,7 @@
UAC3_PROCESSING_UNIT);
case PTYPE(UAC_VERSION_2, UAC2_EFFECT_UNIT):
case PTYPE(UAC_VERSION_3, UAC3_EFFECT_UNIT):
- return parse_term_proc_unit(state, term, p1, id,
- UAC3_EFFECT_UNIT);
+ return parse_term_effect_unit(state, term, p1, id);
case PTYPE(UAC_VERSION_1, UAC1_EXTENSION_UNIT):
case PTYPE(UAC_VERSION_2, UAC2_EXTENSION_UNIT_V2):
case PTYPE(UAC_VERSION_3, UAC3_EXTENSION_UNIT):
@@ -1020,7 +1030,7 @@
int type_uac2; /* data type for uac2 if different from uac1, else -1 */
};
-static struct usb_feature_control_info audio_feature_info[] = {
+static const struct usb_feature_control_info audio_feature_info[] = {
{ UAC_FU_MUTE, "Mute", USB_MIXER_INV_BOOLEAN, -1 },
{ UAC_FU_VOLUME, "Volume", USB_MIXER_S16, -1 },
{ UAC_FU_BASS, "Tone Control - Bass", USB_MIXER_S8, -1 },
@@ -1163,6 +1173,14 @@
cval->res = 384;
}
break;
+ case USB_ID(0x0495, 0x3042): /* ESS Technology Asus USB DAC */
+ if ((strstr(kctl->id.name, "Playback Volume") != NULL) ||
+ strstr(kctl->id.name, "Capture Volume") != NULL) {
+ cval->min >>= 8;
+ cval->max = 0;
+ cval->res = 1;
+ }
+ break;
}
}
@@ -1438,7 +1456,7 @@
usb_audio_err(chip,
"cannot get connectors status: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n",
UAC_GET_CUR, validx, idx, cval->val_type);
- return ret;
+ return filter_error(cval, ret);
}
ucontrol->value.integer.value[0] = val;
@@ -1526,7 +1544,7 @@
strlcpy(kctl->id.name, "Headphone", sizeof(kctl->id.name));
}
-static struct usb_feature_control_info *get_feature_control_info(int control)
+static const struct usb_feature_control_info *get_feature_control_info(int control)
{
int i;
@@ -1544,7 +1562,7 @@
struct usb_audio_term *oterm,
int unitid, int nameid, int readonly_mask)
{
- struct usb_feature_control_info *ctl_info;
+ const struct usb_feature_control_info *ctl_info;
unsigned int len = 0;
int mapped_name = 0;
struct snd_kcontrol *kctl;
@@ -1666,6 +1684,16 @@
/* get min/max values */
get_min_max_with_quirks(cval, 0, kctl);
+ /* skip a bogus volume range */
+ if (cval->max <= cval->min) {
+ usb_audio_dbg(mixer->chip,
+ "[%d] FU [%s] skipped due to invalid volume\n",
+ cval->head.id, kctl->id.name);
+ snd_ctl_free_one(kctl);
+ return;
+ }
+
+
if (control == UAC_FU_VOLUME) {
check_mapped_dB(map, cval);
if (cval->dBmin < cval->dBmax || !cval->initialized) {
@@ -1742,10 +1770,16 @@
/* Build a mixer control for a UAC connector control (jack-detect) */
static void build_connector_control(struct usb_mixer_interface *mixer,
+ const struct usbmix_name_map *imap,
struct usb_audio_term *term, bool is_input)
{
struct snd_kcontrol *kctl;
struct usb_mixer_elem_info *cval;
+ const struct usbmix_name_map *map;
+
+ map = find_map(imap, term->id, 0);
+ if (check_ignored_ctl(map))
+ return;
cval = kzalloc(sizeof(*cval), GFP_KERNEL);
if (!cval)
@@ -1776,8 +1810,12 @@
usb_mixer_elem_info_free(cval);
return;
}
- get_connector_control_name(mixer, term, is_input, kctl->id.name,
- sizeof(kctl->id.name));
+
+ if (check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name)))
+ strlcat(kctl->id.name, " Jack", sizeof(kctl->id.name));
+ else
+ get_connector_control_name(mixer, term, is_input, kctl->id.name,
+ sizeof(kctl->id.name));
kctl->private_free = snd_usb_mixer_elem_free;
snd_usb_mixer_add_control(&cval->head, kctl);
}
@@ -2080,8 +2118,9 @@
check_input_term(state, term_id, &iterm);
/* Check for jack detection. */
- if (uac_v2v3_control_is_readable(bmctls, control))
- build_connector_control(state->mixer, &iterm, true);
+ if ((iterm.type & 0xff00) != 0x0100 &&
+ uac_v2v3_control_is_readable(bmctls, control))
+ build_connector_control(state->mixer, state->map, &iterm, true);
return 0;
}
@@ -2198,7 +2237,7 @@
*/
struct procunit_value_info {
int control;
- char *suffix;
+ const char *suffix;
int val_type;
int min_value;
};
@@ -2206,44 +2245,44 @@
struct procunit_info {
int type;
char *name;
- struct procunit_value_info *values;
+ const struct procunit_value_info *values;
};
-static struct procunit_value_info undefined_proc_info[] = {
+static const struct procunit_value_info undefined_proc_info[] = {
{ 0x00, "Control Undefined", 0 },
{ 0 }
};
-static struct procunit_value_info updown_proc_info[] = {
+static const struct procunit_value_info updown_proc_info[] = {
{ UAC_UD_ENABLE, "Switch", USB_MIXER_BOOLEAN },
{ UAC_UD_MODE_SELECT, "Mode Select", USB_MIXER_U8, 1 },
{ 0 }
};
-static struct procunit_value_info prologic_proc_info[] = {
+static const struct procunit_value_info prologic_proc_info[] = {
{ UAC_DP_ENABLE, "Switch", USB_MIXER_BOOLEAN },
{ UAC_DP_MODE_SELECT, "Mode Select", USB_MIXER_U8, 1 },
{ 0 }
};
-static struct procunit_value_info threed_enh_proc_info[] = {
+static const struct procunit_value_info threed_enh_proc_info[] = {
{ UAC_3D_ENABLE, "Switch", USB_MIXER_BOOLEAN },
{ UAC_3D_SPACE, "Spaciousness", USB_MIXER_U8 },
{ 0 }
};
-static struct procunit_value_info reverb_proc_info[] = {
+static const struct procunit_value_info reverb_proc_info[] = {
{ UAC_REVERB_ENABLE, "Switch", USB_MIXER_BOOLEAN },
{ UAC_REVERB_LEVEL, "Level", USB_MIXER_U8 },
{ UAC_REVERB_TIME, "Time", USB_MIXER_U16 },
{ UAC_REVERB_FEEDBACK, "Feedback", USB_MIXER_U8 },
{ 0 }
};
-static struct procunit_value_info chorus_proc_info[] = {
+static const struct procunit_value_info chorus_proc_info[] = {
{ UAC_CHORUS_ENABLE, "Switch", USB_MIXER_BOOLEAN },
{ UAC_CHORUS_LEVEL, "Level", USB_MIXER_U8 },
{ UAC_CHORUS_RATE, "Rate", USB_MIXER_U16 },
{ UAC_CHORUS_DEPTH, "Depth", USB_MIXER_U16 },
{ 0 }
};
-static struct procunit_value_info dcr_proc_info[] = {
+static const struct procunit_value_info dcr_proc_info[] = {
{ UAC_DCR_ENABLE, "Switch", USB_MIXER_BOOLEAN },
{ UAC_DCR_RATE, "Ratio", USB_MIXER_U16 },
{ UAC_DCR_MAXAMPL, "Max Amp", USB_MIXER_S16 },
@@ -2253,7 +2292,7 @@
{ 0 }
};
-static struct procunit_info procunits[] = {
+static const struct procunit_info procunits[] = {
{ UAC_PROCESS_UP_DOWNMIX, "Up Down", updown_proc_info },
{ UAC_PROCESS_DOLBY_PROLOGIC, "Dolby Prologic", prologic_proc_info },
{ UAC_PROCESS_STEREO_EXTENDER, "3D Stereo Extender", threed_enh_proc_info },
@@ -2263,16 +2302,16 @@
{ 0 },
};
-static struct procunit_value_info uac3_updown_proc_info[] = {
+static const struct procunit_value_info uac3_updown_proc_info[] = {
{ UAC3_UD_MODE_SELECT, "Mode Select", USB_MIXER_U8, 1 },
{ 0 }
};
-static struct procunit_value_info uac3_stereo_ext_proc_info[] = {
+static const struct procunit_value_info uac3_stereo_ext_proc_info[] = {
{ UAC3_EXT_WIDTH_CONTROL, "Width Control", USB_MIXER_U8 },
{ 0 }
};
-static struct procunit_info uac3_procunits[] = {
+static const struct procunit_info uac3_procunits[] = {
{ UAC3_PROCESS_UP_DOWNMIX, "Up Down", uac3_updown_proc_info },
{ UAC3_PROCESS_STEREO_EXTENDER, "3D Stereo Extender", uac3_stereo_ext_proc_info },
{ UAC3_PROCESS_MULTI_FUNCTION, "Multi-Function", undefined_proc_info },
@@ -2282,23 +2321,23 @@
/*
* predefined data for extension units
*/
-static struct procunit_value_info clock_rate_xu_info[] = {
+static const struct procunit_value_info clock_rate_xu_info[] = {
{ USB_XU_CLOCK_RATE_SELECTOR, "Selector", USB_MIXER_U8, 0 },
{ 0 }
};
-static struct procunit_value_info clock_source_xu_info[] = {
+static const struct procunit_value_info clock_source_xu_info[] = {
{ USB_XU_CLOCK_SOURCE_SELECTOR, "External", USB_MIXER_BOOLEAN },
{ 0 }
};
-static struct procunit_value_info spdif_format_xu_info[] = {
+static const struct procunit_value_info spdif_format_xu_info[] = {
{ USB_XU_DIGITAL_FORMAT_SELECTOR, "SPDIF/AC3", USB_MIXER_BOOLEAN },
{ 0 }
};
-static struct procunit_value_info soft_limit_xu_info[] = {
+static const struct procunit_value_info soft_limit_xu_info[] = {
{ USB_XU_SOFT_LIMIT_SELECTOR, " ", USB_MIXER_BOOLEAN },
{ 0 }
};
-static struct procunit_info extunits[] = {
+static const struct procunit_info extunits[] = {
{ USB_XU_CLOCK_RATE, "Clock rate", clock_rate_xu_info },
{ USB_XU_CLOCK_SOURCE, "DigitalIn CLK source", clock_source_xu_info },
{ USB_XU_DIGITAL_IO_STATUS, "DigitalOut format:", spdif_format_xu_info },
@@ -2310,7 +2349,7 @@
* build a processing/extension unit
*/
static int build_audio_procunit(struct mixer_build *state, int unitid,
- void *raw_desc, struct procunit_info *list,
+ void *raw_desc, const struct procunit_info *list,
bool extension_unit)
{
struct uac_processing_unit_descriptor *desc = raw_desc;
@@ -2318,14 +2357,14 @@
struct usb_mixer_elem_info *cval;
struct snd_kcontrol *kctl;
int i, err, nameid, type, len;
- struct procunit_info *info;
- struct procunit_value_info *valinfo;
+ const struct procunit_info *info;
+ const struct procunit_value_info *valinfo;
const struct usbmix_name_map *map;
- static struct procunit_value_info default_value_info[] = {
+ static const struct procunit_value_info default_value_info[] = {
{ 0x01, "Switch", USB_MIXER_BOOLEAN },
{ 0 }
};
- static struct procunit_info default_info = {
+ static const struct procunit_info default_info = {
0, NULL, default_value_info
};
const char *name = extension_unit ?
@@ -2803,7 +2842,7 @@
int st_chmask; /* side tone mixing channel mask */
};
-static struct uac3_badd_profile uac3_badd_profiles[] = {
+static const struct uac3_badd_profile uac3_badd_profiles[] = {
{
/*
* BAIF, BAOF or combination of both
@@ -2864,7 +2903,7 @@
};
static bool uac3_badd_func_has_valid_channels(struct usb_mixer_interface *mixer,
- struct uac3_badd_profile *f,
+ const struct uac3_badd_profile *f,
int c_chmask, int p_chmask)
{
/*
@@ -2908,7 +2947,7 @@
struct usb_device *dev = mixer->chip->dev;
struct usb_interface_assoc_descriptor *assoc;
int badd_profile = mixer->chip->badd_profile;
- struct uac3_badd_profile *f;
+ const struct uac3_badd_profile *f;
const struct usbmix_ctl_map *map;
int p_chmask = 0, c_chmask = 0, st_chmask = 0;
int i;
@@ -3042,13 +3081,13 @@
memset(&iterm, 0, sizeof(iterm));
iterm.id = UAC3_BADD_IT_ID4;
iterm.type = UAC_BIDIR_TERMINAL_HEADSET;
- build_connector_control(mixer, &iterm, true);
+ build_connector_control(mixer, map->map, &iterm, true);
/* Output Term - Insertion control */
memset(&oterm, 0, sizeof(oterm));
oterm.id = UAC3_BADD_OT_ID3;
oterm.type = UAC_BIDIR_TERMINAL_HEADSET;
- build_connector_control(mixer, &oterm, false);
+ build_connector_control(mixer, map->map, &oterm, false);
}
return 0;
@@ -3077,7 +3116,8 @@
if (map->id == state.chip->usb_id) {
state.map = map->map;
state.selector_map = map->selector_map;
- mixer->ignore_ctl_error = map->ignore_ctl_error;
+ mixer->connector_map = map->connector_map;
+ mixer->ignore_ctl_error |= map->ignore_ctl_error;
break;
}
}
@@ -3120,10 +3160,11 @@
if (err < 0 && err != -EINVAL)
return err;
- if (uac_v2v3_control_is_readable(le16_to_cpu(desc->bmControls),
+ if ((state.oterm.type & 0xff00) != 0x0100 &&
+ uac_v2v3_control_is_readable(le16_to_cpu(desc->bmControls),
UAC2_TE_CONNECTOR)) {
- build_connector_control(state.mixer, &state.oterm,
- false);
+ build_connector_control(state.mixer, state.map,
+ &state.oterm, false);
}
} else { /* UAC_VERSION_3 */
struct uac3_output_terminal_descriptor *desc = p;
@@ -3145,10 +3186,11 @@
if (err < 0 && err != -EINVAL)
return err;
- if (uac_v2v3_control_is_readable(le32_to_cpu(desc->bmControls),
+ if ((state.oterm.type & 0xff00) != 0x0100 &&
+ uac_v2v3_control_is_readable(le32_to_cpu(desc->bmControls),
UAC3_TE_INSERTION)) {
- build_connector_control(state.mixer, &state.oterm,
- false);
+ build_connector_control(state.mixer, state.map,
+ &state.oterm, false);
}
}
}
@@ -3156,13 +3198,38 @@
return 0;
}
+static int delegate_notify(struct usb_mixer_interface *mixer, int unitid,
+ u8 *control, u8 *channel)
+{
+ const struct usbmix_connector_map *map = mixer->connector_map;
+
+ if (!map)
+ return unitid;
+
+ for (; map->id; map++) {
+ if (map->id == unitid) {
+ if (control && map->control)
+ *control = map->control;
+ if (channel && map->channel)
+ *channel = map->channel;
+ return map->delegated_id;
+ }
+ }
+ return unitid;
+}
+
void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid)
{
struct usb_mixer_elem_list *list;
+ unitid = delegate_notify(mixer, unitid, NULL, NULL);
+
for_each_mixer_elem(list, mixer, unitid) {
- struct usb_mixer_elem_info *info =
- mixer_elem_list_to_info(list);
+ struct usb_mixer_elem_info *info;
+
+ if (!list->is_std_info)
+ continue;
+ info = mixer_elem_list_to_info(list);
/* invalidate cache, so the value is read from the device */
info->cached = 0;
snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
@@ -3174,8 +3241,17 @@
struct usb_mixer_elem_list *list)
{
struct usb_mixer_elem_info *cval = mixer_elem_list_to_info(list);
- static char *val_types[] = {"BOOLEAN", "INV_BOOLEAN",
- "S8", "U8", "S16", "U16"};
+ static const char * const val_types[] = {
+ [USB_MIXER_BOOLEAN] = "BOOLEAN",
+ [USB_MIXER_INV_BOOLEAN] = "INV_BOOLEAN",
+ [USB_MIXER_S8] = "S8",
+ [USB_MIXER_U8] = "U8",
+ [USB_MIXER_S16] = "S16",
+ [USB_MIXER_U16] = "U16",
+ [USB_MIXER_S32] = "S32",
+ [USB_MIXER_U32] = "U32",
+ [USB_MIXER_BESPOKEN] = "BESPOKEN",
+ };
snd_iprintf(buffer, " Info: id=%i, control=%i, cmask=0x%x, "
"channels=%i, type=\"%s\"\n", cval->head.id,
cval->control, cval->cmask, cval->channels,
@@ -3229,6 +3305,8 @@
return;
}
+ unitid = delegate_notify(mixer, unitid, &control, &channel);
+
for_each_mixer_elem(list, mixer, unitid)
count++;
@@ -3240,6 +3318,8 @@
if (!list->kctl)
continue;
+ if (!list->is_std_info)
+ continue;
info = mixer_elem_list_to_info(list);
if (count > 1 && info->control != control)
@@ -3527,6 +3607,9 @@
struct usb_mixer_elem_info *cval = mixer_elem_list_to_info(list);
int c, err, idx;
+ if (cval->val_type == USB_MIXER_BESPOKEN)
+ return 0;
+
if (cval->cmask) {
idx = 0;
for (c = 0; c < MAX_CHANNELS; c++) {