/* Must be called with both v4l_lock and vb_queue_lock hold */ void stk1160_clear_queue(struct stk1160 *dev) { struct stk1160_buffer *buf; unsigned long flags; /* Release all active buffers */ spin_lock_irqsave(&dev->buf_lock, flags); while (!list_empty(&dev->avail_bufs)) { buf = list_first_entry(&dev->avail_bufs, struct stk1160_buffer, list); list_del(&buf->list); vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); stk1160_info("buffer [%p/%d] aborted\n", buf, buf->vb.v4l2_buf.index); } /* It's important to release the current buffer */ if (dev->isoc_ctl.buf) { buf = dev->isoc_ctl.buf; dev->isoc_ctl.buf = NULL; vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); stk1160_info("buffer [%p/%d] aborted\n", buf, buf->vb.v4l2_buf.index); } spin_unlock_irqrestore(&dev->buf_lock, flags); }
/* * Videobuf2 operations */ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *v4l_fmt, unsigned int *nbuffers, unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[]) { struct stk1160 *dev = vb2_get_drv_priv(vq); unsigned long size; size = dev->width * dev->height * 2; /* * Here we can change the number of buffers being requested. * So, we set a minimum and a maximum like this: */ *nbuffers = clamp_t(unsigned int, *nbuffers, STK1160_MIN_VIDEO_BUFFERS, STK1160_MAX_VIDEO_BUFFERS); /* This means a packed colorformat */ *nplanes = 1; sizes[0] = size; stk1160_info("%s: buffer count %d, each %ld bytes\n", __func__, *nbuffers, size); return 0; }
/* Must be called with v4l_lock hold */ static void stk1160_stop_hw(struct stk1160 *dev) { /* If the device is not physically present, there is nothing to do */ if (!dev->udev) return; /* set alternate 0 */ dev->alt = 0; stk1160_info("setting alternate %d\n", dev->alt); usb_set_interface(dev->udev, 0, 0); /* Stop stk1160 */ stk1160_write_reg(dev, STK1160_DCTRL, 0x00); stk1160_write_reg(dev, STK1160_DCTRL+3, 0x00); /* Stop saa711x */ v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0); }
/* * Set a new alternate setting. * Returns true is dev->max_pkt_size has changed, false otherwise. */ static bool stk1160_set_alternate(struct stk1160 *dev) { int i, prev_alt = dev->alt; unsigned int min_pkt_size; bool new_pkt_size; /* * If we don't set right alternate, * then we will get a green screen with junk. */ min_pkt_size = STK1160_MIN_PKT_SIZE; for (i = 0; i < dev->num_alt; i++) { /* stop when the selected alt setting offers enough bandwidth */ if (dev->alt_max_pkt_size[i] >= min_pkt_size) { dev->alt = i; break; /* * otherwise make sure that we end up with the maximum bandwidth * because the min_pkt_size equation might be wrong... */ } else if (dev->alt_max_pkt_size[i] > dev->alt_max_pkt_size[dev->alt]) dev->alt = i; } stk1160_info("setting alternate %d\n", dev->alt); if (dev->alt != prev_alt) { stk1160_dbg("minimum isoc packet size: %u (alt=%d)\n", min_pkt_size, dev->alt); stk1160_dbg("setting alt %d with wMaxPacketSize=%u\n", dev->alt, dev->alt_max_pkt_size[dev->alt]); usb_set_interface(dev->udev, 0, dev->alt); } new_pkt_size = dev->max_pkt_size != dev->alt_max_pkt_size[dev->alt]; dev->max_pkt_size = dev->alt_max_pkt_size[dev->alt]; return new_pkt_size; }