static int buffer_prepare(struct vb2_buffer *vb) { struct vb2_queue *vq = vb->vb2_queue; struct fimc_ctx *ctx = vq->drv_priv; struct v4l2_device *v4l2_dev = &ctx->fimc_dev->m2m.v4l2_dev; int i; if (!ctx->d_frame.fmt || vq->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) return -EINVAL; for (i = 0; i < ctx->d_frame.fmt->memplanes; i++) { unsigned long size = get_plane_size(&ctx->d_frame, i); if (vb2_plane_size(vb, i) < size) { v4l2_err(v4l2_dev, "User buffer too small (%ld < %ld)\n", vb2_plane_size(vb, i), size); return -EINVAL; } vb2_set_plane_payload(vb, i, size); } return 0; }
static int gsc_capture_buf_prepare(struct vb2_buffer *vb) { struct vb2_queue *vq = vb->vb2_queue; struct gsc_ctx *ctx = vq->drv_priv; struct gsc_frame *frame = &ctx->d_frame; int i; if (frame->fmt == NULL) return -EINVAL; for (i = 0; i < frame->fmt->num_planes; i++) { unsigned long size = frame->payload[i]; if (vb2_plane_size(vb, i) < size) { v4l2_err(ctx->gsc_dev->cap.vfd, "User buffer too small (%ld < %ld)\n", vb2_plane_size(vb, i), size); return -EINVAL; } vb2_set_plane_payload(vb, i, size); } return 0; }
static int dt3155_buf_prepare(struct vb2_buffer *vb) { vb2_set_plane_payload(vb, 0, img_width * img_height); return 0; }
int dvb_vb2_fill_buffer(struct dvb_vb2_ctx *ctx, const unsigned char *src, int len, enum dmx_buffer_flags *buffer_flags) { unsigned long flags = 0; void *vbuf = NULL; int todo = len; unsigned char *psrc = (unsigned char *)src; int ll = 0; /* * normal case: This func is called twice from demux driver * one with valid src pointer, second time with NULL pointer */ if (!src || !len) return 0; spin_lock_irqsave(&ctx->slock, flags); if (buffer_flags && *buffer_flags) { ctx->flags |= *buffer_flags; *buffer_flags = 0; } while (todo) { if (!ctx->buf) { if (list_empty(&ctx->dvb_q)) { dprintk(3, "[%s] Buffer overflow!!!\n", ctx->name); break; } ctx->buf = list_entry(ctx->dvb_q.next, struct dvb_buffer, list); ctx->remain = vb2_plane_size(&ctx->buf->vb, 0); ctx->offset = 0; } if (!dvb_vb2_is_streaming(ctx)) { vb2_buffer_done(&ctx->buf->vb, VB2_BUF_STATE_ERROR); list_del(&ctx->buf->list); ctx->buf = NULL; break; } /* Fill buffer */ ll = min(todo, ctx->remain); vbuf = vb2_plane_vaddr(&ctx->buf->vb, 0); memcpy(vbuf + ctx->offset, psrc, ll); todo -= ll; psrc += ll; ctx->remain -= ll; ctx->offset += ll; if (ctx->remain == 0) { vb2_buffer_done(&ctx->buf->vb, VB2_BUF_STATE_DONE); list_del(&ctx->buf->list); ctx->buf = NULL; } } if (ctx->nonblocking && ctx->buf) { vb2_set_plane_payload(&ctx->buf->vb, 0, ll); vb2_buffer_done(&ctx->buf->vb, VB2_BUF_STATE_DONE); list_del(&ctx->buf->list); ctx->buf = NULL; } spin_unlock_irqrestore(&ctx->slock, flags); if (todo) dprintk(1, "[%s] %d bytes are dropped.\n", ctx->name, todo); else dprintk(3, "[%s]\n", ctx->name); dprintk(3, "[%s] %d bytes are copied\n", ctx->name, len - todo); return (len - todo); }
/* Called for each 256-byte image chunk. * First word identifies the chunk, followed by 240 words of image * data and padding. */ static void usbtv_image_chunk(struct usbtv *usbtv, __be32 *chunk) { int frame_id, odd, chunk_no; u32 *frame; struct usbtv_buf *buf; unsigned long flags; /* Ignore corrupted lines. */ if (!USBTV_MAGIC_OK(chunk)) return; frame_id = USBTV_FRAME_ID(chunk); odd = USBTV_ODD(chunk); chunk_no = USBTV_CHUNK_NO(chunk); if (chunk_no >= usbtv->n_chunks) return; /* Beginning of a frame. */ if (chunk_no == 0) { usbtv->frame_id = frame_id; usbtv->chunks_done = 0; } if (usbtv->frame_id != frame_id) return; spin_lock_irqsave(&usbtv->buflock, flags); if (list_empty(&usbtv->bufs)) { /* No free buffers. Userspace likely too slow. */ spin_unlock_irqrestore(&usbtv->buflock, flags); return; } /* First available buffer. */ buf = list_first_entry(&usbtv->bufs, struct usbtv_buf, list); frame = vb2_plane_vaddr(&buf->vb.vb2_buf, 0); /* Copy the chunk data. */ usbtv_chunk_to_vbuf(frame, &chunk[1], chunk_no, odd); usbtv->chunks_done++; /* Last chunk in a field */ if (chunk_no == usbtv->n_chunks-1) { /* Last chunk in a frame, signalling an end */ if (odd && !usbtv->last_odd) { int size = vb2_plane_size(&buf->vb.vb2_buf, 0); enum vb2_buffer_state state = usbtv->chunks_done == usbtv->n_chunks ? VB2_BUF_STATE_DONE : VB2_BUF_STATE_ERROR; buf->vb.field = V4L2_FIELD_INTERLACED; buf->vb.sequence = usbtv->sequence++; buf->vb.vb2_buf.timestamp = ktime_get_ns(); vb2_set_plane_payload(&buf->vb.vb2_buf, 0, size); vb2_buffer_done(&buf->vb.vb2_buf, state); list_del(&buf->list); } usbtv->last_odd = odd; } spin_unlock_irqrestore(&usbtv->buflock, flags); }
static void mtk_vdec_worker(struct work_struct *work) { struct mtk_vcodec_ctx *ctx = container_of(work, struct mtk_vcodec_ctx, decode_work); struct mtk_vcodec_dev *dev = ctx->dev; struct vb2_buffer *src_buf, *dst_buf; struct mtk_vcodec_mem buf; struct vdec_fb *pfb; bool res_chg = false; int ret; struct mtk_video_dec_buf *dst_buf_info, *src_buf_info; struct vb2_v4l2_buffer *dst_vb2_v4l2, *src_vb2_v4l2; src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx); if (src_buf == NULL) { v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); mtk_v4l2_debug(1, "[%d] src_buf empty!!", ctx->id); return; } dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); if (dst_buf == NULL) { v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); mtk_v4l2_debug(1, "[%d] dst_buf empty!!", ctx->id); return; } src_vb2_v4l2 = container_of(src_buf, struct vb2_v4l2_buffer, vb2_buf); src_buf_info = container_of(src_vb2_v4l2, struct mtk_video_dec_buf, vb); dst_vb2_v4l2 = container_of(dst_buf, struct vb2_v4l2_buffer, vb2_buf); dst_buf_info = container_of(dst_vb2_v4l2, struct mtk_video_dec_buf, vb); pfb = &dst_buf_info->frame_buffer; pfb->base_y.va = vb2_plane_vaddr(dst_buf, 0); pfb->base_y.dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0); pfb->base_y.size = ctx->picinfo.y_bs_sz + ctx->picinfo.y_len_sz; pfb->base_c.va = vb2_plane_vaddr(dst_buf, 1); pfb->base_c.dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 1); pfb->base_c.size = ctx->picinfo.c_bs_sz + ctx->picinfo.c_len_sz; pfb->status = 0; mtk_v4l2_debug(3, "===>[%d] vdec_if_decode() ===>", ctx->id); mtk_v4l2_debug(3, "id=%d Framebuf pfb=%p VA=%p Y_DMA=%pad C_DMA=%pad Size=%zx", dst_buf->index, pfb, pfb->base_y.va, &pfb->base_y.dma_addr, &pfb->base_c.dma_addr, pfb->base_y.size); if (src_buf_info->lastframe) { mtk_v4l2_debug(1, "Got empty flush input buffer."); src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); /* update dst buf status */ dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); mutex_lock(&ctx->lock); dst_buf_info->used = false; mutex_unlock(&ctx->lock); vdec_if_decode(ctx, NULL, NULL, &res_chg); clean_display_buffer(ctx); vb2_set_plane_payload(&dst_buf_info->vb.vb2_buf, 0, 0); vb2_set_plane_payload(&dst_buf_info->vb.vb2_buf, 1, 0); dst_vb2_v4l2->flags |= V4L2_BUF_FLAG_LAST; v4l2_m2m_buf_done(&dst_buf_info->vb, VB2_BUF_STATE_DONE); clean_free_buffer(ctx); v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); return; } buf.va = vb2_plane_vaddr(src_buf, 0); buf.dma_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0); buf.size = (size_t)src_buf->planes[0].bytesused; if (!buf.va) { v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); mtk_v4l2_err("[%d] id=%d src_addr is NULL!!", ctx->id, src_buf->index); return; } mtk_v4l2_debug(3, "[%d] Bitstream VA=%p DMA=%pad Size=%zx vb=%p", ctx->id, buf.va, &buf.dma_addr, buf.size, src_buf); dst_buf_info->vb.vb2_buf.timestamp = src_buf_info->vb.vb2_buf.timestamp; dst_buf_info->vb.timecode = src_buf_info->vb.timecode; mutex_lock(&ctx->lock); dst_buf_info->used = true; mutex_unlock(&ctx->lock); src_buf_info->used = true; ret = vdec_if_decode(ctx, &buf, pfb, &res_chg); if (ret) { mtk_v4l2_err( " <===[%d], src_buf[%d] sz=0x%zx pts=%llu dst_buf[%d] vdec_if_decode() ret=%d res_chg=%d===>", ctx->id, src_buf->index, buf.size, src_buf_info->vb.vb2_buf.timestamp, dst_buf->index, ret, res_chg); src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); v4l2_m2m_buf_done(&src_buf_info->vb, VB2_BUF_STATE_ERROR); } else if (res_chg == false) { /* * we only return src buffer with VB2_BUF_STATE_DONE * when decode success without resolution change */ src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); v4l2_m2m_buf_done(&src_buf_info->vb, VB2_BUF_STATE_DONE); } dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); clean_display_buffer(ctx); clean_free_buffer(ctx); if (!ret && res_chg) { mtk_vdec_pic_info_update(ctx); /* * On encountering a resolution change in the stream. * The driver must first process and decode all * remaining buffers from before the resolution change * point, so call flush decode here */ mtk_vdec_flush_decoder(ctx); /* * After all buffers containing decoded frames from * before the resolution change point ready to be * dequeued on the CAPTURE queue, the driver sends a * V4L2_EVENT_SOURCE_CHANGE event for source change * type V4L2_EVENT_SRC_CH_RESOLUTION */ mtk_vdec_queue_res_chg_event(ctx); } v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); }
static irqreturn_t jpeg_hx_irq(int irq, void *priv) { unsigned int int_status; struct vb2_buffer *src_vb, *dst_vb; struct jpeg_dev *ctrl = priv; struct jpeg_ctx *ctx; unsigned long payload_size = 0; if (ctrl->mode == ENCODING) ctx = v4l2_m2m_get_curr_priv(ctrl->m2m_dev_enc); else ctx = v4l2_m2m_get_curr_priv(ctrl->m2m_dev_dec); if (ctx == 0) { printk(KERN_ERR "ctx is null.\n"); jpeg_hx_sw_reset(ctrl->reg_base); goto ctx_err; } spin_lock(&ctx->slock); int_status = jpeg_hx_int_pending(ctrl); jpeg_hx_clear_int_status(ctrl->reg_base, int_status); if (int_status == 8 && ctrl->mode == DECODING) { jpeg_hx_re_start(ctrl->reg_base); spin_unlock(&ctx->slock); return IRQ_HANDLED; } src_vb = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); dst_vb = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); if (int_status) { switch (int_status & 0xfff) { case 0xe20: ctrl->irq_ret = OK_ENC_OR_DEC; break; default: ctrl->irq_ret = ERR_UNKNOWN; break; } } else { ctrl->irq_ret = ERR_UNKNOWN; } if (ctrl->irq_ret == OK_ENC_OR_DEC) { if (ctrl->mode == ENCODING) { payload_size = jpeg_hx_get_stream_size(ctrl->reg_base); vb2_set_plane_payload(dst_vb, 0, payload_size); v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE); v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE); } else if (int_status != 8 && ctrl->mode == DECODING) { v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE); v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE); } } else { v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_ERROR); v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_ERROR); } if (ctrl->mode == ENCODING) v4l2_m2m_job_finish(ctrl->m2m_dev_enc, ctx->m2m_ctx); else v4l2_m2m_job_finish(ctrl->m2m_dev_dec, ctx->m2m_ctx); spin_unlock(&ctx->slock); ctx_err: return IRQ_HANDLED; }
int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf) { int n, line, col; void *yuv, *image; u16 *src; u16 *dsty, *dstu, *dstv; image = vb2_plane_vaddr(&fbuf->vb, 0); yuv = fbuf->data + pdev->frame_header_size; /* Skip header */ /* Raw format; that's easy... */ if (pdev->pixfmt != V4L2_PIX_FMT_YUV420) { struct pwc_raw_frame *raw_frame = image; raw_frame->type = cpu_to_le16(pdev->type); raw_frame->vbandlength = cpu_to_le16(pdev->vbandlength); /* cmd_buf is always 4 bytes, but sometimes, only the * first 3 bytes is filled (Nala case). We can * determine this using the type of the webcam */ memcpy(raw_frame->cmd, pdev->cmd_buf, 4); memcpy(raw_frame+1, yuv, pdev->frame_size); vb2_set_plane_payload(&fbuf->vb, 0, pdev->frame_size + sizeof(struct pwc_raw_frame)); return 0; } vb2_set_plane_payload(&fbuf->vb, 0, pdev->width * pdev->height * 3 / 2); if (pdev->vbandlength == 0) { /* Uncompressed mode. * * We do some byte shuffling here to go from the * native format to YUV420P. */ src = (u16 *)yuv; n = pdev->width * pdev->height; dsty = (u16 *)(image); dstu = (u16 *)(image + n); dstv = (u16 *)(image + n + n / 4); for (line = 0; line < pdev->height; line++) { for (col = 0; col < pdev->width; col += 4) { *dsty++ = *src++; *dsty++ = *src++; if (line & 1) *dstv++ = *src++; else *dstu++ = *src++; } } return 0; } /* * Compressed; * the decompressor routines will write the data in planar format * immediately. */ if (DEVICE_USE_CODEC1(pdev->type)) { /* TODO & FIXME */ PWC_ERROR("This chipset is not supported for now\n"); return -ENXIO; /* No such device or address: missing decompressor */ } else { pwc_dec23_decompress(pdev, yuv, image); } return 0; }