static void vb2ops_vdec_buf_queue(struct vb2_buffer *vb) { struct vb2_buffer *src_buf; struct mtk_vcodec_mem src_mem; bool res_chg = false; int ret = 0; unsigned int dpbsize = 1; struct mtk_vcodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); struct vb2_v4l2_buffer *vb2_v4l2 = NULL; struct mtk_video_dec_buf *buf = NULL; mtk_v4l2_debug(3, "[%d] (%d) id=%d, vb=%p", ctx->id, vb->vb2_queue->type, vb->index, vb); /* * check if this buffer is ready to be used after decode */ if (vb->vb2_queue->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { vb2_v4l2 = to_vb2_v4l2_buffer(vb); buf = container_of(vb2_v4l2, struct mtk_video_dec_buf, vb); mutex_lock(&ctx->lock); if (buf->used == false) { v4l2_m2m_buf_queue(ctx->m2m_ctx, vb2_v4l2); buf->queued_in_vb2 = true; buf->queued_in_v4l2 = true; buf->ready_to_display = false; } else { buf->queued_in_vb2 = false; buf->queued_in_v4l2 = true; buf->ready_to_display = false; } mutex_unlock(&ctx->lock); return; }
static int uvc_buffer_prepare(struct vb2_buffer *vb) { struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue); struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct uvc_buffer *buf = container_of(vbuf, struct uvc_buffer, buf); if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) { uvc_trace(UVC_TRACE_CAPTURE, "[E] Bytes used out of bounds.\n"); return -EINVAL; } if (unlikely(queue->flags & UVC_QUEUE_DISCONNECTED)) return -ENODEV; buf->state = UVC_BUF_STATE_QUEUED; buf->mem = vb2_plane_vaddr(vb, 0); buf->length = vb2_plane_size(vb, 0); if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) buf->bytesused = 0; else buf->bytesused = vb2_get_plane_payload(vb, 0); return 0; }
static int video_buf_init(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct camss_video *video = vb2_get_drv_priv(vb->vb2_queue); struct camss_buffer *buffer = container_of(vbuf, struct camss_buffer, vb); const struct v4l2_pix_format_mplane *format = &video->active_fmt.fmt.pix_mp; struct sg_table *sgt; unsigned int i; for (i = 0; i < format->num_planes; i++) { sgt = vb2_dma_sg_plane_desc(vb, i); if (!sgt) return -EFAULT; buffer->addr[i] = sg_dma_address(sgt->sgl); } if (format->pixelformat == V4L2_PIX_FMT_NV12 || format->pixelformat == V4L2_PIX_FMT_NV21 || format->pixelformat == V4L2_PIX_FMT_NV16 || format->pixelformat == V4L2_PIX_FMT_NV61) buffer->addr[1] = buffer->addr[0] + format->plane_fmt[0].bytesperline * format->height; return 0; }
static int isp_video_buffer_prepare(struct vb2_buffer *buf) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(buf); struct isp_video_fh *vfh = vb2_get_drv_priv(buf->vb2_queue); struct isp_buffer *buffer = to_isp_buffer(vbuf); struct isp_video *video = vfh->video; dma_addr_t 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 = vb2_dma_contig_plane_dma_addr(buf, 0); if (!IS_ALIGNED(addr, 32)) { dev_dbg(video->isp->dev, "Buffer address must be aligned to 32 bytes boundary.\n"); return -EINVAL; } vb2_set_plane_payload(&buffer->vb.vb2_buf, 0, vfh->format.fmt.pix.sizeimage); buffer->dma = addr; return 0; }
static void buffer_queue(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct cx8800_dev *dev = vb->vb2_queue->drv_priv; struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb); struct cx88_buffer *prev; struct cx88_dmaqueue *q = &dev->vbiq; /* add jump to start */ buf->risc.cpu[1] = cpu_to_le32(buf->risc.dma + 8); buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_CNT_INC); buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma + 8); if (list_empty(&q->active)) { list_add_tail(&buf->list, &q->active); cx8800_start_vbi_dma(dev, q, buf); dprintk(2,"[%p/%d] vbi_queue - first active\n", buf, buf->vb.vb2_buf.index); } else { buf->risc.cpu[0] |= cpu_to_le32(RISC_IRQ1); prev = list_entry(q->active.prev, struct cx88_buffer, list); list_add_tail(&buf->list, &q->active); prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); dprintk(2,"[%p/%d] buffer_queue - append to active\n", buf, buf->vb.vb2_buf.index); } }
static void buffer_cleanup(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct pwc_frame_buf *buf = container_of(vbuf, struct pwc_frame_buf, vb); vfree(buf->data); }
static void hva_buf_queue(struct vb2_buffer *vb) { struct hva_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); if (ctx->fh.m2m_ctx) v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); }
static void video_buf_queue(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct camss_video *video = vb2_get_drv_priv(vb->vb2_queue); struct camss_buffer *buffer = container_of(vbuf, struct camss_buffer, vb); video->ops->queue_buffer(video, buffer); }
static void uvc_buffer_finish(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue); struct uvc_streaming *stream = uvc_queue_to_stream(queue); struct uvc_buffer *buf = uvc_vbuf_to_buffer(vbuf); if (vb->state == VB2_BUF_STATE_DONE) uvc_video_clock_update(stream, vbuf, buf); }
static void gsc_m2m_buf_queue(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct gsc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); pr_debug("ctx: %p, ctx->state: 0x%x", ctx, ctx->state); if (ctx->m2m_ctx) v4l2_m2m_buf_queue(ctx->m2m_ctx, vbuf); }
static void buffer_finish(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct cx8800_dev *dev = vb->vb2_queue->drv_priv; struct cx88_buffer *buf = container_of(vbuf, struct cx88_buffer, vb); struct cx88_riscmem *risc = &buf->risc; if (risc->cpu) pci_free_consistent(dev->pci, risc->size, risc->cpu, risc->dma); memset(risc, 0, sizeof(*risc)); }
static void histo_buffer_queue(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct vsp1_histogram *histo = vb2_get_drv_priv(vb->vb2_queue); struct vsp1_histogram_buffer *buf = to_vsp1_histogram_buffer(vbuf); unsigned long flags; spin_lock_irqsave(&histo->irqlock, flags); list_add_tail(&buf->queue, &histo->irqqueue); spin_unlock_irqrestore(&histo->irqlock, flags); }
static void solo_buf_queue(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct vb2_queue *vq = vb->vb2_queue; struct solo_dev *solo_dev = vb2_get_drv_priv(vq); struct solo_vb2_buf *solo_vb = container_of(vbuf, struct solo_vb2_buf, vb); spin_lock(&solo_dev->slock); list_add_tail(&solo_vb->list, &solo_dev->vidq_active); spin_unlock(&solo_dev->slock); wake_up_interruptible(&solo_dev->disp_thread_wait); }
static void dt3155_buf_queue(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct dt3155_priv *pd = vb2_get_drv_priv(vb->vb2_queue); /* pd->vidq.streaming = 1 when dt3155_buf_queue() is invoked */ spin_lock_irq(&pd->lock); if (pd->curr_buf) list_add_tail(&vb->done_entry, &pd->dmaq); else pd->curr_buf = vbuf; spin_unlock_irq(&pd->lock); }
static int buffer_init(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct pwc_frame_buf *buf = container_of(vbuf, struct pwc_frame_buf, vb); /* need vmalloc since frame buffer > 128K */ buf->data = vzalloc(PWC_FRAME_SIZE); if (buf->data == NULL) return -ENOMEM; return 0; }
static int hva_buf_prepare(struct vb2_buffer *vb) { struct hva_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); struct device *dev = ctx_to_dev(ctx); struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); if (vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { struct hva_frame *frame = to_hva_frame(vbuf); if (vbuf->field == V4L2_FIELD_ANY) vbuf->field = V4L2_FIELD_NONE; if (vbuf->field != V4L2_FIELD_NONE) { dev_dbg(dev, "%s frame[%d] prepare: %d field not supported\n", ctx->name, vb->index, vbuf->field); return -EINVAL; } if (!frame->prepared) { /* get memory addresses */ frame->vaddr = vb2_plane_vaddr(&vbuf->vb2_buf, 0); frame->paddr = vb2_dma_contig_plane_dma_addr( &vbuf->vb2_buf, 0); frame->info = ctx->frameinfo; frame->prepared = true; dev_dbg(dev, "%s frame[%d] prepared; virt=%p, phy=%pad\n", ctx->name, vb->index, frame->vaddr, &frame->paddr); } } else { struct hva_stream *stream = to_hva_stream(vbuf); if (!stream->prepared) { /* get memory addresses */ stream->vaddr = vb2_plane_vaddr(&vbuf->vb2_buf, 0); stream->paddr = vb2_dma_contig_plane_dma_addr( &vbuf->vb2_buf, 0); stream->size = vb2_plane_size(&vbuf->vb2_buf, 0); stream->prepared = true; dev_dbg(dev, "%s stream[%d] prepared; virt=%p, phy=%pad\n", ctx->name, vb->index, stream->vaddr, &stream->paddr); } } return 0; }
static void bdisp_buf_queue(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct bdisp_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); /* return to V4L2 any 0-size buffer so it can be dequeued by user */ if (!vb2_get_plane_payload(vb, 0)) { dev_dbg(ctx->bdisp_dev->dev, "0 data buffer, skip it\n"); vb2_buffer_done(vb, VB2_BUF_STATE_DONE); return; } if (ctx->fh.m2m_ctx) v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf); }
static irqreturn_t dt3155_irq_handler_even(int irq, void *dev_id) { struct dt3155_priv *ipd = dev_id; struct vb2_buffer *ivb; dma_addr_t dma_addr; u32 tmp; tmp = ioread32(ipd->regs + INT_CSR) & (FLD_START | FLD_END_ODD); if (!tmp) return IRQ_NONE; /* not our irq */ if ((tmp & FLD_START) && !(tmp & FLD_END_ODD)) { iowrite32(FLD_START_EN | FLD_END_ODD_EN | FLD_START, ipd->regs + INT_CSR); return IRQ_HANDLED; /* start of field irq */ } tmp = ioread32(ipd->regs + CSR1) & (FLD_CRPT_EVEN | FLD_CRPT_ODD); if (tmp) { iowrite32(FIFO_EN | SRST | FLD_CRPT_ODD | FLD_CRPT_EVEN | FLD_DN_ODD | FLD_DN_EVEN | CAP_CONT_EVEN | CAP_CONT_ODD, ipd->regs + CSR1); mmiowb(); } spin_lock(&ipd->lock); if (ipd->curr_buf && !list_empty(&ipd->dmaq)) { ipd->curr_buf->vb2_buf.timestamp = ktime_get_ns(); ipd->curr_buf->sequence = ipd->sequence++; ipd->curr_buf->field = V4L2_FIELD_NONE; vb2_buffer_done(&ipd->curr_buf->vb2_buf, VB2_BUF_STATE_DONE); ivb = list_first_entry(&ipd->dmaq, typeof(*ivb), done_entry); list_del(&ivb->done_entry); ipd->curr_buf = to_vb2_v4l2_buffer(ivb); dma_addr = vb2_dma_contig_plane_dma_addr(ivb, 0); iowrite32(dma_addr, ipd->regs + EVEN_DMA_START); iowrite32(dma_addr + ipd->width, ipd->regs + ODD_DMA_START); iowrite32(ipd->width, ipd->regs + EVEN_DMA_STRIDE); iowrite32(ipd->width, ipd->regs + ODD_DMA_STRIDE); mmiowb(); } /* enable interrupts, clear all irq flags */ iowrite32(FLD_START_EN | FLD_END_ODD_EN | FLD_START | FLD_END_EVEN | FLD_END_ODD, ipd->regs + INT_CSR); spin_unlock(&ipd->lock); return IRQ_HANDLED; }
static void usbtv_buf_queue(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct usbtv *usbtv = vb2_get_drv_priv(vb->vb2_queue); struct usbtv_buf *buf = container_of(vbuf, struct usbtv_buf, vb); unsigned long flags; if (usbtv->udev == NULL) { vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); return; } spin_lock_irqsave(&usbtv->buflock, flags); list_add_tail(&buf->list, &usbtv->bufs); spin_unlock_irqrestore(&usbtv->buflock, flags); }
static int histo_buffer_prepare(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct vsp1_histogram *histo = vb2_get_drv_priv(vb->vb2_queue); struct vsp1_histogram_buffer *buf = to_vsp1_histogram_buffer(vbuf); if (vb->num_planes != 1) return -EINVAL; if (vb2_plane_size(vb, 0) < histo->data_size) return -EINVAL; buf->addr = vb2_plane_vaddr(vb, 0); return 0; }
static void vbi_buffer_queue(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct em28xx *dev = vb2_get_drv_priv(vb->vb2_queue); struct em28xx_buffer *buf = container_of(vbuf, struct em28xx_buffer, vb); struct em28xx_dmaqueue *vbiq = &dev->vbiq; unsigned long flags = 0; buf->mem = vb2_plane_vaddr(vb, 0); buf->length = vb2_plane_size(vb, 0); spin_lock_irqsave(&dev->slock, flags); list_add_tail(&buf->list, &vbiq->active); spin_unlock_irqrestore(&dev->slock, flags); }
/* * 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 vb2_buffer *buf) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(buf); struct isp_video_fh *vfh = vb2_get_drv_priv(buf->vb2_queue); struct isp_buffer *buffer = to_isp_buffer(vbuf); 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; spin_lock_irqsave(&video->irqlock, flags); if (unlikely(video->error)) { vb2_buffer_done(&buffer->vb.vb2_buf, VB2_BUF_STATE_ERROR); spin_unlock_irqrestore(&video->irqlock, flags); return; } empty = list_empty(&video->dmaqueue); list_add_tail(&buffer->irqlist, &video->dmaqueue); spin_unlock_irqrestore(&video->irqlock, flags); 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 void buffer_finish(struct vb2_buffer *vb) { struct pwc_device *pdev = vb2_get_drv_priv(vb->vb2_queue); struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct pwc_frame_buf *buf = container_of(vbuf, struct pwc_frame_buf, vb); if (vb->state == VB2_BUF_STATE_DONE) { /* * Application has called dqbuf and is getting back a buffer * we've filled, take the pwc data we've stored in buf->data * and decompress it into a usable format, storing the result * in the vb2_buffer. */ pwc_decompress(pdev, buf); } }
static void __copy_timestamp(struct vb2_buffer *vb, const void *pb) { const struct v4l2_buffer *b = pb; struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct vb2_queue *q = vb->vb2_queue; if (q->is_output) { /* * For output buffers copy the timestamp if needed, * and the timecode field and flag if needed. */ if (q->copy_timestamp) vb->timestamp = timeval_to_ns(&b->timestamp); vbuf->flags |= b->flags & V4L2_BUF_FLAG_TIMECODE; if (b->flags & V4L2_BUF_FLAG_TIMECODE) vbuf->timecode = b->timecode; } };
static void buffer_queue(struct vb2_buffer *vb) { struct pwc_device *pdev = vb2_get_drv_priv(vb->vb2_queue); struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct pwc_frame_buf *buf = container_of(vbuf, struct pwc_frame_buf, vb); unsigned long flags = 0; /* Check the device has not disconnected between prep and queuing */ if (!pdev->udev) { vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); return; } spin_lock_irqsave(&pdev->queued_bufs_lock, flags); list_add_tail(&buf->list, &pdev->queued_bufs); spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags); }
static int video_buf_prepare(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct camss_video *video = vb2_get_drv_priv(vb->vb2_queue); const struct v4l2_pix_format_mplane *format = &video->active_fmt.fmt.pix_mp; unsigned int i; for (i = 0; i < format->num_planes; i++) { if (format->plane_fmt[i].sizeimage > vb2_plane_size(vb, i)) return -EINVAL; vb2_set_plane_payload(vb, i, format->plane_fmt[i].sizeimage); } vbuf->field = V4L2_FIELD_NONE; return 0; }
static void isp_video_capture_buffer_queue(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct fimc_isp *isp = vb2_get_drv_priv(vb->vb2_queue); struct fimc_is_video *video = &isp->video_capture; struct fimc_is *is = fimc_isp_to_is(isp); struct isp_video_buf *ivb = to_isp_video_buf(vbuf); unsigned long flags; unsigned int i; if (test_bit(ST_ISP_VID_CAP_BUF_PREP, &isp->state)) { spin_lock_irqsave(&is->slock, flags); video->buf_mask |= BIT(ivb->index); spin_unlock_irqrestore(&is->slock, flags); } else { unsigned int num_planes = video->format->memplanes; ivb->index = video->buf_count; video->buffers[ivb->index] = ivb; for (i = 0; i < num_planes; i++) { int buf_index = ivb->index * num_planes + i; ivb->dma_addr[i] = vb2_dma_contig_plane_dma_addr(vb, i); is->is_p_region->shared[32 + buf_index] = ivb->dma_addr[i]; isp_dbg(2, &video->ve.vdev, "dma_buf %pad (%d/%d/%d) addr: %pad\n", &buf_index, ivb->index, i, vb->index, &ivb->dma_addr[i]); } if (++video->buf_count < video->reqbufs_count) return; video->buf_mask = (1UL << video->buf_count) - 1; set_bit(ST_ISP_VID_CAP_BUF_PREP, &isp->state); } if (!test_bit(ST_ISP_VID_CAP_STREAMING, &isp->state)) isp_video_capture_start_streaming(vb->vb2_queue, 0); }
static void uvc_buffer_queue(struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue); struct uvc_buffer *buf = container_of(vbuf, struct uvc_buffer, buf); unsigned long flags; spin_lock_irqsave(&queue->irqlock, flags); if (likely(!(queue->flags & UVC_QUEUE_DISCONNECTED))) { list_add_tail(&buf->queue, &queue->irqqueue); } else { /* If the device is disconnected return the buffer to userspace * directly. The next QBUF call will fail with -ENODEV. */ buf->state = UVC_BUF_STATE_ERROR; vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); } spin_unlock_irqrestore(&queue->irqlock, flags); }
static int __set_timestamp(struct vb2_buffer *vb, const void *pb) { const struct v4l2_buffer *b = pb; struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); struct vb2_queue *q = vb->vb2_queue; if (q->is_output) { /* * For output buffers copy the timestamp if needed, * and the timecode field and flag if needed. */ if ((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) == V4L2_BUF_FLAG_TIMESTAMP_COPY) vbuf->timestamp = b->timestamp; vbuf->flags |= b->flags & V4L2_BUF_FLAG_TIMECODE; if (b->flags & V4L2_BUF_FLAG_TIMECODE) vbuf->timecode = b->timecode; } return 0; };
static void solo_fillbuf(struct solo_dev *solo_dev, struct vb2_buffer *vb) { struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); dma_addr_t addr; unsigned int fdma_addr; int error = -1; int i; addr = vb2_dma_contig_plane_dma_addr(vb, 0); if (!addr) goto finish_buf; if (erase_off(solo_dev)) { void *p = vb2_plane_vaddr(vb, 0); int image_size = solo_image_size(solo_dev); for (i = 0; i < image_size; i += 2) { ((u8 *)p)[i] = 0x80; ((u8 *)p)[i + 1] = 0x00; } error = 0; } else { fdma_addr = SOLO_DISP_EXT_ADDR + (solo_dev->old_write * (SOLO_HW_BPL * solo_vlines(solo_dev))); error = solo_p2m_dma_t(solo_dev, 0, addr, fdma_addr, solo_bytesperline(solo_dev), solo_vlines(solo_dev), SOLO_HW_BPL); } finish_buf: if (!error) { vb2_set_plane_payload(vb, 0, solo_vlines(solo_dev) * solo_bytesperline(solo_dev)); vbuf->sequence = solo_dev->sequence++; vb->timestamp = ktime_get_ns(); } vb2_buffer_done(vb, error ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); }