diff options
Diffstat (limited to 'packages/linux/linux-omap/musb-dma-iso-in.eml')
-rw-r--r-- | packages/linux/linux-omap/musb-dma-iso-in.eml | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/packages/linux/linux-omap/musb-dma-iso-in.eml b/packages/linux/linux-omap/musb-dma-iso-in.eml new file mode 100644 index 0000000000..8f0a6c5689 --- /dev/null +++ b/packages/linux/linux-omap/musb-dma-iso-in.eml @@ -0,0 +1,138 @@ +Fixes blurred capture images in dma mode. Isochronous error field in
+urb and source data buffer pointer were not updated properly in dma
+mode.
+
+Signed-off-by: Ajay Kumar Gupta <ajay.gupta@ti.com>
+---
+diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
+index 08e421f..a481d54 100644
+--- a/drivers/usb/musb/musb_host.c
++++ b/drivers/usb/musb/musb_host.c
+@@ -1505,10 +1505,29 @@ void musb_host_rx(struct musb *musb, u8 epnum)
+ musb_writew(hw_ep->regs, MUSB_RXCSR, val);
+
+ #ifdef CONFIG_USB_INVENTRA_DMA
++ if (usb_pipeisoc(pipe)) {
++ struct usb_iso_packet_descriptor *d;
++
++ d = urb->iso_frame_desc + qh->iso_idx;
++ d->actual_length = xfer_len;
++
++ /* even if there was an error, we did the dma
++ * for iso_frame_desc->length
++ */
++ if (d->status != EILSEQ && d->status != -EOVERFLOW)
++ d->status = 0;
++
++ if (++qh->iso_idx >= urb->number_of_packets)
++ done = true;
++ else
++ done = false;
++
++ } else {
+ /* done if urb buffer is full or short packet is recd */
+ done = (urb->actual_length + xfer_len >=
+ urb->transfer_buffer_length
+ || dma->actual_len < qh->maxpacket);
++ }
+
+ /* send IN token for next packet, without AUTOREQ */
+ if (!done) {
+@@ -1545,7 +1564,8 @@ void musb_host_rx(struct musb *musb, u8 epnum)
+ if (dma) {
+ struct dma_controller *c;
+ u16 rx_count;
+- int ret;
++ int ret, length;
++ dma_addr_t buf;
+
+ rx_count = musb_readw(epio, MUSB_RXCOUNT);
+
+@@ -1558,6 +1578,35 @@ void musb_host_rx(struct musb *musb, u8 epnum)
+
+ c = musb->dma_controller;
+
++ if (usb_pipeisoc(pipe)) {
++ int status = 0;
++ struct usb_iso_packet_descriptor *d;
++
++ d = urb->iso_frame_desc + qh->iso_idx;
++
++ if (iso_err) {
++ status = -EILSEQ;
++ urb->error_count++;
++ }
++ if (rx_count > d->length) {
++ if (status == 0) {
++ status = -EOVERFLOW;
++ urb->error_count++;
++ }
++ DBG(2, "** OVERFLOW %d into %d\n",\
++ rx_count, d->length);
++
++ length = d->length;
++ } else
++ length = rx_count;
++ d->status = status;
++ buf = urb->transfer_dma + d->offset;
++ } else {
++ length = rx_count;
++ buf = urb->transfer_dma +
++ urb->actual_length;
++ }
++
+ dma->desired_mode = 0;
+ #ifdef USE_MODE1
+ /* because of the issue below, mode 1 will
+@@ -1569,6 +1618,12 @@ void musb_host_rx(struct musb *musb, u8 epnum)
+ urb->actual_length)
+ > qh->maxpacket)
+ dma->desired_mode = 1;
++ if (rx_count < hw_ep->max_packet_sz_rx) {
++ length = rx_count;
++ dma->bDesiredMode = 0;
++ } else {
++ length = urb->transfer_buffer_length;
++ }
+ #endif
+
+ /* Disadvantage of using mode 1:
+@@ -1606,12 +1661,7 @@ void musb_host_rx(struct musb *musb, u8 epnum)
+ */
+ ret = c->channel_program(
+ dma, qh->maxpacket,
+- dma->desired_mode,
+- urb->transfer_dma
+- + urb->actual_length,
+- (dma->desired_mode == 0)
+- ? rx_count
+- : urb->transfer_buffer_length);
++ dma->desired_mode, buf, length);
+
+ if (!ret) {
+ c->channel_release(dma);
+@@ -1628,19 +1678,6 @@ void musb_host_rx(struct musb *musb, u8 epnum)
+ }
+ }
+
+- if (dma && usb_pipeisoc(pipe)) {
+- struct usb_iso_packet_descriptor *d;
+- int iso_stat = status;
+-
+- d = urb->iso_frame_desc + qh->iso_idx;
+- d->actual_length += xfer_len;
+- if (iso_err) {
+- iso_stat = -EILSEQ;
+- urb->error_count++;
+- }
+- d->status = iso_stat;
+- }
+-
+ finish:
+ urb->actual_length += xfer_len;
+ qh->offset += xfer_len;
+--
+To unsubscribe from this list: send the line "unsubscribe linux-omap" in
+the body of a message to majordomo@vger.kernel.org
+More majordomo info at http://vger.kernel.org/majordomo-info.html
+
|