Commit 4ed941a9 authored by Pavel Hofman's avatar Pavel Hofman Committed by Greg Kroah-Hartman
Browse files

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: default avatarJohn Keeping <john@metanate.com>
Signed-off-by: default avatarPavel Hofman <pavel.hofman@ivitera.com>
Link: https://lore.kernel.org/r/20220127114331.41367-2-pavel.hofman@ivitera.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent e1f09f40
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -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
+2 −0
Original line number Original line Diff line number Diff line
@@ -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
+27 −4
Original line number Original line Diff line number Diff line
@@ -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;
+4 −0
Original line number Original line Diff line number Diff line
@@ -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;