/* * isp_video_buffer_queue - Add buffer to streaming queue * @buf: Video buffer * * In memory-to-memory mode, start streaming on the pipeline if buffers are * queued on both the input and the output, if the pipeline isn't already busy. * If the pipeline is busy, it will be restarted in the output module interrupt * handler. */ static void isp_video_buffer_queue(struct isp_video_buffer *buf) { struct isp_video_fh *vfh = isp_video_queue_to_isp_video_fh(buf->queue); struct isp_buffer *buffer = to_isp_buffer(buf); struct isp_video *video = vfh->video; struct isp_pipeline *pipe = to_isp_pipeline(&video->video.entity); enum isp_pipeline_state state; unsigned long flags; unsigned int empty; unsigned int start; empty = list_empty(&video->dmaqueue); list_add_tail(&buffer->buffer.irqlist, &video->dmaqueue); if (empty) { if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) state = ISP_PIPELINE_QUEUE_OUTPUT; else state = ISP_PIPELINE_QUEUE_INPUT; spin_lock_irqsave(&pipe->lock, flags); pipe->state |= state; video->ops->queue(video, buffer); video->dmaqueue_flags |= ISP_VIDEO_DMAQUEUE_QUEUED; start = isp_pipeline_ready(pipe); if (start) pipe->state |= ISP_PIPELINE_STREAM; spin_unlock_irqrestore(&pipe->lock, flags); if (start) omap3isp_pipeline_set_stream(pipe, ISP_PIPELINE_STREAM_SINGLESHOT); } }
static int isp_video_buffer_prepare(struct isp_video_buffer *buf) { struct isp_video_fh *vfh = isp_video_queue_to_isp_video_fh(buf->queue); struct isp_buffer *buffer = to_isp_buffer(buf); struct isp_video *video = vfh->video; unsigned long addr; /* Refuse to prepare the buffer is the video node has registered an * error. We don't need to take any lock here as the operation is * inherently racy. The authoritative check will be performed in the * queue handler, which can't return an error, this check is just a best * effort to notify userspace as early as possible. */ if (unlikely(video->error)) return -EIO; addr = ispmmu_vmap(video->isp, buf->sglist, buf->sglen); if (IS_ERR_VALUE(addr)) return -EIO; if (!IS_ALIGNED(addr, 32)) { dev_dbg(video->isp->dev, "Buffer address must be " "aligned to 32 bytes boundary.\n"); ispmmu_vunmap(video->isp, buffer->isp_addr); return -EINVAL; } buf->vbuf.bytesused = vfh->format.fmt.pix.sizeimage; buffer->isp_addr = addr; return 0; }
static void isp_video_buffer_cleanup(struct isp_video_buffer *buf) { struct isp_video_fh *vfh = isp_video_queue_to_isp_video_fh(buf->queue); struct isp_buffer *buffer = to_isp_buffer(buf); struct isp_video *video = vfh->video; if (buffer->isp_addr) { ispmmu_vunmap(video->isp, buffer->isp_addr); buffer->isp_addr = 0; } }
static int isp_video_buffer_prepare(struct isp_video_buffer *buf) { struct isp_video_fh *vfh = isp_video_queue_to_isp_video_fh(buf->queue); struct isp_buffer *buffer = to_isp_buffer(buf); struct isp_video *video = vfh->video; unsigned long addr; addr = ispmmu_vmap(video->isp, buf->sglist, buf->sglen); if (IS_ERR_VALUE(addr)) return -EIO; if (!IS_ALIGNED(addr, 32)) { dev_dbg(video->isp->dev, "Buffer address must be " "aligned to 32 bytes boundary.\n"); ispmmu_vunmap(video->isp, buffer->isp_addr); return -EINVAL; } buf->vbuf.bytesused = vfh->format.fmt.pix.sizeimage; buffer->isp_addr = addr; return 0; }