mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-18 22:14:16 +00:00
usb: gadget: f_uac2: Add HS/SS bInterval to configfs
Allow configuring the HS/SS bInterval through configfs, via parameters p_hs_bint/c_hs_bint separately for playback/capture. The default param values are left at the original 4. Suggested-by: John Keeping <john@metanate.com> Signed-off-by: Pavel Hofman <pavel.hofman@ivitera.com> Link: https://lore.kernel.org/r/20220127114331.41367-2-pavel.hofman@ivitera.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
e1f09f409f
commit
4ed941a999
4 changed files with 35 additions and 4 deletions
|
@ -8,6 +8,7 @@ Description:
|
||||||
c_chmask capture channel mask
|
c_chmask capture channel mask
|
||||||
c_srate list of capture sampling rates (comma-separated)
|
c_srate list of capture sampling rates (comma-separated)
|
||||||
c_ssize capture sample size (bytes)
|
c_ssize capture sample size (bytes)
|
||||||
|
c_hs_bint capture bInterval for HS/SS (1-4)
|
||||||
c_sync capture synchronization type
|
c_sync capture synchronization type
|
||||||
(async/adaptive)
|
(async/adaptive)
|
||||||
c_mute_present capture mute control enable
|
c_mute_present capture mute control enable
|
||||||
|
@ -22,6 +23,7 @@ Description:
|
||||||
p_chmask playback channel mask
|
p_chmask playback channel mask
|
||||||
p_srate list of playback sampling rates (comma-separated)
|
p_srate list of playback sampling rates (comma-separated)
|
||||||
p_ssize playback sample size (bytes)
|
p_ssize playback sample size (bytes)
|
||||||
|
p_hs_bint playback bInterval for HS/SS (1-4)
|
||||||
p_mute_present playback mute control enable
|
p_mute_present playback mute control enable
|
||||||
p_volume_present playback volume control enable
|
p_volume_present playback volume control enable
|
||||||
p_volume_min playback volume control min value
|
p_volume_min playback volume control min value
|
||||||
|
|
|
@ -734,6 +734,7 @@ The uac2 function provides these attributes in its function directory:
|
||||||
c_volume_min capture volume control min value (in 1/256 dB)
|
c_volume_min capture volume control min value (in 1/256 dB)
|
||||||
c_volume_max capture volume control max value (in 1/256 dB)
|
c_volume_max capture volume control max value (in 1/256 dB)
|
||||||
c_volume_res capture volume control resolution (in 1/256 dB)
|
c_volume_res capture volume control resolution (in 1/256 dB)
|
||||||
|
c_hs_bint capture bInterval for HS/SS (1-4)
|
||||||
fb_max maximum extra bandwidth in async mode
|
fb_max maximum extra bandwidth in async mode
|
||||||
p_chmask playback channel mask
|
p_chmask playback channel mask
|
||||||
p_srate list of playback sampling rates (comma-separated)
|
p_srate list of playback sampling rates (comma-separated)
|
||||||
|
@ -743,6 +744,7 @@ The uac2 function provides these attributes in its function directory:
|
||||||
p_volume_min playback volume control min value (in 1/256 dB)
|
p_volume_min playback volume control min value (in 1/256 dB)
|
||||||
p_volume_max playback volume control max value (in 1/256 dB)
|
p_volume_max playback volume control max value (in 1/256 dB)
|
||||||
p_volume_res playback volume control resolution (in 1/256 dB)
|
p_volume_res playback volume control resolution (in 1/256 dB)
|
||||||
|
p_hs_bint playback bInterval for HS/SS (1-4)
|
||||||
req_number the number of pre-allocated request for both capture
|
req_number the number of pre-allocated request for both capture
|
||||||
and playback
|
and playback
|
||||||
function_name name of the interface
|
function_name name of the interface
|
||||||
|
|
|
@ -343,7 +343,7 @@ static struct usb_endpoint_descriptor hs_epout_desc = {
|
||||||
|
|
||||||
/* .bmAttributes = DYNAMIC */
|
/* .bmAttributes = DYNAMIC */
|
||||||
/* .wMaxPacketSize = DYNAMIC */
|
/* .wMaxPacketSize = DYNAMIC */
|
||||||
.bInterval = 4,
|
/* .bInterval = DYNAMIC */
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct usb_endpoint_descriptor ss_epout_desc = {
|
static struct usb_endpoint_descriptor ss_epout_desc = {
|
||||||
|
@ -353,7 +353,7 @@ static struct usb_endpoint_descriptor ss_epout_desc = {
|
||||||
.bEndpointAddress = USB_DIR_OUT,
|
.bEndpointAddress = USB_DIR_OUT,
|
||||||
/* .bmAttributes = DYNAMIC */
|
/* .bmAttributes = DYNAMIC */
|
||||||
/* .wMaxPacketSize = DYNAMIC */
|
/* .wMaxPacketSize = DYNAMIC */
|
||||||
.bInterval = 4,
|
/* .bInterval = DYNAMIC */
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct usb_ss_ep_comp_descriptor ss_epout_desc_comp = {
|
static struct usb_ss_ep_comp_descriptor ss_epout_desc_comp = {
|
||||||
|
@ -477,7 +477,7 @@ static struct usb_endpoint_descriptor hs_epin_desc = {
|
||||||
|
|
||||||
.bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC,
|
.bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC,
|
||||||
/* .wMaxPacketSize = DYNAMIC */
|
/* .wMaxPacketSize = DYNAMIC */
|
||||||
.bInterval = 4,
|
/* .bInterval = DYNAMIC */
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct usb_endpoint_descriptor ss_epin_desc = {
|
static struct usb_endpoint_descriptor ss_epin_desc = {
|
||||||
|
@ -487,7 +487,7 @@ static struct usb_endpoint_descriptor ss_epin_desc = {
|
||||||
.bEndpointAddress = USB_DIR_IN,
|
.bEndpointAddress = USB_DIR_IN,
|
||||||
.bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC,
|
.bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC,
|
||||||
/* .wMaxPacketSize = DYNAMIC */
|
/* .wMaxPacketSize = DYNAMIC */
|
||||||
.bInterval = 4,
|
/* .bInterval = DYNAMIC */
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct usb_ss_ep_comp_descriptor ss_epin_desc_comp = {
|
static struct usb_ss_ep_comp_descriptor ss_epin_desc_comp = {
|
||||||
|
@ -965,6 +965,16 @@ static int afunc_validate_opts(struct g_audio *agdev, struct device *dev)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((opts->p_hs_bint < 1) || (opts->p_hs_bint > 4)) {
|
||||||
|
dev_err(dev, "Error: incorrect playback HS/SS bInterval (1-4)\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((opts->c_hs_bint < 1) || (opts->c_hs_bint > 4)) {
|
||||||
|
dev_err(dev, "Error: incorrect capture HS/SS bInterval (1-4)\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1125,6 +1135,11 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
|
||||||
std_ac_if_desc.bNumEndpoints = 1;
|
std_ac_if_desc.bNumEndpoints = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hs_epin_desc.bInterval = uac2_opts->p_hs_bint;
|
||||||
|
ss_epin_desc.bInterval = uac2_opts->p_hs_bint;
|
||||||
|
hs_epout_desc.bInterval = uac2_opts->c_hs_bint;
|
||||||
|
ss_epout_desc.bInterval = uac2_opts->c_hs_bint;
|
||||||
|
|
||||||
/* Calculate wMaxPacketSize according to audio bandwidth */
|
/* Calculate wMaxPacketSize according to audio bandwidth */
|
||||||
ret = set_ep_max_packet_size(uac2_opts, &fs_epin_desc, USB_SPEED_FULL,
|
ret = set_ep_max_packet_size(uac2_opts, &fs_epin_desc, USB_SPEED_FULL,
|
||||||
true);
|
true);
|
||||||
|
@ -1801,10 +1816,12 @@ static struct configfs_item_operations f_uac2_item_ops = {
|
||||||
.release = f_uac2_attr_release,
|
.release = f_uac2_attr_release,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define uac2_kstrtou8 kstrtou8
|
||||||
#define uac2_kstrtou32 kstrtou32
|
#define uac2_kstrtou32 kstrtou32
|
||||||
#define uac2_kstrtos16 kstrtos16
|
#define uac2_kstrtos16 kstrtos16
|
||||||
#define uac2_kstrtobool(s, base, res) kstrtobool((s), (res))
|
#define uac2_kstrtobool(s, base, res) kstrtobool((s), (res))
|
||||||
|
|
||||||
|
static const char *u8_fmt = "%u\n";
|
||||||
static const char *u32_fmt = "%u\n";
|
static const char *u32_fmt = "%u\n";
|
||||||
static const char *s16_fmt = "%hd\n";
|
static const char *s16_fmt = "%hd\n";
|
||||||
static const char *bool_fmt = "%u\n";
|
static const char *bool_fmt = "%u\n";
|
||||||
|
@ -2004,10 +2021,12 @@ CONFIGFS_ATTR(f_uac2_opts_, name)
|
||||||
UAC2_ATTRIBUTE(u32, p_chmask);
|
UAC2_ATTRIBUTE(u32, p_chmask);
|
||||||
UAC2_RATE_ATTRIBUTE(p_srate);
|
UAC2_RATE_ATTRIBUTE(p_srate);
|
||||||
UAC2_ATTRIBUTE(u32, p_ssize);
|
UAC2_ATTRIBUTE(u32, p_ssize);
|
||||||
|
UAC2_ATTRIBUTE(u8, p_hs_bint);
|
||||||
UAC2_ATTRIBUTE(u32, c_chmask);
|
UAC2_ATTRIBUTE(u32, c_chmask);
|
||||||
UAC2_RATE_ATTRIBUTE(c_srate);
|
UAC2_RATE_ATTRIBUTE(c_srate);
|
||||||
UAC2_ATTRIBUTE_SYNC(c_sync);
|
UAC2_ATTRIBUTE_SYNC(c_sync);
|
||||||
UAC2_ATTRIBUTE(u32, c_ssize);
|
UAC2_ATTRIBUTE(u32, c_ssize);
|
||||||
|
UAC2_ATTRIBUTE(u8, c_hs_bint);
|
||||||
UAC2_ATTRIBUTE(u32, req_number);
|
UAC2_ATTRIBUTE(u32, req_number);
|
||||||
|
|
||||||
UAC2_ATTRIBUTE(bool, p_mute_present);
|
UAC2_ATTRIBUTE(bool, p_mute_present);
|
||||||
|
@ -2028,9 +2047,11 @@ static struct configfs_attribute *f_uac2_attrs[] = {
|
||||||
&f_uac2_opts_attr_p_chmask,
|
&f_uac2_opts_attr_p_chmask,
|
||||||
&f_uac2_opts_attr_p_srate,
|
&f_uac2_opts_attr_p_srate,
|
||||||
&f_uac2_opts_attr_p_ssize,
|
&f_uac2_opts_attr_p_ssize,
|
||||||
|
&f_uac2_opts_attr_p_hs_bint,
|
||||||
&f_uac2_opts_attr_c_chmask,
|
&f_uac2_opts_attr_c_chmask,
|
||||||
&f_uac2_opts_attr_c_srate,
|
&f_uac2_opts_attr_c_srate,
|
||||||
&f_uac2_opts_attr_c_ssize,
|
&f_uac2_opts_attr_c_ssize,
|
||||||
|
&f_uac2_opts_attr_c_hs_bint,
|
||||||
&f_uac2_opts_attr_c_sync,
|
&f_uac2_opts_attr_c_sync,
|
||||||
&f_uac2_opts_attr_req_number,
|
&f_uac2_opts_attr_req_number,
|
||||||
&f_uac2_opts_attr_fb_max,
|
&f_uac2_opts_attr_fb_max,
|
||||||
|
@ -2083,9 +2104,11 @@ static struct usb_function_instance *afunc_alloc_inst(void)
|
||||||
opts->p_chmask = UAC2_DEF_PCHMASK;
|
opts->p_chmask = UAC2_DEF_PCHMASK;
|
||||||
opts->p_srates[0] = UAC2_DEF_PSRATE;
|
opts->p_srates[0] = UAC2_DEF_PSRATE;
|
||||||
opts->p_ssize = UAC2_DEF_PSSIZE;
|
opts->p_ssize = UAC2_DEF_PSSIZE;
|
||||||
|
opts->p_hs_bint = UAC2_DEF_PHSBINT;
|
||||||
opts->c_chmask = UAC2_DEF_CCHMASK;
|
opts->c_chmask = UAC2_DEF_CCHMASK;
|
||||||
opts->c_srates[0] = UAC2_DEF_CSRATE;
|
opts->c_srates[0] = UAC2_DEF_CSRATE;
|
||||||
opts->c_ssize = UAC2_DEF_CSSIZE;
|
opts->c_ssize = UAC2_DEF_CSSIZE;
|
||||||
|
opts->c_hs_bint = UAC2_DEF_CHSBINT;
|
||||||
opts->c_sync = UAC2_DEF_CSYNC;
|
opts->c_sync = UAC2_DEF_CSYNC;
|
||||||
|
|
||||||
opts->p_mute_present = UAC2_DEF_MUTE_PRESENT;
|
opts->p_mute_present = UAC2_DEF_MUTE_PRESENT;
|
||||||
|
|
|
@ -19,9 +19,11 @@
|
||||||
#define UAC2_DEF_PCHMASK 0x3
|
#define UAC2_DEF_PCHMASK 0x3
|
||||||
#define UAC2_DEF_PSRATE 48000
|
#define UAC2_DEF_PSRATE 48000
|
||||||
#define UAC2_DEF_PSSIZE 2
|
#define UAC2_DEF_PSSIZE 2
|
||||||
|
#define UAC2_DEF_PHSBINT 4
|
||||||
#define UAC2_DEF_CCHMASK 0x3
|
#define UAC2_DEF_CCHMASK 0x3
|
||||||
#define UAC2_DEF_CSRATE 64000
|
#define UAC2_DEF_CSRATE 64000
|
||||||
#define UAC2_DEF_CSSIZE 2
|
#define UAC2_DEF_CSSIZE 2
|
||||||
|
#define UAC2_DEF_CHSBINT 4
|
||||||
#define UAC2_DEF_CSYNC USB_ENDPOINT_SYNC_ASYNC
|
#define UAC2_DEF_CSYNC USB_ENDPOINT_SYNC_ASYNC
|
||||||
|
|
||||||
#define UAC2_DEF_MUTE_PRESENT 1
|
#define UAC2_DEF_MUTE_PRESENT 1
|
||||||
|
@ -38,10 +40,12 @@ struct f_uac2_opts {
|
||||||
int p_chmask;
|
int p_chmask;
|
||||||
int p_srates[UAC_MAX_RATES];
|
int p_srates[UAC_MAX_RATES];
|
||||||
int p_ssize;
|
int p_ssize;
|
||||||
|
u8 p_hs_bint;
|
||||||
int c_chmask;
|
int c_chmask;
|
||||||
int c_srates[UAC_MAX_RATES];
|
int c_srates[UAC_MAX_RATES];
|
||||||
int c_ssize;
|
int c_ssize;
|
||||||
int c_sync;
|
int c_sync;
|
||||||
|
u8 c_hs_bint;
|
||||||
|
|
||||||
bool p_mute_present;
|
bool p_mute_present;
|
||||||
bool p_volume_present;
|
bool p_volume_present;
|
||||||
|
|
Loading…
Add table
Reference in a new issue