Skip to content

Commit 037690d

Browse files
committed
usb: gadget: f_uac1: finalize wMaxPacketSize according to bandwidth
According to USB Audio Device 1.0 Spec, Ch4.6.1.1: The wMaxPacketSize of endpoint is defined as follows: Maximum packet size of endpoint is capable of sending or receiving when this configuration is selected. This is determined by the audio bandwidth constraints of the endpoint. In current code, the wMaxPacketSize is limited to 200, and the bInterval is set to 4 (1ms). That is, the maximum bandwidth over USB bus is 200 * 1000 = 200000 bytes. We find an issue about bandwidth limitation when we try to support UAC1 with 8ch * 16bit * 16KHz on RK3308 platform, which needs more bandwidth than it can support. This patch sets the wMaxPacketSize dynamically according to the parameters of UAC1. It is similar to the same thing done earlier for f_uac2. Change-Id: I9af3fd7665a80b5eb0cfb5dc91ebe2c20df1dd46 Signed-off-by: William Wu <william.wu@rock-chips.com>
1 parent dc241f0 commit 037690d

File tree

1 file changed

+75
-2
lines changed

1 file changed

+75
-2
lines changed

drivers/usb/gadget/function/f_uac1.c

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ static struct usb_endpoint_descriptor as_out_ep_desc = {
250250
.bEndpointAddress = USB_DIR_OUT,
251251
.bmAttributes = USB_ENDPOINT_SYNC_ADAPTIVE
252252
| USB_ENDPOINT_XFER_ISOC,
253-
.wMaxPacketSize = cpu_to_le16(UAC1_OUT_EP_MAX_PACKET_SIZE),
253+
/* .wMaxPacketSize = DYNAMIC */
254254
.bInterval = 4,
255255
};
256256

@@ -281,7 +281,7 @@ static struct usb_endpoint_descriptor as_in_ep_desc = {
281281
.bEndpointAddress = USB_DIR_IN,
282282
.bmAttributes = USB_ENDPOINT_SYNC_ASYNC
283283
| USB_ENDPOINT_XFER_ISOC,
284-
.wMaxPacketSize = cpu_to_le16(UAC1_OUT_EP_MAX_PACKET_SIZE),
284+
/* .wMaxPacketSize = DYNAMIC */
285285
.bInterval = 4,
286286
};
287287

@@ -812,6 +812,57 @@ static void setup_descriptor(struct f_uac_opts *opts)
812812
f_audio_desc[i++] = NULL;
813813
}
814814

815+
static int set_ep_max_packet_size(const struct f_uac_opts *opts,
816+
struct usb_endpoint_descriptor *ep_desc,
817+
enum usb_device_speed speed, bool is_playback)
818+
{
819+
int chmask, srate = 0, ssize;
820+
u16 max_size_bw, max_size_ep;
821+
unsigned int factor;
822+
int i;
823+
824+
switch (speed) {
825+
case USB_SPEED_FULL:
826+
max_size_ep = 1023;
827+
factor = 1000;
828+
break;
829+
830+
case USB_SPEED_HIGH:
831+
max_size_ep = 1024;
832+
factor = 8000;
833+
break;
834+
835+
default:
836+
return -EINVAL;
837+
}
838+
839+
if (is_playback) {
840+
chmask = opts->p_chmask;
841+
for (i = 0; i < UAC_MAX_RATES; i++) {
842+
if (opts->p_srate[i] == 0)
843+
break;
844+
if (opts->p_srate[i] > srate)
845+
srate = opts->p_srate[i];
846+
}
847+
ssize = opts->p_ssize;
848+
} else {
849+
chmask = opts->c_chmask;
850+
for (i = 0; i < UAC_MAX_RATES; i++) {
851+
if (opts->c_srate[i] == 0)
852+
break;
853+
if (opts->c_srate[i] > srate)
854+
srate = opts->c_srate[i];
855+
}
856+
ssize = opts->c_ssize;
857+
}
858+
859+
max_size_bw = num_channels(chmask) * ssize *
860+
((srate / (factor / (1 << (ep_desc->bInterval - 1)))) + 1);
861+
ep_desc->wMaxPacketSize = cpu_to_le16(min_t(u16, max_size_bw,
862+
max_size_ep));
863+
864+
return 0;
865+
}
815866

816867
/* audio function driver setup/binding */
817868
static int f_audio_bind(struct usb_configuration *c, struct usb_function *f)
@@ -823,6 +874,7 @@ static int f_audio_bind(struct usb_configuration *c, struct usb_function *f)
823874
struct f_uac_opts *audio_opts;
824875
struct usb_ep *ep = NULL;
825876
struct usb_string *us;
877+
struct device *dev = &gadget->dev;
826878
int status;
827879
int idx, i;
828880

@@ -866,6 +918,27 @@ static int f_audio_bind(struct usb_configuration *c, struct usb_function *f)
866918
memcpy(as_out_type_i_desc.tSamFreq[idx++],
867919
&audio_opts->c_srate[i], 3);
868920
}
921+
922+
/*
923+
* Calculate wMaxPacketSize according to audio bandwidth.
924+
* Set the max packet with USB_SPEED_HIGH by default to
925+
* be compatible with larger bandwidth requirements for
926+
* high speed mode.
927+
*/
928+
status = set_ep_max_packet_size(audio_opts, &as_out_ep_desc,
929+
USB_SPEED_HIGH, false);
930+
if (status < 0) {
931+
dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
932+
goto fail;
933+
}
934+
935+
status = set_ep_max_packet_size(audio_opts, &as_in_ep_desc,
936+
USB_SPEED_HIGH, true);
937+
if (status < 0) {
938+
dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
939+
goto fail;
940+
}
941+
869942
as_out_type_i_desc.bLength = UAC_FORMAT_TYPE_I_DISCRETE_DESC_SIZE(idx);
870943
as_out_type_i_desc.bSamFreqType = idx;
871944

0 commit comments

Comments
 (0)