diff options
Diffstat (limited to 'drivers/usb/gadget/function/f_uac2.c')
| -rw-r--r-- | drivers/usb/gadget/function/f_uac2.c | 33 | 
1 files changed, 28 insertions, 5 deletions
diff --git a/drivers/usb/gadget/function/f_uac2.c b/drivers/usb/gadget/function/f_uac2.c index 3c34995276e7..ef55b8bb5870 100644 --- a/drivers/usb/gadget/function/f_uac2.c +++ b/drivers/usb/gadget/function/f_uac2.c @@ -406,6 +406,14 @@ static struct usb_endpoint_descriptor ss_epin_fback_desc = {  	.bInterval = 4,  }; +static struct usb_ss_ep_comp_descriptor ss_epin_fback_desc_comp = { +	.bLength		= sizeof(ss_epin_fback_desc_comp), +	.bDescriptorType	= USB_DT_SS_ENDPOINT_COMP, +	.bMaxBurst		= 0, +	.bmAttributes		= 0, +	.wBytesPerInterval	= cpu_to_le16(4), +}; +  /* Audio Streaming IN Interface - Alt0 */  static struct usb_interface_descriptor std_as_in_if0_desc = { @@ -597,6 +605,7 @@ static struct usb_descriptor_header *ss_audio_desc[] = {  	(struct usb_descriptor_header *)&ss_epout_desc_comp,  	(struct usb_descriptor_header *)&as_iso_out_desc,  	(struct usb_descriptor_header *)&ss_epin_fback_desc, +	(struct usb_descriptor_header *)&ss_epin_fback_desc_comp,  	(struct usb_descriptor_header *)&std_as_in_if0_desc,  	(struct usb_descriptor_header *)&std_as_in_if1_desc, @@ -665,11 +674,17 @@ static int set_ep_max_packet_size(const struct f_uac2_opts *uac2_opts,  		ssize = uac2_opts->c_ssize;  	} -	if (!is_playback && (uac2_opts->c_sync == USB_ENDPOINT_SYNC_ASYNC)) +	if (!is_playback && (uac2_opts->c_sync == USB_ENDPOINT_SYNC_ASYNC)) { +	  // Win10 requires max packet size + 1 frame  		srate = srate * (1000 + uac2_opts->fb_max) / 1000; - -	max_size_bw = num_channels(chmask) * ssize * -		DIV_ROUND_UP(srate, factor / (1 << (ep_desc->bInterval - 1))); +		// updated srate is always bigger, therefore DIV_ROUND_UP always yields +1 +		max_size_bw = num_channels(chmask) * ssize * +			(DIV_ROUND_UP(srate, factor / (1 << (ep_desc->bInterval - 1)))); +	} else { +		// adding 1 frame provision for Win10 +		max_size_bw = num_channels(chmask) * ssize * +			(DIV_ROUND_UP(srate, factor / (1 << (ep_desc->bInterval - 1))) + 1); +	}  	ep_desc->wMaxPacketSize = cpu_to_le16(min_t(u16, max_size_bw,  						    max_size_ep)); @@ -705,6 +720,7 @@ static void setup_headers(struct f_uac2_opts *opts,  {  	struct usb_ss_ep_comp_descriptor *epout_desc_comp = NULL;  	struct usb_ss_ep_comp_descriptor *epin_desc_comp = NULL; +	struct usb_ss_ep_comp_descriptor *epin_fback_desc_comp = NULL;  	struct usb_endpoint_descriptor *epout_desc;  	struct usb_endpoint_descriptor *epin_desc;  	struct usb_endpoint_descriptor *epin_fback_desc; @@ -730,6 +746,7 @@ static void setup_headers(struct f_uac2_opts *opts,  		epout_desc_comp = &ss_epout_desc_comp;  		epin_desc_comp = &ss_epin_desc_comp;  		epin_fback_desc = &ss_epin_fback_desc; +		epin_fback_desc_comp = &ss_epin_fback_desc_comp;  		ep_int_desc = &ss_ep_int_desc;  	} @@ -773,8 +790,11 @@ static void setup_headers(struct f_uac2_opts *opts,  		headers[i++] = USBDHDR(&as_iso_out_desc); -		if (EPOUT_FBACK_IN_EN(opts)) +		if (EPOUT_FBACK_IN_EN(opts)) {  			headers[i++] = USBDHDR(epin_fback_desc); +			if (epin_fback_desc_comp) +				headers[i++] = USBDHDR(epin_fback_desc_comp); +		}  	}  	if (EPIN_EN(opts)) { @@ -1164,6 +1184,9 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)  	agdev->out_ep_maxpsize = max_t(u16, agdev->out_ep_maxpsize,  				le16_to_cpu(ss_epout_desc.wMaxPacketSize)); +	ss_epin_desc_comp.wBytesPerInterval = ss_epin_desc.wMaxPacketSize; +	ss_epout_desc_comp.wBytesPerInterval = ss_epout_desc.wMaxPacketSize; +  	// HS and SS endpoint addresses are copied from autoconfigured FS descriptors  	hs_ep_int_desc.bEndpointAddress = fs_ep_int_desc.bEndpointAddress;  	hs_epout_desc.bEndpointAddress = fs_epout_desc.bEndpointAddress;  | 
