162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * STK1160 driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2012 Ezequiel Garcia 662306a36Sopenharmony_ci * <elezegarcia--a.t--gmail.com> 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Based on Easycap driver by R.M. Thomas 962306a36Sopenharmony_ci * Copyright (C) 2010 R.M. Thomas 1062306a36Sopenharmony_ci * <rmthomas--a.t--sciolus.org> 1162306a36Sopenharmony_ci */ 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include <linux/module.h> 1462306a36Sopenharmony_ci#include <linux/usb.h> 1562306a36Sopenharmony_ci#include <linux/slab.h> 1662306a36Sopenharmony_ci#include <linux/ratelimit.h> 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#include "stk1160.h" 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_cistatic unsigned int debug; 2162306a36Sopenharmony_cimodule_param(debug, int, 0644); 2262306a36Sopenharmony_ciMODULE_PARM_DESC(debug, "enable debug messages"); 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_cistatic inline void print_err_status(struct stk1160 *dev, 2562306a36Sopenharmony_ci int packet, int status) 2662306a36Sopenharmony_ci{ 2762306a36Sopenharmony_ci char *errmsg = "Unknown"; 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci switch (status) { 3062306a36Sopenharmony_ci case -ENOENT: 3162306a36Sopenharmony_ci errmsg = "unlinked synchronously"; 3262306a36Sopenharmony_ci break; 3362306a36Sopenharmony_ci case -ECONNRESET: 3462306a36Sopenharmony_ci errmsg = "unlinked asynchronously"; 3562306a36Sopenharmony_ci break; 3662306a36Sopenharmony_ci case -ENOSR: 3762306a36Sopenharmony_ci errmsg = "Buffer error (overrun)"; 3862306a36Sopenharmony_ci break; 3962306a36Sopenharmony_ci case -EPIPE: 4062306a36Sopenharmony_ci errmsg = "Stalled (device not responding)"; 4162306a36Sopenharmony_ci break; 4262306a36Sopenharmony_ci case -EOVERFLOW: 4362306a36Sopenharmony_ci errmsg = "Babble (bad cable?)"; 4462306a36Sopenharmony_ci break; 4562306a36Sopenharmony_ci case -EPROTO: 4662306a36Sopenharmony_ci errmsg = "Bit-stuff error (bad cable?)"; 4762306a36Sopenharmony_ci break; 4862306a36Sopenharmony_ci case -EILSEQ: 4962306a36Sopenharmony_ci errmsg = "CRC/Timeout (could be anything)"; 5062306a36Sopenharmony_ci break; 5162306a36Sopenharmony_ci case -ETIME: 5262306a36Sopenharmony_ci errmsg = "Device does not respond"; 5362306a36Sopenharmony_ci break; 5462306a36Sopenharmony_ci } 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci if (packet < 0) 5762306a36Sopenharmony_ci printk_ratelimited(KERN_WARNING "URB status %d [%s].\n", 5862306a36Sopenharmony_ci status, errmsg); 5962306a36Sopenharmony_ci else 6062306a36Sopenharmony_ci printk_ratelimited(KERN_INFO "URB packet %d, status %d [%s].\n", 6162306a36Sopenharmony_ci packet, status, errmsg); 6262306a36Sopenharmony_ci} 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_cistatic inline 6562306a36Sopenharmony_cistruct stk1160_buffer *stk1160_next_buffer(struct stk1160 *dev) 6662306a36Sopenharmony_ci{ 6762306a36Sopenharmony_ci struct stk1160_buffer *buf = NULL; 6862306a36Sopenharmony_ci unsigned long flags = 0; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci /* Current buffer must be NULL when this functions gets called */ 7162306a36Sopenharmony_ci WARN_ON(dev->isoc_ctl.buf); 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci spin_lock_irqsave(&dev->buf_lock, flags); 7462306a36Sopenharmony_ci if (!list_empty(&dev->avail_bufs)) { 7562306a36Sopenharmony_ci buf = list_first_entry(&dev->avail_bufs, 7662306a36Sopenharmony_ci struct stk1160_buffer, list); 7762306a36Sopenharmony_ci list_del(&buf->list); 7862306a36Sopenharmony_ci } 7962306a36Sopenharmony_ci spin_unlock_irqrestore(&dev->buf_lock, flags); 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci return buf; 8262306a36Sopenharmony_ci} 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_cistatic inline 8562306a36Sopenharmony_civoid stk1160_buffer_done(struct stk1160 *dev) 8662306a36Sopenharmony_ci{ 8762306a36Sopenharmony_ci struct stk1160_buffer *buf = dev->isoc_ctl.buf; 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci buf->vb.sequence = dev->sequence++; 9062306a36Sopenharmony_ci buf->vb.field = V4L2_FIELD_INTERLACED; 9162306a36Sopenharmony_ci buf->vb.vb2_buf.timestamp = ktime_get_ns(); 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci vb2_set_plane_payload(&buf->vb.vb2_buf, 0, buf->bytesused); 9462306a36Sopenharmony_ci vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE); 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci dev->isoc_ctl.buf = NULL; 9762306a36Sopenharmony_ci} 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_cistatic inline 10062306a36Sopenharmony_civoid stk1160_copy_video(struct stk1160 *dev, u8 *src, int len) 10162306a36Sopenharmony_ci{ 10262306a36Sopenharmony_ci int linesdone, lineoff, lencopy; 10362306a36Sopenharmony_ci int bytesperline = dev->width * 2; 10462306a36Sopenharmony_ci struct stk1160_buffer *buf = dev->isoc_ctl.buf; 10562306a36Sopenharmony_ci u8 *dst = buf->mem; 10662306a36Sopenharmony_ci int remain; 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci /* 10962306a36Sopenharmony_ci * TODO: These stk1160_dbg are very spammy! 11062306a36Sopenharmony_ci * We should check why we are getting them. 11162306a36Sopenharmony_ci * 11262306a36Sopenharmony_ci * UPDATE: One of the reasons (the only one?) for getting these 11362306a36Sopenharmony_ci * is incorrect standard (mismatch between expected and configured). 11462306a36Sopenharmony_ci * So perhaps, we could add a counter for errors. When the counter 11562306a36Sopenharmony_ci * reaches some value, we simply stop streaming. 11662306a36Sopenharmony_ci */ 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci len -= 4; 11962306a36Sopenharmony_ci src += 4; 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci remain = len; 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci linesdone = buf->pos / bytesperline; 12462306a36Sopenharmony_ci lineoff = buf->pos % bytesperline; /* offset in current line */ 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci if (!buf->odd) 12762306a36Sopenharmony_ci dst += bytesperline; 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci /* Multiply linesdone by two, to take account of the other field */ 13062306a36Sopenharmony_ci dst += linesdone * bytesperline * 2 + lineoff; 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci /* Copy the remaining of current line */ 13362306a36Sopenharmony_ci if (remain < (bytesperline - lineoff)) 13462306a36Sopenharmony_ci lencopy = remain; 13562306a36Sopenharmony_ci else 13662306a36Sopenharmony_ci lencopy = bytesperline - lineoff; 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci /* 13962306a36Sopenharmony_ci * Check if we have enough space left in the buffer. 14062306a36Sopenharmony_ci * In that case, we force loop exit after copy. 14162306a36Sopenharmony_ci */ 14262306a36Sopenharmony_ci if (lencopy > buf->bytesused - buf->length) { 14362306a36Sopenharmony_ci lencopy = buf->bytesused - buf->length; 14462306a36Sopenharmony_ci remain = lencopy; 14562306a36Sopenharmony_ci } 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci /* Check if the copy is done */ 14862306a36Sopenharmony_ci if (lencopy == 0 || remain == 0) 14962306a36Sopenharmony_ci return; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci /* Let the bug hunt begin! sanity checks! */ 15262306a36Sopenharmony_ci if (lencopy < 0) { 15362306a36Sopenharmony_ci printk_ratelimited(KERN_DEBUG "copy skipped: negative lencopy\n"); 15462306a36Sopenharmony_ci return; 15562306a36Sopenharmony_ci } 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci if ((unsigned long)dst + lencopy > 15862306a36Sopenharmony_ci (unsigned long)buf->mem + buf->length) { 15962306a36Sopenharmony_ci printk_ratelimited(KERN_WARNING "stk1160: buffer overflow detected\n"); 16062306a36Sopenharmony_ci return; 16162306a36Sopenharmony_ci } 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci memcpy(dst, src, lencopy); 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci buf->bytesused += lencopy; 16662306a36Sopenharmony_ci buf->pos += lencopy; 16762306a36Sopenharmony_ci remain -= lencopy; 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci /* Copy current field line by line, interlacing with the other field */ 17062306a36Sopenharmony_ci while (remain > 0) { 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci dst += lencopy + bytesperline; 17362306a36Sopenharmony_ci src += lencopy; 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci /* Copy one line at a time */ 17662306a36Sopenharmony_ci if (remain < bytesperline) 17762306a36Sopenharmony_ci lencopy = remain; 17862306a36Sopenharmony_ci else 17962306a36Sopenharmony_ci lencopy = bytesperline; 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci /* 18262306a36Sopenharmony_ci * Check if we have enough space left in the buffer. 18362306a36Sopenharmony_ci * In that case, we force loop exit after copy. 18462306a36Sopenharmony_ci */ 18562306a36Sopenharmony_ci if (lencopy > buf->bytesused - buf->length) { 18662306a36Sopenharmony_ci lencopy = buf->bytesused - buf->length; 18762306a36Sopenharmony_ci remain = lencopy; 18862306a36Sopenharmony_ci } 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci /* Check if the copy is done */ 19162306a36Sopenharmony_ci if (lencopy == 0 || remain == 0) 19262306a36Sopenharmony_ci return; 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci if (lencopy < 0) { 19562306a36Sopenharmony_ci printk_ratelimited(KERN_WARNING "stk1160: negative lencopy detected\n"); 19662306a36Sopenharmony_ci return; 19762306a36Sopenharmony_ci } 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci if ((unsigned long)dst + lencopy > 20062306a36Sopenharmony_ci (unsigned long)buf->mem + buf->length) { 20162306a36Sopenharmony_ci printk_ratelimited(KERN_WARNING "stk1160: buffer overflow detected\n"); 20262306a36Sopenharmony_ci return; 20362306a36Sopenharmony_ci } 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci memcpy(dst, src, lencopy); 20662306a36Sopenharmony_ci remain -= lencopy; 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci buf->bytesused += lencopy; 20962306a36Sopenharmony_ci buf->pos += lencopy; 21062306a36Sopenharmony_ci } 21162306a36Sopenharmony_ci} 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci/* 21462306a36Sopenharmony_ci * Controls the isoc copy of each urb packet 21562306a36Sopenharmony_ci */ 21662306a36Sopenharmony_cistatic void stk1160_process_isoc(struct stk1160 *dev, struct urb *urb) 21762306a36Sopenharmony_ci{ 21862306a36Sopenharmony_ci int i, len, status; 21962306a36Sopenharmony_ci u8 *p; 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci if (!dev) { 22262306a36Sopenharmony_ci stk1160_warn("%s called with null device\n", __func__); 22362306a36Sopenharmony_ci return; 22462306a36Sopenharmony_ci } 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci if (urb->status < 0) { 22762306a36Sopenharmony_ci /* Print status and drop current packet (or field?) */ 22862306a36Sopenharmony_ci print_err_status(dev, -1, urb->status); 22962306a36Sopenharmony_ci return; 23062306a36Sopenharmony_ci } 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci for (i = 0; i < urb->number_of_packets; i++) { 23362306a36Sopenharmony_ci status = urb->iso_frame_desc[i].status; 23462306a36Sopenharmony_ci if (status < 0) { 23562306a36Sopenharmony_ci print_err_status(dev, i, status); 23662306a36Sopenharmony_ci continue; 23762306a36Sopenharmony_ci } 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci /* Get packet actual length and pointer to data */ 24062306a36Sopenharmony_ci p = urb->transfer_buffer + urb->iso_frame_desc[i].offset; 24162306a36Sopenharmony_ci len = urb->iso_frame_desc[i].actual_length; 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci /* Empty packet */ 24462306a36Sopenharmony_ci if (len <= 4) 24562306a36Sopenharmony_ci continue; 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci /* 24862306a36Sopenharmony_ci * An 8-byte packet sequence means end of field. 24962306a36Sopenharmony_ci * So if we don't have any packet, we start receiving one now 25062306a36Sopenharmony_ci * and if we do have a packet, then we are done with it. 25162306a36Sopenharmony_ci * 25262306a36Sopenharmony_ci * These end of field packets are always 0xc0 or 0x80, 25362306a36Sopenharmony_ci * but not always 8-byte long so we don't check packet length. 25462306a36Sopenharmony_ci */ 25562306a36Sopenharmony_ci if (p[0] == 0xc0) { 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci /* 25862306a36Sopenharmony_ci * If first byte is 0xc0 then we received 25962306a36Sopenharmony_ci * second field, and frame has ended. 26062306a36Sopenharmony_ci */ 26162306a36Sopenharmony_ci if (dev->isoc_ctl.buf != NULL) 26262306a36Sopenharmony_ci stk1160_buffer_done(dev); 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci dev->isoc_ctl.buf = stk1160_next_buffer(dev); 26562306a36Sopenharmony_ci if (dev->isoc_ctl.buf == NULL) 26662306a36Sopenharmony_ci return; 26762306a36Sopenharmony_ci } 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci /* 27062306a36Sopenharmony_ci * If we don't have a buffer here, then it means we 27162306a36Sopenharmony_ci * haven't found the start mark sequence. 27262306a36Sopenharmony_ci */ 27362306a36Sopenharmony_ci if (dev->isoc_ctl.buf == NULL) 27462306a36Sopenharmony_ci continue; 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci if (p[0] == 0xc0 || p[0] == 0x80) { 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci /* We set next packet parity and 27962306a36Sopenharmony_ci * continue to get next one 28062306a36Sopenharmony_ci */ 28162306a36Sopenharmony_ci dev->isoc_ctl.buf->odd = *p & 0x40; 28262306a36Sopenharmony_ci dev->isoc_ctl.buf->pos = 0; 28362306a36Sopenharmony_ci continue; 28462306a36Sopenharmony_ci } 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci stk1160_copy_video(dev, p, len); 28762306a36Sopenharmony_ci } 28862306a36Sopenharmony_ci} 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci/* 29262306a36Sopenharmony_ci * IRQ callback, called by URB callback 29362306a36Sopenharmony_ci */ 29462306a36Sopenharmony_cistatic void stk1160_isoc_irq(struct urb *urb) 29562306a36Sopenharmony_ci{ 29662306a36Sopenharmony_ci int i, rc; 29762306a36Sopenharmony_ci struct stk1160_urb *stk_urb = urb->context; 29862306a36Sopenharmony_ci struct stk1160 *dev = stk_urb->dev; 29962306a36Sopenharmony_ci struct device *dma_dev = stk1160_get_dmadev(dev); 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci switch (urb->status) { 30262306a36Sopenharmony_ci case 0: 30362306a36Sopenharmony_ci break; 30462306a36Sopenharmony_ci case -ECONNRESET: /* kill */ 30562306a36Sopenharmony_ci case -ENOENT: 30662306a36Sopenharmony_ci case -ESHUTDOWN: 30762306a36Sopenharmony_ci /* TODO: check uvc driver: he frees the queue here */ 30862306a36Sopenharmony_ci return; 30962306a36Sopenharmony_ci default: 31062306a36Sopenharmony_ci stk1160_err("urb error! status %d\n", urb->status); 31162306a36Sopenharmony_ci return; 31262306a36Sopenharmony_ci } 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci invalidate_kernel_vmap_range(stk_urb->transfer_buffer, 31562306a36Sopenharmony_ci urb->transfer_buffer_length); 31662306a36Sopenharmony_ci dma_sync_sgtable_for_cpu(dma_dev, stk_urb->sgt, DMA_FROM_DEVICE); 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci stk1160_process_isoc(dev, urb); 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci /* Reset urb buffers */ 32162306a36Sopenharmony_ci for (i = 0; i < urb->number_of_packets; i++) { 32262306a36Sopenharmony_ci urb->iso_frame_desc[i].status = 0; 32362306a36Sopenharmony_ci urb->iso_frame_desc[i].actual_length = 0; 32462306a36Sopenharmony_ci } 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci dma_sync_sgtable_for_device(dma_dev, stk_urb->sgt, DMA_FROM_DEVICE); 32762306a36Sopenharmony_ci rc = usb_submit_urb(urb, GFP_ATOMIC); 32862306a36Sopenharmony_ci if (rc) 32962306a36Sopenharmony_ci stk1160_err("urb re-submit failed (%d)\n", rc); 33062306a36Sopenharmony_ci} 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci/* 33362306a36Sopenharmony_ci * Cancel urbs 33462306a36Sopenharmony_ci * This function can't be called in atomic context 33562306a36Sopenharmony_ci */ 33662306a36Sopenharmony_civoid stk1160_cancel_isoc(struct stk1160 *dev) 33762306a36Sopenharmony_ci{ 33862306a36Sopenharmony_ci int i, num_bufs = dev->isoc_ctl.num_bufs; 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci /* 34162306a36Sopenharmony_ci * This check is not necessary, but we add it 34262306a36Sopenharmony_ci * to avoid a spurious debug message 34362306a36Sopenharmony_ci */ 34462306a36Sopenharmony_ci if (!num_bufs) 34562306a36Sopenharmony_ci return; 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci stk1160_dbg("killing %d urbs...\n", num_bufs); 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci for (i = 0; i < num_bufs; i++) { 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci /* 35262306a36Sopenharmony_ci * To kill urbs we can't be in atomic context. 35362306a36Sopenharmony_ci * We don't care for NULL pointer since 35462306a36Sopenharmony_ci * usb_kill_urb allows it. 35562306a36Sopenharmony_ci */ 35662306a36Sopenharmony_ci usb_kill_urb(dev->isoc_ctl.urb_ctl[i].urb); 35762306a36Sopenharmony_ci } 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci stk1160_dbg("all urbs killed\n"); 36062306a36Sopenharmony_ci} 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_cistatic void stk_free_urb(struct stk1160 *dev, struct stk1160_urb *stk_urb) 36362306a36Sopenharmony_ci{ 36462306a36Sopenharmony_ci struct device *dma_dev = stk1160_get_dmadev(dev); 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci dma_vunmap_noncontiguous(dma_dev, stk_urb->transfer_buffer); 36762306a36Sopenharmony_ci dma_free_noncontiguous(dma_dev, stk_urb->urb->transfer_buffer_length, 36862306a36Sopenharmony_ci stk_urb->sgt, DMA_FROM_DEVICE); 36962306a36Sopenharmony_ci usb_free_urb(stk_urb->urb); 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci stk_urb->transfer_buffer = NULL; 37262306a36Sopenharmony_ci stk_urb->sgt = NULL; 37362306a36Sopenharmony_ci stk_urb->urb = NULL; 37462306a36Sopenharmony_ci stk_urb->dev = NULL; 37562306a36Sopenharmony_ci stk_urb->dma = 0; 37662306a36Sopenharmony_ci} 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci/* 37962306a36Sopenharmony_ci * Releases urb and transfer buffers 38062306a36Sopenharmony_ci * Obviusly, associated urb must be killed before releasing it. 38162306a36Sopenharmony_ci */ 38262306a36Sopenharmony_civoid stk1160_free_isoc(struct stk1160 *dev) 38362306a36Sopenharmony_ci{ 38462306a36Sopenharmony_ci int i, num_bufs = dev->isoc_ctl.num_bufs; 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci stk1160_dbg("freeing %d urb buffers...\n", num_bufs); 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci for (i = 0; i < num_bufs; i++) 38962306a36Sopenharmony_ci stk_free_urb(dev, &dev->isoc_ctl.urb_ctl[i]); 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci dev->isoc_ctl.num_bufs = 0; 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci stk1160_dbg("all urb buffers freed\n"); 39462306a36Sopenharmony_ci} 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci/* 39762306a36Sopenharmony_ci * Helper for cancelling and freeing urbs 39862306a36Sopenharmony_ci * This function can't be called in atomic context 39962306a36Sopenharmony_ci */ 40062306a36Sopenharmony_civoid stk1160_uninit_isoc(struct stk1160 *dev) 40162306a36Sopenharmony_ci{ 40262306a36Sopenharmony_ci stk1160_cancel_isoc(dev); 40362306a36Sopenharmony_ci stk1160_free_isoc(dev); 40462306a36Sopenharmony_ci} 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_cistatic int stk1160_fill_urb(struct stk1160 *dev, struct stk1160_urb *stk_urb, 40762306a36Sopenharmony_ci int sb_size, int max_packets) 40862306a36Sopenharmony_ci{ 40962306a36Sopenharmony_ci struct device *dma_dev = stk1160_get_dmadev(dev); 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci stk_urb->urb = usb_alloc_urb(max_packets, GFP_KERNEL); 41262306a36Sopenharmony_ci if (!stk_urb->urb) 41362306a36Sopenharmony_ci return -ENOMEM; 41462306a36Sopenharmony_ci stk_urb->sgt = dma_alloc_noncontiguous(dma_dev, sb_size, 41562306a36Sopenharmony_ci DMA_FROM_DEVICE, GFP_KERNEL, 0); 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_ci /* 41862306a36Sopenharmony_ci * If the buffer allocation failed, we exit but return 0 since 41962306a36Sopenharmony_ci * we allow the driver working with less buffers 42062306a36Sopenharmony_ci */ 42162306a36Sopenharmony_ci if (!stk_urb->sgt) 42262306a36Sopenharmony_ci goto free_urb; 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci stk_urb->transfer_buffer = dma_vmap_noncontiguous(dma_dev, sb_size, 42562306a36Sopenharmony_ci stk_urb->sgt); 42662306a36Sopenharmony_ci if (!stk_urb->transfer_buffer) 42762306a36Sopenharmony_ci goto free_sgt; 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci stk_urb->dma = stk_urb->sgt->sgl->dma_address; 43062306a36Sopenharmony_ci stk_urb->dev = dev; 43162306a36Sopenharmony_ci return 0; 43262306a36Sopenharmony_cifree_sgt: 43362306a36Sopenharmony_ci dma_free_noncontiguous(dma_dev, sb_size, stk_urb->sgt, DMA_FROM_DEVICE); 43462306a36Sopenharmony_ci stk_urb->sgt = NULL; 43562306a36Sopenharmony_cifree_urb: 43662306a36Sopenharmony_ci usb_free_urb(stk_urb->urb); 43762306a36Sopenharmony_ci stk_urb->urb = NULL; 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci return 0; 44062306a36Sopenharmony_ci} 44162306a36Sopenharmony_ci/* 44262306a36Sopenharmony_ci * Allocate URBs 44362306a36Sopenharmony_ci */ 44462306a36Sopenharmony_ciint stk1160_alloc_isoc(struct stk1160 *dev) 44562306a36Sopenharmony_ci{ 44662306a36Sopenharmony_ci struct urb *urb; 44762306a36Sopenharmony_ci int i, j, k, sb_size, max_packets, num_bufs; 44862306a36Sopenharmony_ci int ret; 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_ci /* 45162306a36Sopenharmony_ci * It may be necessary to release isoc here, 45262306a36Sopenharmony_ci * since isoc are only released on disconnection. 45362306a36Sopenharmony_ci * (see new_pkt_size flag) 45462306a36Sopenharmony_ci */ 45562306a36Sopenharmony_ci if (dev->isoc_ctl.num_bufs) 45662306a36Sopenharmony_ci stk1160_uninit_isoc(dev); 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ci stk1160_dbg("allocating urbs...\n"); 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_ci num_bufs = STK1160_NUM_BUFS; 46162306a36Sopenharmony_ci max_packets = STK1160_NUM_PACKETS; 46262306a36Sopenharmony_ci sb_size = max_packets * dev->max_pkt_size; 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci dev->isoc_ctl.buf = NULL; 46562306a36Sopenharmony_ci dev->isoc_ctl.max_pkt_size = dev->max_pkt_size; 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_ci /* allocate urbs and transfer buffers */ 46862306a36Sopenharmony_ci for (i = 0; i < num_bufs; i++) { 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_ci ret = stk1160_fill_urb(dev, &dev->isoc_ctl.urb_ctl[i], 47162306a36Sopenharmony_ci sb_size, max_packets); 47262306a36Sopenharmony_ci if (ret) 47362306a36Sopenharmony_ci goto free_i_bufs; 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci urb = dev->isoc_ctl.urb_ctl[i].urb; 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci if (!urb) { 47862306a36Sopenharmony_ci /* Not enough transfer buffers, so just give up */ 47962306a36Sopenharmony_ci if (i < STK1160_MIN_BUFS) 48062306a36Sopenharmony_ci goto free_i_bufs; 48162306a36Sopenharmony_ci goto nomore_tx_bufs; 48262306a36Sopenharmony_ci } 48362306a36Sopenharmony_ci memset(dev->isoc_ctl.urb_ctl[i].transfer_buffer, 0, sb_size); 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ci /* 48662306a36Sopenharmony_ci * FIXME: Where can I get the endpoint? 48762306a36Sopenharmony_ci */ 48862306a36Sopenharmony_ci urb->dev = dev->udev; 48962306a36Sopenharmony_ci urb->pipe = usb_rcvisocpipe(dev->udev, STK1160_EP_VIDEO); 49062306a36Sopenharmony_ci urb->transfer_buffer = dev->isoc_ctl.urb_ctl[i].transfer_buffer; 49162306a36Sopenharmony_ci urb->transfer_buffer_length = sb_size; 49262306a36Sopenharmony_ci urb->complete = stk1160_isoc_irq; 49362306a36Sopenharmony_ci urb->context = &dev->isoc_ctl.urb_ctl[i]; 49462306a36Sopenharmony_ci urb->interval = 1; 49562306a36Sopenharmony_ci urb->start_frame = 0; 49662306a36Sopenharmony_ci urb->number_of_packets = max_packets; 49762306a36Sopenharmony_ci urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; 49862306a36Sopenharmony_ci urb->transfer_dma = dev->isoc_ctl.urb_ctl[i].dma; 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_ci k = 0; 50162306a36Sopenharmony_ci for (j = 0; j < max_packets; j++) { 50262306a36Sopenharmony_ci urb->iso_frame_desc[j].offset = k; 50362306a36Sopenharmony_ci urb->iso_frame_desc[j].length = 50462306a36Sopenharmony_ci dev->isoc_ctl.max_pkt_size; 50562306a36Sopenharmony_ci k += dev->isoc_ctl.max_pkt_size; 50662306a36Sopenharmony_ci } 50762306a36Sopenharmony_ci } 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_ci stk1160_dbg("%d urbs allocated\n", num_bufs); 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci /* At last we can say we have some buffers */ 51262306a36Sopenharmony_ci dev->isoc_ctl.num_bufs = num_bufs; 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci return 0; 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_cinomore_tx_bufs: 51762306a36Sopenharmony_ci /* 51862306a36Sopenharmony_ci * Failed to allocate desired buffer count. However, we may have 51962306a36Sopenharmony_ci * enough to work fine, so we just free the extra urb, 52062306a36Sopenharmony_ci * store the allocated count and keep going, fingers crossed! 52162306a36Sopenharmony_ci */ 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_ci stk1160_warn("%d urbs allocated. Trying to continue...\n", i); 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci dev->isoc_ctl.num_bufs = i; 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_ci return 0; 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_cifree_i_bufs: 53062306a36Sopenharmony_ci /* Save the allocated buffers so far, so we can properly free them */ 53162306a36Sopenharmony_ci dev->isoc_ctl.num_bufs = i; 53262306a36Sopenharmony_ci stk1160_free_isoc(dev); 53362306a36Sopenharmony_ci return -ENOMEM; 53462306a36Sopenharmony_ci} 53562306a36Sopenharmony_ci 536