18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * STK1160 driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2012 Ezequiel Garcia 68c2ecf20Sopenharmony_ci * <elezegarcia--a.t--gmail.com> 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * Based on Easycap driver by R.M. Thomas 98c2ecf20Sopenharmony_ci * Copyright (C) 2010 R.M. Thomas 108c2ecf20Sopenharmony_ci * <rmthomas--a.t--sciolus.org> 118c2ecf20Sopenharmony_ci */ 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include <linux/module.h> 148c2ecf20Sopenharmony_ci#include <linux/usb.h> 158c2ecf20Sopenharmony_ci#include <linux/slab.h> 168c2ecf20Sopenharmony_ci#include <linux/ratelimit.h> 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#include "stk1160.h" 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_cistatic unsigned int debug; 218c2ecf20Sopenharmony_cimodule_param(debug, int, 0644); 228c2ecf20Sopenharmony_ciMODULE_PARM_DESC(debug, "enable debug messages"); 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_cistatic inline void print_err_status(struct stk1160 *dev, 258c2ecf20Sopenharmony_ci int packet, int status) 268c2ecf20Sopenharmony_ci{ 278c2ecf20Sopenharmony_ci char *errmsg = "Unknown"; 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci switch (status) { 308c2ecf20Sopenharmony_ci case -ENOENT: 318c2ecf20Sopenharmony_ci errmsg = "unlinked synchronously"; 328c2ecf20Sopenharmony_ci break; 338c2ecf20Sopenharmony_ci case -ECONNRESET: 348c2ecf20Sopenharmony_ci errmsg = "unlinked asynchronously"; 358c2ecf20Sopenharmony_ci break; 368c2ecf20Sopenharmony_ci case -ENOSR: 378c2ecf20Sopenharmony_ci errmsg = "Buffer error (overrun)"; 388c2ecf20Sopenharmony_ci break; 398c2ecf20Sopenharmony_ci case -EPIPE: 408c2ecf20Sopenharmony_ci errmsg = "Stalled (device not responding)"; 418c2ecf20Sopenharmony_ci break; 428c2ecf20Sopenharmony_ci case -EOVERFLOW: 438c2ecf20Sopenharmony_ci errmsg = "Babble (bad cable?)"; 448c2ecf20Sopenharmony_ci break; 458c2ecf20Sopenharmony_ci case -EPROTO: 468c2ecf20Sopenharmony_ci errmsg = "Bit-stuff error (bad cable?)"; 478c2ecf20Sopenharmony_ci break; 488c2ecf20Sopenharmony_ci case -EILSEQ: 498c2ecf20Sopenharmony_ci errmsg = "CRC/Timeout (could be anything)"; 508c2ecf20Sopenharmony_ci break; 518c2ecf20Sopenharmony_ci case -ETIME: 528c2ecf20Sopenharmony_ci errmsg = "Device does not respond"; 538c2ecf20Sopenharmony_ci break; 548c2ecf20Sopenharmony_ci } 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci if (packet < 0) 578c2ecf20Sopenharmony_ci printk_ratelimited(KERN_WARNING "URB status %d [%s].\n", 588c2ecf20Sopenharmony_ci status, errmsg); 598c2ecf20Sopenharmony_ci else 608c2ecf20Sopenharmony_ci printk_ratelimited(KERN_INFO "URB packet %d, status %d [%s].\n", 618c2ecf20Sopenharmony_ci packet, status, errmsg); 628c2ecf20Sopenharmony_ci} 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_cistatic inline 658c2ecf20Sopenharmony_cistruct stk1160_buffer *stk1160_next_buffer(struct stk1160 *dev) 668c2ecf20Sopenharmony_ci{ 678c2ecf20Sopenharmony_ci struct stk1160_buffer *buf = NULL; 688c2ecf20Sopenharmony_ci unsigned long flags = 0; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci /* Current buffer must be NULL when this functions gets called */ 718c2ecf20Sopenharmony_ci WARN_ON(dev->isoc_ctl.buf); 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci spin_lock_irqsave(&dev->buf_lock, flags); 748c2ecf20Sopenharmony_ci if (!list_empty(&dev->avail_bufs)) { 758c2ecf20Sopenharmony_ci buf = list_first_entry(&dev->avail_bufs, 768c2ecf20Sopenharmony_ci struct stk1160_buffer, list); 778c2ecf20Sopenharmony_ci list_del(&buf->list); 788c2ecf20Sopenharmony_ci } 798c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&dev->buf_lock, flags); 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci return buf; 828c2ecf20Sopenharmony_ci} 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_cistatic inline 858c2ecf20Sopenharmony_civoid stk1160_buffer_done(struct stk1160 *dev) 868c2ecf20Sopenharmony_ci{ 878c2ecf20Sopenharmony_ci struct stk1160_buffer *buf = dev->isoc_ctl.buf; 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci buf->vb.sequence = dev->sequence++; 908c2ecf20Sopenharmony_ci buf->vb.field = V4L2_FIELD_INTERLACED; 918c2ecf20Sopenharmony_ci buf->vb.vb2_buf.timestamp = ktime_get_ns(); 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci vb2_set_plane_payload(&buf->vb.vb2_buf, 0, buf->bytesused); 948c2ecf20Sopenharmony_ci vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE); 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci dev->isoc_ctl.buf = NULL; 978c2ecf20Sopenharmony_ci} 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_cistatic inline 1008c2ecf20Sopenharmony_civoid stk1160_copy_video(struct stk1160 *dev, u8 *src, int len) 1018c2ecf20Sopenharmony_ci{ 1028c2ecf20Sopenharmony_ci int linesdone, lineoff, lencopy; 1038c2ecf20Sopenharmony_ci int bytesperline = dev->width * 2; 1048c2ecf20Sopenharmony_ci struct stk1160_buffer *buf = dev->isoc_ctl.buf; 1058c2ecf20Sopenharmony_ci u8 *dst = buf->mem; 1068c2ecf20Sopenharmony_ci int remain; 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci /* 1098c2ecf20Sopenharmony_ci * TODO: These stk1160_dbg are very spammy! 1108c2ecf20Sopenharmony_ci * We should check why we are getting them. 1118c2ecf20Sopenharmony_ci * 1128c2ecf20Sopenharmony_ci * UPDATE: One of the reasons (the only one?) for getting these 1138c2ecf20Sopenharmony_ci * is incorrect standard (mismatch between expected and configured). 1148c2ecf20Sopenharmony_ci * So perhaps, we could add a counter for errors. When the counter 1158c2ecf20Sopenharmony_ci * reaches some value, we simply stop streaming. 1168c2ecf20Sopenharmony_ci */ 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci len -= 4; 1198c2ecf20Sopenharmony_ci src += 4; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci remain = len; 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci linesdone = buf->pos / bytesperline; 1248c2ecf20Sopenharmony_ci lineoff = buf->pos % bytesperline; /* offset in current line */ 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci if (!buf->odd) 1278c2ecf20Sopenharmony_ci dst += bytesperline; 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci /* Multiply linesdone by two, to take account of the other field */ 1308c2ecf20Sopenharmony_ci dst += linesdone * bytesperline * 2 + lineoff; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci /* Copy the remaining of current line */ 1338c2ecf20Sopenharmony_ci if (remain < (bytesperline - lineoff)) 1348c2ecf20Sopenharmony_ci lencopy = remain; 1358c2ecf20Sopenharmony_ci else 1368c2ecf20Sopenharmony_ci lencopy = bytesperline - lineoff; 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci /* 1398c2ecf20Sopenharmony_ci * Check if we have enough space left in the buffer. 1408c2ecf20Sopenharmony_ci * In that case, we force loop exit after copy. 1418c2ecf20Sopenharmony_ci */ 1428c2ecf20Sopenharmony_ci if (lencopy > buf->bytesused - buf->length) { 1438c2ecf20Sopenharmony_ci lencopy = buf->bytesused - buf->length; 1448c2ecf20Sopenharmony_ci remain = lencopy; 1458c2ecf20Sopenharmony_ci } 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci /* Check if the copy is done */ 1488c2ecf20Sopenharmony_ci if (lencopy == 0 || remain == 0) 1498c2ecf20Sopenharmony_ci return; 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci /* Let the bug hunt begin! sanity checks! */ 1528c2ecf20Sopenharmony_ci if (lencopy < 0) { 1538c2ecf20Sopenharmony_ci printk_ratelimited(KERN_DEBUG "copy skipped: negative lencopy\n"); 1548c2ecf20Sopenharmony_ci return; 1558c2ecf20Sopenharmony_ci } 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci if ((unsigned long)dst + lencopy > 1588c2ecf20Sopenharmony_ci (unsigned long)buf->mem + buf->length) { 1598c2ecf20Sopenharmony_ci printk_ratelimited(KERN_WARNING "stk1160: buffer overflow detected\n"); 1608c2ecf20Sopenharmony_ci return; 1618c2ecf20Sopenharmony_ci } 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci memcpy(dst, src, lencopy); 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci buf->bytesused += lencopy; 1668c2ecf20Sopenharmony_ci buf->pos += lencopy; 1678c2ecf20Sopenharmony_ci remain -= lencopy; 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci /* Copy current field line by line, interlacing with the other field */ 1708c2ecf20Sopenharmony_ci while (remain > 0) { 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci dst += lencopy + bytesperline; 1738c2ecf20Sopenharmony_ci src += lencopy; 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci /* Copy one line at a time */ 1768c2ecf20Sopenharmony_ci if (remain < bytesperline) 1778c2ecf20Sopenharmony_ci lencopy = remain; 1788c2ecf20Sopenharmony_ci else 1798c2ecf20Sopenharmony_ci lencopy = bytesperline; 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci /* 1828c2ecf20Sopenharmony_ci * Check if we have enough space left in the buffer. 1838c2ecf20Sopenharmony_ci * In that case, we force loop exit after copy. 1848c2ecf20Sopenharmony_ci */ 1858c2ecf20Sopenharmony_ci if (lencopy > buf->bytesused - buf->length) { 1868c2ecf20Sopenharmony_ci lencopy = buf->bytesused - buf->length; 1878c2ecf20Sopenharmony_ci remain = lencopy; 1888c2ecf20Sopenharmony_ci } 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci /* Check if the copy is done */ 1918c2ecf20Sopenharmony_ci if (lencopy == 0 || remain == 0) 1928c2ecf20Sopenharmony_ci return; 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci if (lencopy < 0) { 1958c2ecf20Sopenharmony_ci printk_ratelimited(KERN_WARNING "stk1160: negative lencopy detected\n"); 1968c2ecf20Sopenharmony_ci return; 1978c2ecf20Sopenharmony_ci } 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci if ((unsigned long)dst + lencopy > 2008c2ecf20Sopenharmony_ci (unsigned long)buf->mem + buf->length) { 2018c2ecf20Sopenharmony_ci printk_ratelimited(KERN_WARNING "stk1160: buffer overflow detected\n"); 2028c2ecf20Sopenharmony_ci return; 2038c2ecf20Sopenharmony_ci } 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci memcpy(dst, src, lencopy); 2068c2ecf20Sopenharmony_ci remain -= lencopy; 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci buf->bytesused += lencopy; 2098c2ecf20Sopenharmony_ci buf->pos += lencopy; 2108c2ecf20Sopenharmony_ci } 2118c2ecf20Sopenharmony_ci} 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci/* 2148c2ecf20Sopenharmony_ci * Controls the isoc copy of each urb packet 2158c2ecf20Sopenharmony_ci */ 2168c2ecf20Sopenharmony_cistatic void stk1160_process_isoc(struct stk1160 *dev, struct urb *urb) 2178c2ecf20Sopenharmony_ci{ 2188c2ecf20Sopenharmony_ci int i, len, status; 2198c2ecf20Sopenharmony_ci u8 *p; 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci if (!dev) { 2228c2ecf20Sopenharmony_ci stk1160_warn("%s called with null device\n", __func__); 2238c2ecf20Sopenharmony_ci return; 2248c2ecf20Sopenharmony_ci } 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci if (urb->status < 0) { 2278c2ecf20Sopenharmony_ci /* Print status and drop current packet (or field?) */ 2288c2ecf20Sopenharmony_ci print_err_status(dev, -1, urb->status); 2298c2ecf20Sopenharmony_ci return; 2308c2ecf20Sopenharmony_ci } 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci for (i = 0; i < urb->number_of_packets; i++) { 2338c2ecf20Sopenharmony_ci status = urb->iso_frame_desc[i].status; 2348c2ecf20Sopenharmony_ci if (status < 0) { 2358c2ecf20Sopenharmony_ci print_err_status(dev, i, status); 2368c2ecf20Sopenharmony_ci continue; 2378c2ecf20Sopenharmony_ci } 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci /* Get packet actual length and pointer to data */ 2408c2ecf20Sopenharmony_ci p = urb->transfer_buffer + urb->iso_frame_desc[i].offset; 2418c2ecf20Sopenharmony_ci len = urb->iso_frame_desc[i].actual_length; 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci /* Empty packet */ 2448c2ecf20Sopenharmony_ci if (len <= 4) 2458c2ecf20Sopenharmony_ci continue; 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci /* 2488c2ecf20Sopenharmony_ci * An 8-byte packet sequence means end of field. 2498c2ecf20Sopenharmony_ci * So if we don't have any packet, we start receiving one now 2508c2ecf20Sopenharmony_ci * and if we do have a packet, then we are done with it. 2518c2ecf20Sopenharmony_ci * 2528c2ecf20Sopenharmony_ci * These end of field packets are always 0xc0 or 0x80, 2538c2ecf20Sopenharmony_ci * but not always 8-byte long so we don't check packet length. 2548c2ecf20Sopenharmony_ci */ 2558c2ecf20Sopenharmony_ci if (p[0] == 0xc0) { 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci /* 2588c2ecf20Sopenharmony_ci * If first byte is 0xc0 then we received 2598c2ecf20Sopenharmony_ci * second field, and frame has ended. 2608c2ecf20Sopenharmony_ci */ 2618c2ecf20Sopenharmony_ci if (dev->isoc_ctl.buf != NULL) 2628c2ecf20Sopenharmony_ci stk1160_buffer_done(dev); 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci dev->isoc_ctl.buf = stk1160_next_buffer(dev); 2658c2ecf20Sopenharmony_ci if (dev->isoc_ctl.buf == NULL) 2668c2ecf20Sopenharmony_ci return; 2678c2ecf20Sopenharmony_ci } 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci /* 2708c2ecf20Sopenharmony_ci * If we don't have a buffer here, then it means we 2718c2ecf20Sopenharmony_ci * haven't found the start mark sequence. 2728c2ecf20Sopenharmony_ci */ 2738c2ecf20Sopenharmony_ci if (dev->isoc_ctl.buf == NULL) 2748c2ecf20Sopenharmony_ci continue; 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci if (p[0] == 0xc0 || p[0] == 0x80) { 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci /* We set next packet parity and 2798c2ecf20Sopenharmony_ci * continue to get next one 2808c2ecf20Sopenharmony_ci */ 2818c2ecf20Sopenharmony_ci dev->isoc_ctl.buf->odd = *p & 0x40; 2828c2ecf20Sopenharmony_ci dev->isoc_ctl.buf->pos = 0; 2838c2ecf20Sopenharmony_ci continue; 2848c2ecf20Sopenharmony_ci } 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci stk1160_copy_video(dev, p, len); 2878c2ecf20Sopenharmony_ci } 2888c2ecf20Sopenharmony_ci} 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci/* 2928c2ecf20Sopenharmony_ci * IRQ callback, called by URB callback 2938c2ecf20Sopenharmony_ci */ 2948c2ecf20Sopenharmony_cistatic void stk1160_isoc_irq(struct urb *urb) 2958c2ecf20Sopenharmony_ci{ 2968c2ecf20Sopenharmony_ci int i, rc; 2978c2ecf20Sopenharmony_ci struct stk1160 *dev = urb->context; 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci switch (urb->status) { 3008c2ecf20Sopenharmony_ci case 0: 3018c2ecf20Sopenharmony_ci break; 3028c2ecf20Sopenharmony_ci case -ECONNRESET: /* kill */ 3038c2ecf20Sopenharmony_ci case -ENOENT: 3048c2ecf20Sopenharmony_ci case -ESHUTDOWN: 3058c2ecf20Sopenharmony_ci /* TODO: check uvc driver: he frees the queue here */ 3068c2ecf20Sopenharmony_ci return; 3078c2ecf20Sopenharmony_ci default: 3088c2ecf20Sopenharmony_ci stk1160_err("urb error! status %d\n", urb->status); 3098c2ecf20Sopenharmony_ci return; 3108c2ecf20Sopenharmony_ci } 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci stk1160_process_isoc(dev, urb); 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci /* Reset urb buffers */ 3158c2ecf20Sopenharmony_ci for (i = 0; i < urb->number_of_packets; i++) { 3168c2ecf20Sopenharmony_ci urb->iso_frame_desc[i].status = 0; 3178c2ecf20Sopenharmony_ci urb->iso_frame_desc[i].actual_length = 0; 3188c2ecf20Sopenharmony_ci } 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_ci rc = usb_submit_urb(urb, GFP_ATOMIC); 3218c2ecf20Sopenharmony_ci if (rc) 3228c2ecf20Sopenharmony_ci stk1160_err("urb re-submit failed (%d)\n", rc); 3238c2ecf20Sopenharmony_ci} 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci/* 3268c2ecf20Sopenharmony_ci * Cancel urbs 3278c2ecf20Sopenharmony_ci * This function can't be called in atomic context 3288c2ecf20Sopenharmony_ci */ 3298c2ecf20Sopenharmony_civoid stk1160_cancel_isoc(struct stk1160 *dev) 3308c2ecf20Sopenharmony_ci{ 3318c2ecf20Sopenharmony_ci int i, num_bufs = dev->isoc_ctl.num_bufs; 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci /* 3348c2ecf20Sopenharmony_ci * This check is not necessary, but we add it 3358c2ecf20Sopenharmony_ci * to avoid a spurious debug message 3368c2ecf20Sopenharmony_ci */ 3378c2ecf20Sopenharmony_ci if (!num_bufs) 3388c2ecf20Sopenharmony_ci return; 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci stk1160_dbg("killing %d urbs...\n", num_bufs); 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci for (i = 0; i < num_bufs; i++) { 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci /* 3458c2ecf20Sopenharmony_ci * To kill urbs we can't be in atomic context. 3468c2ecf20Sopenharmony_ci * We don't care for NULL pointer since 3478c2ecf20Sopenharmony_ci * usb_kill_urb allows it. 3488c2ecf20Sopenharmony_ci */ 3498c2ecf20Sopenharmony_ci usb_kill_urb(dev->isoc_ctl.urb[i]); 3508c2ecf20Sopenharmony_ci } 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci stk1160_dbg("all urbs killed\n"); 3538c2ecf20Sopenharmony_ci} 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ci/* 3568c2ecf20Sopenharmony_ci * Releases urb and transfer buffers 3578c2ecf20Sopenharmony_ci * Obviusly, associated urb must be killed before releasing it. 3588c2ecf20Sopenharmony_ci */ 3598c2ecf20Sopenharmony_civoid stk1160_free_isoc(struct stk1160 *dev) 3608c2ecf20Sopenharmony_ci{ 3618c2ecf20Sopenharmony_ci struct urb *urb; 3628c2ecf20Sopenharmony_ci int i, num_bufs = dev->isoc_ctl.num_bufs; 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci stk1160_dbg("freeing %d urb buffers...\n", num_bufs); 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci for (i = 0; i < num_bufs; i++) { 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci urb = dev->isoc_ctl.urb[i]; 3698c2ecf20Sopenharmony_ci if (urb) { 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_ci if (dev->isoc_ctl.transfer_buffer[i]) { 3728c2ecf20Sopenharmony_ci#ifndef CONFIG_DMA_NONCOHERENT 3738c2ecf20Sopenharmony_ci usb_free_coherent(dev->udev, 3748c2ecf20Sopenharmony_ci urb->transfer_buffer_length, 3758c2ecf20Sopenharmony_ci dev->isoc_ctl.transfer_buffer[i], 3768c2ecf20Sopenharmony_ci urb->transfer_dma); 3778c2ecf20Sopenharmony_ci#else 3788c2ecf20Sopenharmony_ci kfree(dev->isoc_ctl.transfer_buffer[i]); 3798c2ecf20Sopenharmony_ci#endif 3808c2ecf20Sopenharmony_ci } 3818c2ecf20Sopenharmony_ci usb_free_urb(urb); 3828c2ecf20Sopenharmony_ci dev->isoc_ctl.urb[i] = NULL; 3838c2ecf20Sopenharmony_ci } 3848c2ecf20Sopenharmony_ci dev->isoc_ctl.transfer_buffer[i] = NULL; 3858c2ecf20Sopenharmony_ci } 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci kfree(dev->isoc_ctl.urb); 3888c2ecf20Sopenharmony_ci kfree(dev->isoc_ctl.transfer_buffer); 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci dev->isoc_ctl.urb = NULL; 3918c2ecf20Sopenharmony_ci dev->isoc_ctl.transfer_buffer = NULL; 3928c2ecf20Sopenharmony_ci dev->isoc_ctl.num_bufs = 0; 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci stk1160_dbg("all urb buffers freed\n"); 3958c2ecf20Sopenharmony_ci} 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci/* 3988c2ecf20Sopenharmony_ci * Helper for cancelling and freeing urbs 3998c2ecf20Sopenharmony_ci * This function can't be called in atomic context 4008c2ecf20Sopenharmony_ci */ 4018c2ecf20Sopenharmony_civoid stk1160_uninit_isoc(struct stk1160 *dev) 4028c2ecf20Sopenharmony_ci{ 4038c2ecf20Sopenharmony_ci stk1160_cancel_isoc(dev); 4048c2ecf20Sopenharmony_ci stk1160_free_isoc(dev); 4058c2ecf20Sopenharmony_ci} 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci/* 4088c2ecf20Sopenharmony_ci * Allocate URBs 4098c2ecf20Sopenharmony_ci */ 4108c2ecf20Sopenharmony_ciint stk1160_alloc_isoc(struct stk1160 *dev) 4118c2ecf20Sopenharmony_ci{ 4128c2ecf20Sopenharmony_ci struct urb *urb; 4138c2ecf20Sopenharmony_ci int i, j, k, sb_size, max_packets, num_bufs; 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci /* 4168c2ecf20Sopenharmony_ci * It may be necessary to release isoc here, 4178c2ecf20Sopenharmony_ci * since isoc are only released on disconnection. 4188c2ecf20Sopenharmony_ci * (see new_pkt_size flag) 4198c2ecf20Sopenharmony_ci */ 4208c2ecf20Sopenharmony_ci if (dev->isoc_ctl.num_bufs) 4218c2ecf20Sopenharmony_ci stk1160_uninit_isoc(dev); 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_ci stk1160_dbg("allocating urbs...\n"); 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci num_bufs = STK1160_NUM_BUFS; 4268c2ecf20Sopenharmony_ci max_packets = STK1160_NUM_PACKETS; 4278c2ecf20Sopenharmony_ci sb_size = max_packets * dev->max_pkt_size; 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci dev->isoc_ctl.buf = NULL; 4308c2ecf20Sopenharmony_ci dev->isoc_ctl.max_pkt_size = dev->max_pkt_size; 4318c2ecf20Sopenharmony_ci dev->isoc_ctl.urb = kcalloc(num_bufs, sizeof(void *), GFP_KERNEL); 4328c2ecf20Sopenharmony_ci if (!dev->isoc_ctl.urb) { 4338c2ecf20Sopenharmony_ci stk1160_err("out of memory for urb array\n"); 4348c2ecf20Sopenharmony_ci return -ENOMEM; 4358c2ecf20Sopenharmony_ci } 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci dev->isoc_ctl.transfer_buffer = kcalloc(num_bufs, sizeof(void *), 4388c2ecf20Sopenharmony_ci GFP_KERNEL); 4398c2ecf20Sopenharmony_ci if (!dev->isoc_ctl.transfer_buffer) { 4408c2ecf20Sopenharmony_ci stk1160_err("out of memory for usb transfers\n"); 4418c2ecf20Sopenharmony_ci kfree(dev->isoc_ctl.urb); 4428c2ecf20Sopenharmony_ci return -ENOMEM; 4438c2ecf20Sopenharmony_ci } 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_ci /* allocate urbs and transfer buffers */ 4468c2ecf20Sopenharmony_ci for (i = 0; i < num_bufs; i++) { 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_ci urb = usb_alloc_urb(max_packets, GFP_KERNEL); 4498c2ecf20Sopenharmony_ci if (!urb) 4508c2ecf20Sopenharmony_ci goto free_i_bufs; 4518c2ecf20Sopenharmony_ci dev->isoc_ctl.urb[i] = urb; 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ci#ifndef CONFIG_DMA_NONCOHERENT 4548c2ecf20Sopenharmony_ci dev->isoc_ctl.transfer_buffer[i] = usb_alloc_coherent(dev->udev, 4558c2ecf20Sopenharmony_ci sb_size, GFP_KERNEL, &urb->transfer_dma); 4568c2ecf20Sopenharmony_ci#else 4578c2ecf20Sopenharmony_ci dev->isoc_ctl.transfer_buffer[i] = kmalloc(sb_size, GFP_KERNEL); 4588c2ecf20Sopenharmony_ci#endif 4598c2ecf20Sopenharmony_ci if (!dev->isoc_ctl.transfer_buffer[i]) { 4608c2ecf20Sopenharmony_ci stk1160_err("cannot alloc %d bytes for tx[%d] buffer\n", 4618c2ecf20Sopenharmony_ci sb_size, i); 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_ci /* Not enough transfer buffers, so just give up */ 4648c2ecf20Sopenharmony_ci if (i < STK1160_MIN_BUFS) 4658c2ecf20Sopenharmony_ci goto free_i_bufs; 4668c2ecf20Sopenharmony_ci goto nomore_tx_bufs; 4678c2ecf20Sopenharmony_ci } 4688c2ecf20Sopenharmony_ci memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size); 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_ci /* 4718c2ecf20Sopenharmony_ci * FIXME: Where can I get the endpoint? 4728c2ecf20Sopenharmony_ci */ 4738c2ecf20Sopenharmony_ci urb->dev = dev->udev; 4748c2ecf20Sopenharmony_ci urb->pipe = usb_rcvisocpipe(dev->udev, STK1160_EP_VIDEO); 4758c2ecf20Sopenharmony_ci urb->transfer_buffer = dev->isoc_ctl.transfer_buffer[i]; 4768c2ecf20Sopenharmony_ci urb->transfer_buffer_length = sb_size; 4778c2ecf20Sopenharmony_ci urb->complete = stk1160_isoc_irq; 4788c2ecf20Sopenharmony_ci urb->context = dev; 4798c2ecf20Sopenharmony_ci urb->interval = 1; 4808c2ecf20Sopenharmony_ci urb->start_frame = 0; 4818c2ecf20Sopenharmony_ci urb->number_of_packets = max_packets; 4828c2ecf20Sopenharmony_ci#ifndef CONFIG_DMA_NONCOHERENT 4838c2ecf20Sopenharmony_ci urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; 4848c2ecf20Sopenharmony_ci#else 4858c2ecf20Sopenharmony_ci urb->transfer_flags = URB_ISO_ASAP; 4868c2ecf20Sopenharmony_ci#endif 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_ci k = 0; 4898c2ecf20Sopenharmony_ci for (j = 0; j < max_packets; j++) { 4908c2ecf20Sopenharmony_ci urb->iso_frame_desc[j].offset = k; 4918c2ecf20Sopenharmony_ci urb->iso_frame_desc[j].length = 4928c2ecf20Sopenharmony_ci dev->isoc_ctl.max_pkt_size; 4938c2ecf20Sopenharmony_ci k += dev->isoc_ctl.max_pkt_size; 4948c2ecf20Sopenharmony_ci } 4958c2ecf20Sopenharmony_ci } 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_ci stk1160_dbg("%d urbs allocated\n", num_bufs); 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_ci /* At last we can say we have some buffers */ 5008c2ecf20Sopenharmony_ci dev->isoc_ctl.num_bufs = num_bufs; 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_ci return 0; 5038c2ecf20Sopenharmony_ci 5048c2ecf20Sopenharmony_cinomore_tx_bufs: 5058c2ecf20Sopenharmony_ci /* 5068c2ecf20Sopenharmony_ci * Failed to allocate desired buffer count. However, we may have 5078c2ecf20Sopenharmony_ci * enough to work fine, so we just free the extra urb, 5088c2ecf20Sopenharmony_ci * store the allocated count and keep going, fingers crossed! 5098c2ecf20Sopenharmony_ci */ 5108c2ecf20Sopenharmony_ci usb_free_urb(dev->isoc_ctl.urb[i]); 5118c2ecf20Sopenharmony_ci dev->isoc_ctl.urb[i] = NULL; 5128c2ecf20Sopenharmony_ci 5138c2ecf20Sopenharmony_ci stk1160_warn("%d urbs allocated. Trying to continue...\n", i - 1); 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_ci dev->isoc_ctl.num_bufs = i - 1; 5168c2ecf20Sopenharmony_ci 5178c2ecf20Sopenharmony_ci return 0; 5188c2ecf20Sopenharmony_ci 5198c2ecf20Sopenharmony_cifree_i_bufs: 5208c2ecf20Sopenharmony_ci /* Save the allocated buffers so far, so we can properly free them */ 5218c2ecf20Sopenharmony_ci dev->isoc_ctl.num_bufs = i+1; 5228c2ecf20Sopenharmony_ci stk1160_free_isoc(dev); 5238c2ecf20Sopenharmony_ci return -ENOMEM; 5248c2ecf20Sopenharmony_ci} 5258c2ecf20Sopenharmony_ci 526