summaryrefslogtreecommitdiff
path: root/sound/usb
diff options
context:
space:
mode:
Diffstat (limited to 'sound/usb')
-rw-r--r--sound/usb/endpoint.c19
1 files changed, 17 insertions, 2 deletions
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index e6f71894ecdc..a77d9c812dc6 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -610,8 +610,23 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep,
/* assume max. frequency is 25% higher than nominal */
ep->freqmax = ep->freqn + (ep->freqn >> 2);
- maxsize = ((ep->freqmax + 0xffff) * (frame_bits >> 3))
- >> (16 - ep->datainterval);
+ /* Round up freqmax to nearest integer in order to calculate maximum
+ * packet size, which must represent a whole number of frames.
+ * This is accomplished by adding 0x0.ffff before converting the
+ * Q16.16 format into integer.
+ * In order to accurately calculate the maximum packet size when
+ * the data interval is more than 1 (i.e. ep->datainterval > 0),
+ * multiply by the data interval prior to rounding. For instance,
+ * a freqmax of 41 kHz will result in a max packet size of 6 (5.125)
+ * frames with a data interval of 1, but 11 (10.25) frames with a
+ * data interval of 2.
+ * (ep->freqmax << ep->datainterval overflows at 8.192 MHz for the
+ * maximum datainterval value of 3, at USB full speed, higher for
+ * USB high speed, noting that ep->freqmax is in units of
+ * frames per packet in Q16.16 format.)
+ */
+ maxsize = (((ep->freqmax << ep->datainterval) + 0xffff) >> 16) *
+ (frame_bits >> 3);
/* but wMaxPacketSize might reduce this */
if (ep->maxpacksize && ep->maxpacksize < maxsize) {
/* whatever fits into a max. size packet */