162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * videobuf2-v4l2.c - V4L2 driver helper framework 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright (C) 2010 Samsung Electronics 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Author: Pawel Osciak <pawel@osciak.com> 762306a36Sopenharmony_ci * Marek Szyprowski <m.szyprowski@samsung.com> 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * The vb2_thread implementation was based on code from videobuf-dvb.c: 1062306a36Sopenharmony_ci * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SUSE Labs] 1162306a36Sopenharmony_ci * 1262306a36Sopenharmony_ci * This program is free software; you can redistribute it and/or modify 1362306a36Sopenharmony_ci * it under the terms of the GNU General Public License as published by 1462306a36Sopenharmony_ci * the Free Software Foundation. 1562306a36Sopenharmony_ci */ 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#include <linux/device.h> 1862306a36Sopenharmony_ci#include <linux/err.h> 1962306a36Sopenharmony_ci#include <linux/freezer.h> 2062306a36Sopenharmony_ci#include <linux/kernel.h> 2162306a36Sopenharmony_ci#include <linux/kthread.h> 2262306a36Sopenharmony_ci#include <linux/mm.h> 2362306a36Sopenharmony_ci#include <linux/module.h> 2462306a36Sopenharmony_ci#include <linux/poll.h> 2562306a36Sopenharmony_ci#include <linux/sched.h> 2662306a36Sopenharmony_ci#include <linux/slab.h> 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci#include <media/v4l2-common.h> 2962306a36Sopenharmony_ci#include <media/v4l2-dev.h> 3062306a36Sopenharmony_ci#include <media/v4l2-device.h> 3162306a36Sopenharmony_ci#include <media/v4l2-event.h> 3262306a36Sopenharmony_ci#include <media/v4l2-fh.h> 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci#include <media/videobuf2-v4l2.h> 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_cistatic int debug; 3762306a36Sopenharmony_cimodule_param(debug, int, 0644); 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci#define dprintk(q, level, fmt, arg...) \ 4062306a36Sopenharmony_ci do { \ 4162306a36Sopenharmony_ci if (debug >= level) \ 4262306a36Sopenharmony_ci pr_info("vb2-v4l2: [%p] %s: " fmt, \ 4362306a36Sopenharmony_ci (q)->name, __func__, ## arg); \ 4462306a36Sopenharmony_ci } while (0) 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci/* Flags that are set by us */ 4762306a36Sopenharmony_ci#define V4L2_BUFFER_MASK_FLAGS (V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED | \ 4862306a36Sopenharmony_ci V4L2_BUF_FLAG_DONE | V4L2_BUF_FLAG_ERROR | \ 4962306a36Sopenharmony_ci V4L2_BUF_FLAG_PREPARED | \ 5062306a36Sopenharmony_ci V4L2_BUF_FLAG_IN_REQUEST | \ 5162306a36Sopenharmony_ci V4L2_BUF_FLAG_REQUEST_FD | \ 5262306a36Sopenharmony_ci V4L2_BUF_FLAG_TIMESTAMP_MASK) 5362306a36Sopenharmony_ci/* Output buffer flags that should be passed on to the driver */ 5462306a36Sopenharmony_ci#define V4L2_BUFFER_OUT_FLAGS (V4L2_BUF_FLAG_PFRAME | \ 5562306a36Sopenharmony_ci V4L2_BUF_FLAG_BFRAME | \ 5662306a36Sopenharmony_ci V4L2_BUF_FLAG_KEYFRAME | \ 5762306a36Sopenharmony_ci V4L2_BUF_FLAG_TIMECODE | \ 5862306a36Sopenharmony_ci V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF) 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci/* 6162306a36Sopenharmony_ci * __verify_planes_array() - verify that the planes array passed in struct 6262306a36Sopenharmony_ci * v4l2_buffer from userspace can be safely used 6362306a36Sopenharmony_ci */ 6462306a36Sopenharmony_cistatic int __verify_planes_array(struct vb2_buffer *vb, const struct v4l2_buffer *b) 6562306a36Sopenharmony_ci{ 6662306a36Sopenharmony_ci if (!V4L2_TYPE_IS_MULTIPLANAR(b->type)) 6762306a36Sopenharmony_ci return 0; 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci /* Is memory for copying plane information present? */ 7062306a36Sopenharmony_ci if (b->m.planes == NULL) { 7162306a36Sopenharmony_ci dprintk(vb->vb2_queue, 1, 7262306a36Sopenharmony_ci "multi-planar buffer passed but planes array not provided\n"); 7362306a36Sopenharmony_ci return -EINVAL; 7462306a36Sopenharmony_ci } 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci if (b->length < vb->num_planes || b->length > VB2_MAX_PLANES) { 7762306a36Sopenharmony_ci dprintk(vb->vb2_queue, 1, 7862306a36Sopenharmony_ci "incorrect planes array length, expected %d, got %d\n", 7962306a36Sopenharmony_ci vb->num_planes, b->length); 8062306a36Sopenharmony_ci return -EINVAL; 8162306a36Sopenharmony_ci } 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci return 0; 8462306a36Sopenharmony_ci} 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_cistatic int __verify_planes_array_core(struct vb2_buffer *vb, const void *pb) 8762306a36Sopenharmony_ci{ 8862306a36Sopenharmony_ci return __verify_planes_array(vb, pb); 8962306a36Sopenharmony_ci} 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci/* 9262306a36Sopenharmony_ci * __verify_length() - Verify that the bytesused value for each plane fits in 9362306a36Sopenharmony_ci * the plane length and that the data offset doesn't exceed the bytesused value. 9462306a36Sopenharmony_ci */ 9562306a36Sopenharmony_cistatic int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b) 9662306a36Sopenharmony_ci{ 9762306a36Sopenharmony_ci unsigned int length; 9862306a36Sopenharmony_ci unsigned int bytesused; 9962306a36Sopenharmony_ci unsigned int plane; 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci if (V4L2_TYPE_IS_CAPTURE(b->type)) 10262306a36Sopenharmony_ci return 0; 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) { 10562306a36Sopenharmony_ci for (plane = 0; plane < vb->num_planes; ++plane) { 10662306a36Sopenharmony_ci length = (b->memory == VB2_MEMORY_USERPTR || 10762306a36Sopenharmony_ci b->memory == VB2_MEMORY_DMABUF) 10862306a36Sopenharmony_ci ? b->m.planes[plane].length 10962306a36Sopenharmony_ci : vb->planes[plane].length; 11062306a36Sopenharmony_ci bytesused = b->m.planes[plane].bytesused 11162306a36Sopenharmony_ci ? b->m.planes[plane].bytesused : length; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci if (b->m.planes[plane].bytesused > length) 11462306a36Sopenharmony_ci return -EINVAL; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci if (b->m.planes[plane].data_offset > 0 && 11762306a36Sopenharmony_ci b->m.planes[plane].data_offset >= bytesused) 11862306a36Sopenharmony_ci return -EINVAL; 11962306a36Sopenharmony_ci } 12062306a36Sopenharmony_ci } else { 12162306a36Sopenharmony_ci length = (b->memory == VB2_MEMORY_USERPTR) 12262306a36Sopenharmony_ci ? b->length : vb->planes[0].length; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci if (b->bytesused > length) 12562306a36Sopenharmony_ci return -EINVAL; 12662306a36Sopenharmony_ci } 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci return 0; 12962306a36Sopenharmony_ci} 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci/* 13262306a36Sopenharmony_ci * __init_vb2_v4l2_buffer() - initialize the vb2_v4l2_buffer struct 13362306a36Sopenharmony_ci */ 13462306a36Sopenharmony_cistatic void __init_vb2_v4l2_buffer(struct vb2_buffer *vb) 13562306a36Sopenharmony_ci{ 13662306a36Sopenharmony_ci struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci vbuf->request_fd = -1; 13962306a36Sopenharmony_ci} 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_cistatic void __copy_timestamp(struct vb2_buffer *vb, const void *pb) 14262306a36Sopenharmony_ci{ 14362306a36Sopenharmony_ci const struct v4l2_buffer *b = pb; 14462306a36Sopenharmony_ci struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 14562306a36Sopenharmony_ci struct vb2_queue *q = vb->vb2_queue; 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci if (q->is_output) { 14862306a36Sopenharmony_ci /* 14962306a36Sopenharmony_ci * For output buffers copy the timestamp if needed, 15062306a36Sopenharmony_ci * and the timecode field and flag if needed. 15162306a36Sopenharmony_ci */ 15262306a36Sopenharmony_ci if (q->copy_timestamp) 15362306a36Sopenharmony_ci vb->timestamp = v4l2_buffer_get_timestamp(b); 15462306a36Sopenharmony_ci vbuf->flags |= b->flags & V4L2_BUF_FLAG_TIMECODE; 15562306a36Sopenharmony_ci if (b->flags & V4L2_BUF_FLAG_TIMECODE) 15662306a36Sopenharmony_ci vbuf->timecode = b->timecode; 15762306a36Sopenharmony_ci } 15862306a36Sopenharmony_ci}; 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_cistatic void vb2_warn_zero_bytesused(struct vb2_buffer *vb) 16162306a36Sopenharmony_ci{ 16262306a36Sopenharmony_ci static bool check_once; 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci if (check_once) 16562306a36Sopenharmony_ci return; 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci check_once = true; 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci pr_warn("use of bytesused == 0 is deprecated and will be removed in the future,\n"); 17062306a36Sopenharmony_ci if (vb->vb2_queue->allow_zero_bytesused) 17162306a36Sopenharmony_ci pr_warn("use VIDIOC_DECODER_CMD(V4L2_DEC_CMD_STOP) instead.\n"); 17262306a36Sopenharmony_ci else 17362306a36Sopenharmony_ci pr_warn("use the actual size instead.\n"); 17462306a36Sopenharmony_ci} 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_cistatic int vb2_fill_vb2_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b) 17762306a36Sopenharmony_ci{ 17862306a36Sopenharmony_ci struct vb2_queue *q = vb->vb2_queue; 17962306a36Sopenharmony_ci struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 18062306a36Sopenharmony_ci struct vb2_plane *planes = vbuf->planes; 18162306a36Sopenharmony_ci unsigned int plane; 18262306a36Sopenharmony_ci int ret; 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci ret = __verify_length(vb, b); 18562306a36Sopenharmony_ci if (ret < 0) { 18662306a36Sopenharmony_ci dprintk(q, 1, "plane parameters verification failed: %d\n", ret); 18762306a36Sopenharmony_ci return ret; 18862306a36Sopenharmony_ci } 18962306a36Sopenharmony_ci if (b->field == V4L2_FIELD_ALTERNATE && q->is_output) { 19062306a36Sopenharmony_ci /* 19162306a36Sopenharmony_ci * If the format's field is ALTERNATE, then the buffer's field 19262306a36Sopenharmony_ci * should be either TOP or BOTTOM, not ALTERNATE since that 19362306a36Sopenharmony_ci * makes no sense. The driver has to know whether the 19462306a36Sopenharmony_ci * buffer represents a top or a bottom field in order to 19562306a36Sopenharmony_ci * program any DMA correctly. Using ALTERNATE is wrong, since 19662306a36Sopenharmony_ci * that just says that it is either a top or a bottom field, 19762306a36Sopenharmony_ci * but not which of the two it is. 19862306a36Sopenharmony_ci */ 19962306a36Sopenharmony_ci dprintk(q, 1, "the field is incorrectly set to ALTERNATE for an output buffer\n"); 20062306a36Sopenharmony_ci return -EINVAL; 20162306a36Sopenharmony_ci } 20262306a36Sopenharmony_ci vbuf->sequence = 0; 20362306a36Sopenharmony_ci vbuf->request_fd = -1; 20462306a36Sopenharmony_ci vbuf->is_held = false; 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) { 20762306a36Sopenharmony_ci switch (b->memory) { 20862306a36Sopenharmony_ci case VB2_MEMORY_USERPTR: 20962306a36Sopenharmony_ci for (plane = 0; plane < vb->num_planes; ++plane) { 21062306a36Sopenharmony_ci planes[plane].m.userptr = 21162306a36Sopenharmony_ci b->m.planes[plane].m.userptr; 21262306a36Sopenharmony_ci planes[plane].length = 21362306a36Sopenharmony_ci b->m.planes[plane].length; 21462306a36Sopenharmony_ci } 21562306a36Sopenharmony_ci break; 21662306a36Sopenharmony_ci case VB2_MEMORY_DMABUF: 21762306a36Sopenharmony_ci for (plane = 0; plane < vb->num_planes; ++plane) { 21862306a36Sopenharmony_ci planes[plane].m.fd = 21962306a36Sopenharmony_ci b->m.planes[plane].m.fd; 22062306a36Sopenharmony_ci planes[plane].length = 22162306a36Sopenharmony_ci b->m.planes[plane].length; 22262306a36Sopenharmony_ci } 22362306a36Sopenharmony_ci break; 22462306a36Sopenharmony_ci default: 22562306a36Sopenharmony_ci for (plane = 0; plane < vb->num_planes; ++plane) { 22662306a36Sopenharmony_ci planes[plane].m.offset = 22762306a36Sopenharmony_ci vb->planes[plane].m.offset; 22862306a36Sopenharmony_ci planes[plane].length = 22962306a36Sopenharmony_ci vb->planes[plane].length; 23062306a36Sopenharmony_ci } 23162306a36Sopenharmony_ci break; 23262306a36Sopenharmony_ci } 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci /* Fill in driver-provided information for OUTPUT types */ 23562306a36Sopenharmony_ci if (V4L2_TYPE_IS_OUTPUT(b->type)) { 23662306a36Sopenharmony_ci /* 23762306a36Sopenharmony_ci * Will have to go up to b->length when API starts 23862306a36Sopenharmony_ci * accepting variable number of planes. 23962306a36Sopenharmony_ci * 24062306a36Sopenharmony_ci * If bytesused == 0 for the output buffer, then fall 24162306a36Sopenharmony_ci * back to the full buffer size. In that case 24262306a36Sopenharmony_ci * userspace clearly never bothered to set it and 24362306a36Sopenharmony_ci * it's a safe assumption that they really meant to 24462306a36Sopenharmony_ci * use the full plane sizes. 24562306a36Sopenharmony_ci * 24662306a36Sopenharmony_ci * Some drivers, e.g. old codec drivers, use bytesused == 0 24762306a36Sopenharmony_ci * as a way to indicate that streaming is finished. 24862306a36Sopenharmony_ci * In that case, the driver should use the 24962306a36Sopenharmony_ci * allow_zero_bytesused flag to keep old userspace 25062306a36Sopenharmony_ci * applications working. 25162306a36Sopenharmony_ci */ 25262306a36Sopenharmony_ci for (plane = 0; plane < vb->num_planes; ++plane) { 25362306a36Sopenharmony_ci struct vb2_plane *pdst = &planes[plane]; 25462306a36Sopenharmony_ci struct v4l2_plane *psrc = &b->m.planes[plane]; 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci if (psrc->bytesused == 0) 25762306a36Sopenharmony_ci vb2_warn_zero_bytesused(vb); 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci if (vb->vb2_queue->allow_zero_bytesused) 26062306a36Sopenharmony_ci pdst->bytesused = psrc->bytesused; 26162306a36Sopenharmony_ci else 26262306a36Sopenharmony_ci pdst->bytesused = psrc->bytesused ? 26362306a36Sopenharmony_ci psrc->bytesused : pdst->length; 26462306a36Sopenharmony_ci pdst->data_offset = psrc->data_offset; 26562306a36Sopenharmony_ci } 26662306a36Sopenharmony_ci } 26762306a36Sopenharmony_ci } else { 26862306a36Sopenharmony_ci /* 26962306a36Sopenharmony_ci * Single-planar buffers do not use planes array, 27062306a36Sopenharmony_ci * so fill in relevant v4l2_buffer struct fields instead. 27162306a36Sopenharmony_ci * In vb2 we use our internal V4l2_planes struct for 27262306a36Sopenharmony_ci * single-planar buffers as well, for simplicity. 27362306a36Sopenharmony_ci * 27462306a36Sopenharmony_ci * If bytesused == 0 for the output buffer, then fall back 27562306a36Sopenharmony_ci * to the full buffer size as that's a sensible default. 27662306a36Sopenharmony_ci * 27762306a36Sopenharmony_ci * Some drivers, e.g. old codec drivers, use bytesused == 0 as 27862306a36Sopenharmony_ci * a way to indicate that streaming is finished. In that case, 27962306a36Sopenharmony_ci * the driver should use the allow_zero_bytesused flag to keep 28062306a36Sopenharmony_ci * old userspace applications working. 28162306a36Sopenharmony_ci */ 28262306a36Sopenharmony_ci switch (b->memory) { 28362306a36Sopenharmony_ci case VB2_MEMORY_USERPTR: 28462306a36Sopenharmony_ci planes[0].m.userptr = b->m.userptr; 28562306a36Sopenharmony_ci planes[0].length = b->length; 28662306a36Sopenharmony_ci break; 28762306a36Sopenharmony_ci case VB2_MEMORY_DMABUF: 28862306a36Sopenharmony_ci planes[0].m.fd = b->m.fd; 28962306a36Sopenharmony_ci planes[0].length = b->length; 29062306a36Sopenharmony_ci break; 29162306a36Sopenharmony_ci default: 29262306a36Sopenharmony_ci planes[0].m.offset = vb->planes[0].m.offset; 29362306a36Sopenharmony_ci planes[0].length = vb->planes[0].length; 29462306a36Sopenharmony_ci break; 29562306a36Sopenharmony_ci } 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci planes[0].data_offset = 0; 29862306a36Sopenharmony_ci if (V4L2_TYPE_IS_OUTPUT(b->type)) { 29962306a36Sopenharmony_ci if (b->bytesused == 0) 30062306a36Sopenharmony_ci vb2_warn_zero_bytesused(vb); 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci if (vb->vb2_queue->allow_zero_bytesused) 30362306a36Sopenharmony_ci planes[0].bytesused = b->bytesused; 30462306a36Sopenharmony_ci else 30562306a36Sopenharmony_ci planes[0].bytesused = b->bytesused ? 30662306a36Sopenharmony_ci b->bytesused : planes[0].length; 30762306a36Sopenharmony_ci } else 30862306a36Sopenharmony_ci planes[0].bytesused = 0; 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci } 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci /* Zero flags that we handle */ 31362306a36Sopenharmony_ci vbuf->flags = b->flags & ~V4L2_BUFFER_MASK_FLAGS; 31462306a36Sopenharmony_ci if (!vb->vb2_queue->copy_timestamp || V4L2_TYPE_IS_CAPTURE(b->type)) { 31562306a36Sopenharmony_ci /* 31662306a36Sopenharmony_ci * Non-COPY timestamps and non-OUTPUT queues will get 31762306a36Sopenharmony_ci * their timestamp and timestamp source flags from the 31862306a36Sopenharmony_ci * queue. 31962306a36Sopenharmony_ci */ 32062306a36Sopenharmony_ci vbuf->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; 32162306a36Sopenharmony_ci } 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci if (V4L2_TYPE_IS_OUTPUT(b->type)) { 32462306a36Sopenharmony_ci /* 32562306a36Sopenharmony_ci * For output buffers mask out the timecode flag: 32662306a36Sopenharmony_ci * this will be handled later in vb2_qbuf(). 32762306a36Sopenharmony_ci * The 'field' is valid metadata for this output buffer 32862306a36Sopenharmony_ci * and so that needs to be copied here. 32962306a36Sopenharmony_ci */ 33062306a36Sopenharmony_ci vbuf->flags &= ~V4L2_BUF_FLAG_TIMECODE; 33162306a36Sopenharmony_ci vbuf->field = b->field; 33262306a36Sopenharmony_ci if (!(q->subsystem_flags & VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF)) 33362306a36Sopenharmony_ci vbuf->flags &= ~V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF; 33462306a36Sopenharmony_ci } else { 33562306a36Sopenharmony_ci /* Zero any output buffer flags as this is a capture buffer */ 33662306a36Sopenharmony_ci vbuf->flags &= ~V4L2_BUFFER_OUT_FLAGS; 33762306a36Sopenharmony_ci /* Zero last flag, this is a signal from driver to userspace */ 33862306a36Sopenharmony_ci vbuf->flags &= ~V4L2_BUF_FLAG_LAST; 33962306a36Sopenharmony_ci } 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci return 0; 34262306a36Sopenharmony_ci} 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_cistatic void set_buffer_cache_hints(struct vb2_queue *q, 34562306a36Sopenharmony_ci struct vb2_buffer *vb, 34662306a36Sopenharmony_ci struct v4l2_buffer *b) 34762306a36Sopenharmony_ci{ 34862306a36Sopenharmony_ci if (!vb2_queue_allows_cache_hints(q)) { 34962306a36Sopenharmony_ci /* 35062306a36Sopenharmony_ci * Clear buffer cache flags if queue does not support user 35162306a36Sopenharmony_ci * space hints. That's to indicate to userspace that these 35262306a36Sopenharmony_ci * flags won't work. 35362306a36Sopenharmony_ci */ 35462306a36Sopenharmony_ci b->flags &= ~V4L2_BUF_FLAG_NO_CACHE_INVALIDATE; 35562306a36Sopenharmony_ci b->flags &= ~V4L2_BUF_FLAG_NO_CACHE_CLEAN; 35662306a36Sopenharmony_ci return; 35762306a36Sopenharmony_ci } 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci if (b->flags & V4L2_BUF_FLAG_NO_CACHE_INVALIDATE) 36062306a36Sopenharmony_ci vb->skip_cache_sync_on_finish = 1; 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci if (b->flags & V4L2_BUF_FLAG_NO_CACHE_CLEAN) 36362306a36Sopenharmony_ci vb->skip_cache_sync_on_prepare = 1; 36462306a36Sopenharmony_ci} 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_cistatic int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *mdev, 36762306a36Sopenharmony_ci struct v4l2_buffer *b, bool is_prepare, 36862306a36Sopenharmony_ci struct media_request **p_req) 36962306a36Sopenharmony_ci{ 37062306a36Sopenharmony_ci const char *opname = is_prepare ? "prepare_buf" : "qbuf"; 37162306a36Sopenharmony_ci struct media_request *req; 37262306a36Sopenharmony_ci struct vb2_v4l2_buffer *vbuf; 37362306a36Sopenharmony_ci struct vb2_buffer *vb; 37462306a36Sopenharmony_ci int ret; 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci if (b->type != q->type) { 37762306a36Sopenharmony_ci dprintk(q, 1, "%s: invalid buffer type\n", opname); 37862306a36Sopenharmony_ci return -EINVAL; 37962306a36Sopenharmony_ci } 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ci if (b->index >= q->num_buffers) { 38262306a36Sopenharmony_ci dprintk(q, 1, "%s: buffer index out of range\n", opname); 38362306a36Sopenharmony_ci return -EINVAL; 38462306a36Sopenharmony_ci } 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci if (q->bufs[b->index] == NULL) { 38762306a36Sopenharmony_ci /* Should never happen */ 38862306a36Sopenharmony_ci dprintk(q, 1, "%s: buffer is NULL\n", opname); 38962306a36Sopenharmony_ci return -EINVAL; 39062306a36Sopenharmony_ci } 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci if (b->memory != q->memory) { 39362306a36Sopenharmony_ci dprintk(q, 1, "%s: invalid memory type\n", opname); 39462306a36Sopenharmony_ci return -EINVAL; 39562306a36Sopenharmony_ci } 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci vb = q->bufs[b->index]; 39862306a36Sopenharmony_ci vbuf = to_vb2_v4l2_buffer(vb); 39962306a36Sopenharmony_ci ret = __verify_planes_array(vb, b); 40062306a36Sopenharmony_ci if (ret) 40162306a36Sopenharmony_ci return ret; 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci if (!is_prepare && (b->flags & V4L2_BUF_FLAG_REQUEST_FD) && 40462306a36Sopenharmony_ci vb->state != VB2_BUF_STATE_DEQUEUED) { 40562306a36Sopenharmony_ci dprintk(q, 1, "%s: buffer is not in dequeued state\n", opname); 40662306a36Sopenharmony_ci return -EINVAL; 40762306a36Sopenharmony_ci } 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci if (!vb->prepared) { 41062306a36Sopenharmony_ci set_buffer_cache_hints(q, vb, b); 41162306a36Sopenharmony_ci /* Copy relevant information provided by the userspace */ 41262306a36Sopenharmony_ci memset(vbuf->planes, 0, 41362306a36Sopenharmony_ci sizeof(vbuf->planes[0]) * vb->num_planes); 41462306a36Sopenharmony_ci ret = vb2_fill_vb2_v4l2_buffer(vb, b); 41562306a36Sopenharmony_ci if (ret) 41662306a36Sopenharmony_ci return ret; 41762306a36Sopenharmony_ci } 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci if (is_prepare) 42062306a36Sopenharmony_ci return 0; 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci if (!(b->flags & V4L2_BUF_FLAG_REQUEST_FD)) { 42362306a36Sopenharmony_ci if (q->requires_requests) { 42462306a36Sopenharmony_ci dprintk(q, 1, "%s: queue requires requests\n", opname); 42562306a36Sopenharmony_ci return -EBADR; 42662306a36Sopenharmony_ci } 42762306a36Sopenharmony_ci if (q->uses_requests) { 42862306a36Sopenharmony_ci dprintk(q, 1, "%s: queue uses requests\n", opname); 42962306a36Sopenharmony_ci return -EBUSY; 43062306a36Sopenharmony_ci } 43162306a36Sopenharmony_ci return 0; 43262306a36Sopenharmony_ci } else if (!q->supports_requests) { 43362306a36Sopenharmony_ci dprintk(q, 1, "%s: queue does not support requests\n", opname); 43462306a36Sopenharmony_ci return -EBADR; 43562306a36Sopenharmony_ci } else if (q->uses_qbuf) { 43662306a36Sopenharmony_ci dprintk(q, 1, "%s: queue does not use requests\n", opname); 43762306a36Sopenharmony_ci return -EBUSY; 43862306a36Sopenharmony_ci } 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci /* 44162306a36Sopenharmony_ci * For proper locking when queueing a request you need to be able 44262306a36Sopenharmony_ci * to lock access to the vb2 queue, so check that there is a lock 44362306a36Sopenharmony_ci * that we can use. In addition p_req must be non-NULL. 44462306a36Sopenharmony_ci */ 44562306a36Sopenharmony_ci if (WARN_ON(!q->lock || !p_req)) 44662306a36Sopenharmony_ci return -EINVAL; 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci /* 44962306a36Sopenharmony_ci * Make sure this op is implemented by the driver. It's easy to forget 45062306a36Sopenharmony_ci * this callback, but is it important when canceling a buffer in a 45162306a36Sopenharmony_ci * queued request. 45262306a36Sopenharmony_ci */ 45362306a36Sopenharmony_ci if (WARN_ON(!q->ops->buf_request_complete)) 45462306a36Sopenharmony_ci return -EINVAL; 45562306a36Sopenharmony_ci /* 45662306a36Sopenharmony_ci * Make sure this op is implemented by the driver for the output queue. 45762306a36Sopenharmony_ci * It's easy to forget this callback, but is it important to correctly 45862306a36Sopenharmony_ci * validate the 'field' value at QBUF time. 45962306a36Sopenharmony_ci */ 46062306a36Sopenharmony_ci if (WARN_ON((q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT || 46162306a36Sopenharmony_ci q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) && 46262306a36Sopenharmony_ci !q->ops->buf_out_validate)) 46362306a36Sopenharmony_ci return -EINVAL; 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ci req = media_request_get_by_fd(mdev, b->request_fd); 46662306a36Sopenharmony_ci if (IS_ERR(req)) { 46762306a36Sopenharmony_ci dprintk(q, 1, "%s: invalid request_fd\n", opname); 46862306a36Sopenharmony_ci return PTR_ERR(req); 46962306a36Sopenharmony_ci } 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci /* 47262306a36Sopenharmony_ci * Early sanity check. This is checked again when the buffer 47362306a36Sopenharmony_ci * is bound to the request in vb2_core_qbuf(). 47462306a36Sopenharmony_ci */ 47562306a36Sopenharmony_ci if (req->state != MEDIA_REQUEST_STATE_IDLE && 47662306a36Sopenharmony_ci req->state != MEDIA_REQUEST_STATE_UPDATING) { 47762306a36Sopenharmony_ci dprintk(q, 1, "%s: request is not idle\n", opname); 47862306a36Sopenharmony_ci media_request_put(req); 47962306a36Sopenharmony_ci return -EBUSY; 48062306a36Sopenharmony_ci } 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci *p_req = req; 48362306a36Sopenharmony_ci vbuf->request_fd = b->request_fd; 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ci return 0; 48662306a36Sopenharmony_ci} 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_ci/* 48962306a36Sopenharmony_ci * __fill_v4l2_buffer() - fill in a struct v4l2_buffer with information to be 49062306a36Sopenharmony_ci * returned to userspace 49162306a36Sopenharmony_ci */ 49262306a36Sopenharmony_cistatic void __fill_v4l2_buffer(struct vb2_buffer *vb, void *pb) 49362306a36Sopenharmony_ci{ 49462306a36Sopenharmony_ci struct v4l2_buffer *b = pb; 49562306a36Sopenharmony_ci struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 49662306a36Sopenharmony_ci struct vb2_queue *q = vb->vb2_queue; 49762306a36Sopenharmony_ci unsigned int plane; 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci /* Copy back data such as timestamp, flags, etc. */ 50062306a36Sopenharmony_ci b->index = vb->index; 50162306a36Sopenharmony_ci b->type = vb->type; 50262306a36Sopenharmony_ci b->memory = vb->memory; 50362306a36Sopenharmony_ci b->bytesused = 0; 50462306a36Sopenharmony_ci 50562306a36Sopenharmony_ci b->flags = vbuf->flags; 50662306a36Sopenharmony_ci b->field = vbuf->field; 50762306a36Sopenharmony_ci v4l2_buffer_set_timestamp(b, vb->timestamp); 50862306a36Sopenharmony_ci b->timecode = vbuf->timecode; 50962306a36Sopenharmony_ci b->sequence = vbuf->sequence; 51062306a36Sopenharmony_ci b->reserved2 = 0; 51162306a36Sopenharmony_ci b->request_fd = 0; 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ci if (q->is_multiplanar) { 51462306a36Sopenharmony_ci /* 51562306a36Sopenharmony_ci * Fill in plane-related data if userspace provided an array 51662306a36Sopenharmony_ci * for it. The caller has already verified memory and size. 51762306a36Sopenharmony_ci */ 51862306a36Sopenharmony_ci b->length = vb->num_planes; 51962306a36Sopenharmony_ci for (plane = 0; plane < vb->num_planes; ++plane) { 52062306a36Sopenharmony_ci struct v4l2_plane *pdst = &b->m.planes[plane]; 52162306a36Sopenharmony_ci struct vb2_plane *psrc = &vb->planes[plane]; 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_ci pdst->bytesused = psrc->bytesused; 52462306a36Sopenharmony_ci pdst->length = psrc->length; 52562306a36Sopenharmony_ci if (q->memory == VB2_MEMORY_MMAP) 52662306a36Sopenharmony_ci pdst->m.mem_offset = psrc->m.offset; 52762306a36Sopenharmony_ci else if (q->memory == VB2_MEMORY_USERPTR) 52862306a36Sopenharmony_ci pdst->m.userptr = psrc->m.userptr; 52962306a36Sopenharmony_ci else if (q->memory == VB2_MEMORY_DMABUF) 53062306a36Sopenharmony_ci pdst->m.fd = psrc->m.fd; 53162306a36Sopenharmony_ci pdst->data_offset = psrc->data_offset; 53262306a36Sopenharmony_ci memset(pdst->reserved, 0, sizeof(pdst->reserved)); 53362306a36Sopenharmony_ci } 53462306a36Sopenharmony_ci } else { 53562306a36Sopenharmony_ci /* 53662306a36Sopenharmony_ci * We use length and offset in v4l2_planes array even for 53762306a36Sopenharmony_ci * single-planar buffers, but userspace does not. 53862306a36Sopenharmony_ci */ 53962306a36Sopenharmony_ci b->length = vb->planes[0].length; 54062306a36Sopenharmony_ci b->bytesused = vb->planes[0].bytesused; 54162306a36Sopenharmony_ci if (q->memory == VB2_MEMORY_MMAP) 54262306a36Sopenharmony_ci b->m.offset = vb->planes[0].m.offset; 54362306a36Sopenharmony_ci else if (q->memory == VB2_MEMORY_USERPTR) 54462306a36Sopenharmony_ci b->m.userptr = vb->planes[0].m.userptr; 54562306a36Sopenharmony_ci else if (q->memory == VB2_MEMORY_DMABUF) 54662306a36Sopenharmony_ci b->m.fd = vb->planes[0].m.fd; 54762306a36Sopenharmony_ci } 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_ci /* 55062306a36Sopenharmony_ci * Clear any buffer state related flags. 55162306a36Sopenharmony_ci */ 55262306a36Sopenharmony_ci b->flags &= ~V4L2_BUFFER_MASK_FLAGS; 55362306a36Sopenharmony_ci b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK; 55462306a36Sopenharmony_ci if (!q->copy_timestamp) { 55562306a36Sopenharmony_ci /* 55662306a36Sopenharmony_ci * For non-COPY timestamps, drop timestamp source bits 55762306a36Sopenharmony_ci * and obtain the timestamp source from the queue. 55862306a36Sopenharmony_ci */ 55962306a36Sopenharmony_ci b->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK; 56062306a36Sopenharmony_ci b->flags |= q->timestamp_flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK; 56162306a36Sopenharmony_ci } 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci switch (vb->state) { 56462306a36Sopenharmony_ci case VB2_BUF_STATE_QUEUED: 56562306a36Sopenharmony_ci case VB2_BUF_STATE_ACTIVE: 56662306a36Sopenharmony_ci b->flags |= V4L2_BUF_FLAG_QUEUED; 56762306a36Sopenharmony_ci break; 56862306a36Sopenharmony_ci case VB2_BUF_STATE_IN_REQUEST: 56962306a36Sopenharmony_ci b->flags |= V4L2_BUF_FLAG_IN_REQUEST; 57062306a36Sopenharmony_ci break; 57162306a36Sopenharmony_ci case VB2_BUF_STATE_ERROR: 57262306a36Sopenharmony_ci b->flags |= V4L2_BUF_FLAG_ERROR; 57362306a36Sopenharmony_ci fallthrough; 57462306a36Sopenharmony_ci case VB2_BUF_STATE_DONE: 57562306a36Sopenharmony_ci b->flags |= V4L2_BUF_FLAG_DONE; 57662306a36Sopenharmony_ci break; 57762306a36Sopenharmony_ci case VB2_BUF_STATE_PREPARING: 57862306a36Sopenharmony_ci case VB2_BUF_STATE_DEQUEUED: 57962306a36Sopenharmony_ci /* nothing */ 58062306a36Sopenharmony_ci break; 58162306a36Sopenharmony_ci } 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_ci if ((vb->state == VB2_BUF_STATE_DEQUEUED || 58462306a36Sopenharmony_ci vb->state == VB2_BUF_STATE_IN_REQUEST) && 58562306a36Sopenharmony_ci vb->synced && vb->prepared) 58662306a36Sopenharmony_ci b->flags |= V4L2_BUF_FLAG_PREPARED; 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci if (vb2_buffer_in_use(q, vb)) 58962306a36Sopenharmony_ci b->flags |= V4L2_BUF_FLAG_MAPPED; 59062306a36Sopenharmony_ci if (vbuf->request_fd >= 0) { 59162306a36Sopenharmony_ci b->flags |= V4L2_BUF_FLAG_REQUEST_FD; 59262306a36Sopenharmony_ci b->request_fd = vbuf->request_fd; 59362306a36Sopenharmony_ci } 59462306a36Sopenharmony_ci} 59562306a36Sopenharmony_ci 59662306a36Sopenharmony_ci/* 59762306a36Sopenharmony_ci * __fill_vb2_buffer() - fill a vb2_buffer with information provided in a 59862306a36Sopenharmony_ci * v4l2_buffer by the userspace. It also verifies that struct 59962306a36Sopenharmony_ci * v4l2_buffer has a valid number of planes. 60062306a36Sopenharmony_ci */ 60162306a36Sopenharmony_cistatic int __fill_vb2_buffer(struct vb2_buffer *vb, struct vb2_plane *planes) 60262306a36Sopenharmony_ci{ 60362306a36Sopenharmony_ci struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 60462306a36Sopenharmony_ci unsigned int plane; 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_ci if (!vb->vb2_queue->copy_timestamp) 60762306a36Sopenharmony_ci vb->timestamp = 0; 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_ci for (plane = 0; plane < vb->num_planes; ++plane) { 61062306a36Sopenharmony_ci if (vb->vb2_queue->memory != VB2_MEMORY_MMAP) { 61162306a36Sopenharmony_ci planes[plane].m = vbuf->planes[plane].m; 61262306a36Sopenharmony_ci planes[plane].length = vbuf->planes[plane].length; 61362306a36Sopenharmony_ci } 61462306a36Sopenharmony_ci planes[plane].bytesused = vbuf->planes[plane].bytesused; 61562306a36Sopenharmony_ci planes[plane].data_offset = vbuf->planes[plane].data_offset; 61662306a36Sopenharmony_ci } 61762306a36Sopenharmony_ci return 0; 61862306a36Sopenharmony_ci} 61962306a36Sopenharmony_ci 62062306a36Sopenharmony_cistatic const struct vb2_buf_ops v4l2_buf_ops = { 62162306a36Sopenharmony_ci .verify_planes_array = __verify_planes_array_core, 62262306a36Sopenharmony_ci .init_buffer = __init_vb2_v4l2_buffer, 62362306a36Sopenharmony_ci .fill_user_buffer = __fill_v4l2_buffer, 62462306a36Sopenharmony_ci .fill_vb2_buffer = __fill_vb2_buffer, 62562306a36Sopenharmony_ci .copy_timestamp = __copy_timestamp, 62662306a36Sopenharmony_ci}; 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_cistruct vb2_buffer *vb2_find_buffer(struct vb2_queue *q, u64 timestamp) 62962306a36Sopenharmony_ci{ 63062306a36Sopenharmony_ci unsigned int i; 63162306a36Sopenharmony_ci 63262306a36Sopenharmony_ci for (i = 0; i < q->num_buffers; i++) 63362306a36Sopenharmony_ci if (q->bufs[i]->copied_timestamp && 63462306a36Sopenharmony_ci q->bufs[i]->timestamp == timestamp) 63562306a36Sopenharmony_ci return vb2_get_buffer(q, i); 63662306a36Sopenharmony_ci return NULL; 63762306a36Sopenharmony_ci} 63862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(vb2_find_buffer); 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_ci/* 64162306a36Sopenharmony_ci * vb2_querybuf() - query video buffer information 64262306a36Sopenharmony_ci * @q: vb2 queue 64362306a36Sopenharmony_ci * @b: buffer struct passed from userspace to vidioc_querybuf handler 64462306a36Sopenharmony_ci * in driver 64562306a36Sopenharmony_ci * 64662306a36Sopenharmony_ci * Should be called from vidioc_querybuf ioctl handler in driver. 64762306a36Sopenharmony_ci * This function will verify the passed v4l2_buffer structure and fill the 64862306a36Sopenharmony_ci * relevant information for the userspace. 64962306a36Sopenharmony_ci * 65062306a36Sopenharmony_ci * The return values from this function are intended to be directly returned 65162306a36Sopenharmony_ci * from vidioc_querybuf handler in driver. 65262306a36Sopenharmony_ci */ 65362306a36Sopenharmony_ciint vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b) 65462306a36Sopenharmony_ci{ 65562306a36Sopenharmony_ci struct vb2_buffer *vb; 65662306a36Sopenharmony_ci int ret; 65762306a36Sopenharmony_ci 65862306a36Sopenharmony_ci if (b->type != q->type) { 65962306a36Sopenharmony_ci dprintk(q, 1, "wrong buffer type\n"); 66062306a36Sopenharmony_ci return -EINVAL; 66162306a36Sopenharmony_ci } 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_ci if (b->index >= q->num_buffers) { 66462306a36Sopenharmony_ci dprintk(q, 1, "buffer index out of range\n"); 66562306a36Sopenharmony_ci return -EINVAL; 66662306a36Sopenharmony_ci } 66762306a36Sopenharmony_ci vb = q->bufs[b->index]; 66862306a36Sopenharmony_ci ret = __verify_planes_array(vb, b); 66962306a36Sopenharmony_ci if (!ret) 67062306a36Sopenharmony_ci vb2_core_querybuf(q, b->index, b); 67162306a36Sopenharmony_ci return ret; 67262306a36Sopenharmony_ci} 67362306a36Sopenharmony_ciEXPORT_SYMBOL(vb2_querybuf); 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_cistatic void fill_buf_caps(struct vb2_queue *q, u32 *caps) 67662306a36Sopenharmony_ci{ 67762306a36Sopenharmony_ci *caps = V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS; 67862306a36Sopenharmony_ci if (q->io_modes & VB2_MMAP) 67962306a36Sopenharmony_ci *caps |= V4L2_BUF_CAP_SUPPORTS_MMAP; 68062306a36Sopenharmony_ci if (q->io_modes & VB2_USERPTR) 68162306a36Sopenharmony_ci *caps |= V4L2_BUF_CAP_SUPPORTS_USERPTR; 68262306a36Sopenharmony_ci if (q->io_modes & VB2_DMABUF) 68362306a36Sopenharmony_ci *caps |= V4L2_BUF_CAP_SUPPORTS_DMABUF; 68462306a36Sopenharmony_ci if (q->subsystem_flags & VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF) 68562306a36Sopenharmony_ci *caps |= V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF; 68662306a36Sopenharmony_ci if (q->allow_cache_hints && q->io_modes & VB2_MMAP) 68762306a36Sopenharmony_ci *caps |= V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS; 68862306a36Sopenharmony_ci#ifdef CONFIG_MEDIA_CONTROLLER_REQUEST_API 68962306a36Sopenharmony_ci if (q->supports_requests) 69062306a36Sopenharmony_ci *caps |= V4L2_BUF_CAP_SUPPORTS_REQUESTS; 69162306a36Sopenharmony_ci#endif 69262306a36Sopenharmony_ci} 69362306a36Sopenharmony_ci 69462306a36Sopenharmony_cistatic void validate_memory_flags(struct vb2_queue *q, 69562306a36Sopenharmony_ci int memory, 69662306a36Sopenharmony_ci u32 *flags) 69762306a36Sopenharmony_ci{ 69862306a36Sopenharmony_ci if (!q->allow_cache_hints || memory != V4L2_MEMORY_MMAP) { 69962306a36Sopenharmony_ci /* 70062306a36Sopenharmony_ci * This needs to clear V4L2_MEMORY_FLAG_NON_COHERENT only, 70162306a36Sopenharmony_ci * but in order to avoid bugs we zero out all bits. 70262306a36Sopenharmony_ci */ 70362306a36Sopenharmony_ci *flags = 0; 70462306a36Sopenharmony_ci } else { 70562306a36Sopenharmony_ci /* Clear all unknown flags. */ 70662306a36Sopenharmony_ci *flags &= V4L2_MEMORY_FLAG_NON_COHERENT; 70762306a36Sopenharmony_ci } 70862306a36Sopenharmony_ci} 70962306a36Sopenharmony_ci 71062306a36Sopenharmony_ciint vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req) 71162306a36Sopenharmony_ci{ 71262306a36Sopenharmony_ci int ret = vb2_verify_memory_type(q, req->memory, req->type); 71362306a36Sopenharmony_ci u32 flags = req->flags; 71462306a36Sopenharmony_ci 71562306a36Sopenharmony_ci fill_buf_caps(q, &req->capabilities); 71662306a36Sopenharmony_ci validate_memory_flags(q, req->memory, &flags); 71762306a36Sopenharmony_ci req->flags = flags; 71862306a36Sopenharmony_ci return ret ? ret : vb2_core_reqbufs(q, req->memory, 71962306a36Sopenharmony_ci req->flags, &req->count); 72062306a36Sopenharmony_ci} 72162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(vb2_reqbufs); 72262306a36Sopenharmony_ci 72362306a36Sopenharmony_ciint vb2_prepare_buf(struct vb2_queue *q, struct media_device *mdev, 72462306a36Sopenharmony_ci struct v4l2_buffer *b) 72562306a36Sopenharmony_ci{ 72662306a36Sopenharmony_ci int ret; 72762306a36Sopenharmony_ci 72862306a36Sopenharmony_ci if (vb2_fileio_is_active(q)) { 72962306a36Sopenharmony_ci dprintk(q, 1, "file io in progress\n"); 73062306a36Sopenharmony_ci return -EBUSY; 73162306a36Sopenharmony_ci } 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_ci if (b->flags & V4L2_BUF_FLAG_REQUEST_FD) 73462306a36Sopenharmony_ci return -EINVAL; 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_ci ret = vb2_queue_or_prepare_buf(q, mdev, b, true, NULL); 73762306a36Sopenharmony_ci 73862306a36Sopenharmony_ci return ret ? ret : vb2_core_prepare_buf(q, b->index, b); 73962306a36Sopenharmony_ci} 74062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(vb2_prepare_buf); 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_ciint vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create) 74362306a36Sopenharmony_ci{ 74462306a36Sopenharmony_ci unsigned requested_planes = 1; 74562306a36Sopenharmony_ci unsigned requested_sizes[VIDEO_MAX_PLANES]; 74662306a36Sopenharmony_ci struct v4l2_format *f = &create->format; 74762306a36Sopenharmony_ci int ret = vb2_verify_memory_type(q, create->memory, f->type); 74862306a36Sopenharmony_ci unsigned i; 74962306a36Sopenharmony_ci 75062306a36Sopenharmony_ci fill_buf_caps(q, &create->capabilities); 75162306a36Sopenharmony_ci validate_memory_flags(q, create->memory, &create->flags); 75262306a36Sopenharmony_ci create->index = q->num_buffers; 75362306a36Sopenharmony_ci if (create->count == 0) 75462306a36Sopenharmony_ci return ret != -EBUSY ? ret : 0; 75562306a36Sopenharmony_ci 75662306a36Sopenharmony_ci switch (f->type) { 75762306a36Sopenharmony_ci case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: 75862306a36Sopenharmony_ci case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: 75962306a36Sopenharmony_ci requested_planes = f->fmt.pix_mp.num_planes; 76062306a36Sopenharmony_ci if (requested_planes == 0 || 76162306a36Sopenharmony_ci requested_planes > VIDEO_MAX_PLANES) 76262306a36Sopenharmony_ci return -EINVAL; 76362306a36Sopenharmony_ci for (i = 0; i < requested_planes; i++) 76462306a36Sopenharmony_ci requested_sizes[i] = 76562306a36Sopenharmony_ci f->fmt.pix_mp.plane_fmt[i].sizeimage; 76662306a36Sopenharmony_ci break; 76762306a36Sopenharmony_ci case V4L2_BUF_TYPE_VIDEO_CAPTURE: 76862306a36Sopenharmony_ci case V4L2_BUF_TYPE_VIDEO_OUTPUT: 76962306a36Sopenharmony_ci requested_sizes[0] = f->fmt.pix.sizeimage; 77062306a36Sopenharmony_ci break; 77162306a36Sopenharmony_ci case V4L2_BUF_TYPE_VBI_CAPTURE: 77262306a36Sopenharmony_ci case V4L2_BUF_TYPE_VBI_OUTPUT: 77362306a36Sopenharmony_ci requested_sizes[0] = f->fmt.vbi.samples_per_line * 77462306a36Sopenharmony_ci (f->fmt.vbi.count[0] + f->fmt.vbi.count[1]); 77562306a36Sopenharmony_ci break; 77662306a36Sopenharmony_ci case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: 77762306a36Sopenharmony_ci case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: 77862306a36Sopenharmony_ci requested_sizes[0] = f->fmt.sliced.io_size; 77962306a36Sopenharmony_ci break; 78062306a36Sopenharmony_ci case V4L2_BUF_TYPE_SDR_CAPTURE: 78162306a36Sopenharmony_ci case V4L2_BUF_TYPE_SDR_OUTPUT: 78262306a36Sopenharmony_ci requested_sizes[0] = f->fmt.sdr.buffersize; 78362306a36Sopenharmony_ci break; 78462306a36Sopenharmony_ci case V4L2_BUF_TYPE_META_CAPTURE: 78562306a36Sopenharmony_ci case V4L2_BUF_TYPE_META_OUTPUT: 78662306a36Sopenharmony_ci requested_sizes[0] = f->fmt.meta.buffersize; 78762306a36Sopenharmony_ci break; 78862306a36Sopenharmony_ci default: 78962306a36Sopenharmony_ci return -EINVAL; 79062306a36Sopenharmony_ci } 79162306a36Sopenharmony_ci for (i = 0; i < requested_planes; i++) 79262306a36Sopenharmony_ci if (requested_sizes[i] == 0) 79362306a36Sopenharmony_ci return -EINVAL; 79462306a36Sopenharmony_ci return ret ? ret : vb2_core_create_bufs(q, create->memory, 79562306a36Sopenharmony_ci create->flags, 79662306a36Sopenharmony_ci &create->count, 79762306a36Sopenharmony_ci requested_planes, 79862306a36Sopenharmony_ci requested_sizes); 79962306a36Sopenharmony_ci} 80062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(vb2_create_bufs); 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_ciint vb2_qbuf(struct vb2_queue *q, struct media_device *mdev, 80362306a36Sopenharmony_ci struct v4l2_buffer *b) 80462306a36Sopenharmony_ci{ 80562306a36Sopenharmony_ci struct media_request *req = NULL; 80662306a36Sopenharmony_ci int ret; 80762306a36Sopenharmony_ci 80862306a36Sopenharmony_ci if (vb2_fileio_is_active(q)) { 80962306a36Sopenharmony_ci dprintk(q, 1, "file io in progress\n"); 81062306a36Sopenharmony_ci return -EBUSY; 81162306a36Sopenharmony_ci } 81262306a36Sopenharmony_ci 81362306a36Sopenharmony_ci ret = vb2_queue_or_prepare_buf(q, mdev, b, false, &req); 81462306a36Sopenharmony_ci if (ret) 81562306a36Sopenharmony_ci return ret; 81662306a36Sopenharmony_ci ret = vb2_core_qbuf(q, b->index, b, req); 81762306a36Sopenharmony_ci if (req) 81862306a36Sopenharmony_ci media_request_put(req); 81962306a36Sopenharmony_ci return ret; 82062306a36Sopenharmony_ci} 82162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(vb2_qbuf); 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_ciint vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking) 82462306a36Sopenharmony_ci{ 82562306a36Sopenharmony_ci int ret; 82662306a36Sopenharmony_ci 82762306a36Sopenharmony_ci if (vb2_fileio_is_active(q)) { 82862306a36Sopenharmony_ci dprintk(q, 1, "file io in progress\n"); 82962306a36Sopenharmony_ci return -EBUSY; 83062306a36Sopenharmony_ci } 83162306a36Sopenharmony_ci 83262306a36Sopenharmony_ci if (b->type != q->type) { 83362306a36Sopenharmony_ci dprintk(q, 1, "invalid buffer type\n"); 83462306a36Sopenharmony_ci return -EINVAL; 83562306a36Sopenharmony_ci } 83662306a36Sopenharmony_ci 83762306a36Sopenharmony_ci ret = vb2_core_dqbuf(q, NULL, b, nonblocking); 83862306a36Sopenharmony_ci 83962306a36Sopenharmony_ci if (!q->is_output && 84062306a36Sopenharmony_ci b->flags & V4L2_BUF_FLAG_DONE && 84162306a36Sopenharmony_ci b->flags & V4L2_BUF_FLAG_LAST) 84262306a36Sopenharmony_ci q->last_buffer_dequeued = true; 84362306a36Sopenharmony_ci 84462306a36Sopenharmony_ci /* 84562306a36Sopenharmony_ci * After calling the VIDIOC_DQBUF V4L2_BUF_FLAG_DONE must be 84662306a36Sopenharmony_ci * cleared. 84762306a36Sopenharmony_ci */ 84862306a36Sopenharmony_ci b->flags &= ~V4L2_BUF_FLAG_DONE; 84962306a36Sopenharmony_ci 85062306a36Sopenharmony_ci return ret; 85162306a36Sopenharmony_ci} 85262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(vb2_dqbuf); 85362306a36Sopenharmony_ci 85462306a36Sopenharmony_ciint vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type) 85562306a36Sopenharmony_ci{ 85662306a36Sopenharmony_ci if (vb2_fileio_is_active(q)) { 85762306a36Sopenharmony_ci dprintk(q, 1, "file io in progress\n"); 85862306a36Sopenharmony_ci return -EBUSY; 85962306a36Sopenharmony_ci } 86062306a36Sopenharmony_ci return vb2_core_streamon(q, type); 86162306a36Sopenharmony_ci} 86262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(vb2_streamon); 86362306a36Sopenharmony_ci 86462306a36Sopenharmony_ciint vb2_streamoff(struct vb2_queue *q, enum v4l2_buf_type type) 86562306a36Sopenharmony_ci{ 86662306a36Sopenharmony_ci if (vb2_fileio_is_active(q)) { 86762306a36Sopenharmony_ci dprintk(q, 1, "file io in progress\n"); 86862306a36Sopenharmony_ci return -EBUSY; 86962306a36Sopenharmony_ci } 87062306a36Sopenharmony_ci return vb2_core_streamoff(q, type); 87162306a36Sopenharmony_ci} 87262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(vb2_streamoff); 87362306a36Sopenharmony_ci 87462306a36Sopenharmony_ciint vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb) 87562306a36Sopenharmony_ci{ 87662306a36Sopenharmony_ci return vb2_core_expbuf(q, &eb->fd, eb->type, eb->index, 87762306a36Sopenharmony_ci eb->plane, eb->flags); 87862306a36Sopenharmony_ci} 87962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(vb2_expbuf); 88062306a36Sopenharmony_ci 88162306a36Sopenharmony_ciint vb2_queue_init_name(struct vb2_queue *q, const char *name) 88262306a36Sopenharmony_ci{ 88362306a36Sopenharmony_ci /* 88462306a36Sopenharmony_ci * Sanity check 88562306a36Sopenharmony_ci */ 88662306a36Sopenharmony_ci if (WARN_ON(!q) || 88762306a36Sopenharmony_ci WARN_ON(q->timestamp_flags & 88862306a36Sopenharmony_ci ~(V4L2_BUF_FLAG_TIMESTAMP_MASK | 88962306a36Sopenharmony_ci V4L2_BUF_FLAG_TSTAMP_SRC_MASK))) 89062306a36Sopenharmony_ci return -EINVAL; 89162306a36Sopenharmony_ci 89262306a36Sopenharmony_ci /* Warn that the driver should choose an appropriate timestamp type */ 89362306a36Sopenharmony_ci WARN_ON((q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) == 89462306a36Sopenharmony_ci V4L2_BUF_FLAG_TIMESTAMP_UNKNOWN); 89562306a36Sopenharmony_ci 89662306a36Sopenharmony_ci /* Warn that vb2_memory should match with v4l2_memory */ 89762306a36Sopenharmony_ci if (WARN_ON(VB2_MEMORY_MMAP != (int)V4L2_MEMORY_MMAP) 89862306a36Sopenharmony_ci || WARN_ON(VB2_MEMORY_USERPTR != (int)V4L2_MEMORY_USERPTR) 89962306a36Sopenharmony_ci || WARN_ON(VB2_MEMORY_DMABUF != (int)V4L2_MEMORY_DMABUF)) 90062306a36Sopenharmony_ci return -EINVAL; 90162306a36Sopenharmony_ci 90262306a36Sopenharmony_ci if (q->buf_struct_size == 0) 90362306a36Sopenharmony_ci q->buf_struct_size = sizeof(struct vb2_v4l2_buffer); 90462306a36Sopenharmony_ci 90562306a36Sopenharmony_ci q->buf_ops = &v4l2_buf_ops; 90662306a36Sopenharmony_ci q->is_multiplanar = V4L2_TYPE_IS_MULTIPLANAR(q->type); 90762306a36Sopenharmony_ci q->is_output = V4L2_TYPE_IS_OUTPUT(q->type); 90862306a36Sopenharmony_ci q->copy_timestamp = (q->timestamp_flags & V4L2_BUF_FLAG_TIMESTAMP_MASK) 90962306a36Sopenharmony_ci == V4L2_BUF_FLAG_TIMESTAMP_COPY; 91062306a36Sopenharmony_ci /* 91162306a36Sopenharmony_ci * For compatibility with vb1: if QBUF hasn't been called yet, then 91262306a36Sopenharmony_ci * return EPOLLERR as well. This only affects capture queues, output 91362306a36Sopenharmony_ci * queues will always initialize waiting_for_buffers to false. 91462306a36Sopenharmony_ci */ 91562306a36Sopenharmony_ci q->quirk_poll_must_check_waiting_for_buffers = true; 91662306a36Sopenharmony_ci 91762306a36Sopenharmony_ci if (name) 91862306a36Sopenharmony_ci strscpy(q->name, name, sizeof(q->name)); 91962306a36Sopenharmony_ci else 92062306a36Sopenharmony_ci q->name[0] = '\0'; 92162306a36Sopenharmony_ci 92262306a36Sopenharmony_ci return vb2_core_queue_init(q); 92362306a36Sopenharmony_ci} 92462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(vb2_queue_init_name); 92562306a36Sopenharmony_ci 92662306a36Sopenharmony_ciint vb2_queue_init(struct vb2_queue *q) 92762306a36Sopenharmony_ci{ 92862306a36Sopenharmony_ci return vb2_queue_init_name(q, NULL); 92962306a36Sopenharmony_ci} 93062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(vb2_queue_init); 93162306a36Sopenharmony_ci 93262306a36Sopenharmony_civoid vb2_queue_release(struct vb2_queue *q) 93362306a36Sopenharmony_ci{ 93462306a36Sopenharmony_ci vb2_core_queue_release(q); 93562306a36Sopenharmony_ci} 93662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(vb2_queue_release); 93762306a36Sopenharmony_ci 93862306a36Sopenharmony_ciint vb2_queue_change_type(struct vb2_queue *q, unsigned int type) 93962306a36Sopenharmony_ci{ 94062306a36Sopenharmony_ci if (type == q->type) 94162306a36Sopenharmony_ci return 0; 94262306a36Sopenharmony_ci 94362306a36Sopenharmony_ci if (vb2_is_busy(q)) 94462306a36Sopenharmony_ci return -EBUSY; 94562306a36Sopenharmony_ci 94662306a36Sopenharmony_ci q->type = type; 94762306a36Sopenharmony_ci 94862306a36Sopenharmony_ci return 0; 94962306a36Sopenharmony_ci} 95062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(vb2_queue_change_type); 95162306a36Sopenharmony_ci 95262306a36Sopenharmony_ci__poll_t vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait) 95362306a36Sopenharmony_ci{ 95462306a36Sopenharmony_ci struct video_device *vfd = video_devdata(file); 95562306a36Sopenharmony_ci __poll_t res; 95662306a36Sopenharmony_ci 95762306a36Sopenharmony_ci res = vb2_core_poll(q, file, wait); 95862306a36Sopenharmony_ci 95962306a36Sopenharmony_ci if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) { 96062306a36Sopenharmony_ci struct v4l2_fh *fh = file->private_data; 96162306a36Sopenharmony_ci 96262306a36Sopenharmony_ci poll_wait(file, &fh->wait, wait); 96362306a36Sopenharmony_ci if (v4l2_event_pending(fh)) 96462306a36Sopenharmony_ci res |= EPOLLPRI; 96562306a36Sopenharmony_ci } 96662306a36Sopenharmony_ci 96762306a36Sopenharmony_ci return res; 96862306a36Sopenharmony_ci} 96962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(vb2_poll); 97062306a36Sopenharmony_ci 97162306a36Sopenharmony_ci/* 97262306a36Sopenharmony_ci * The following functions are not part of the vb2 core API, but are helper 97362306a36Sopenharmony_ci * functions that plug into struct v4l2_ioctl_ops, struct v4l2_file_operations 97462306a36Sopenharmony_ci * and struct vb2_ops. 97562306a36Sopenharmony_ci * They contain boilerplate code that most if not all drivers have to do 97662306a36Sopenharmony_ci * and so they simplify the driver code. 97762306a36Sopenharmony_ci */ 97862306a36Sopenharmony_ci 97962306a36Sopenharmony_ci/* vb2 ioctl helpers */ 98062306a36Sopenharmony_ci 98162306a36Sopenharmony_ciint vb2_ioctl_reqbufs(struct file *file, void *priv, 98262306a36Sopenharmony_ci struct v4l2_requestbuffers *p) 98362306a36Sopenharmony_ci{ 98462306a36Sopenharmony_ci struct video_device *vdev = video_devdata(file); 98562306a36Sopenharmony_ci int res = vb2_verify_memory_type(vdev->queue, p->memory, p->type); 98662306a36Sopenharmony_ci u32 flags = p->flags; 98762306a36Sopenharmony_ci 98862306a36Sopenharmony_ci fill_buf_caps(vdev->queue, &p->capabilities); 98962306a36Sopenharmony_ci validate_memory_flags(vdev->queue, p->memory, &flags); 99062306a36Sopenharmony_ci p->flags = flags; 99162306a36Sopenharmony_ci if (res) 99262306a36Sopenharmony_ci return res; 99362306a36Sopenharmony_ci if (vb2_queue_is_busy(vdev->queue, file)) 99462306a36Sopenharmony_ci return -EBUSY; 99562306a36Sopenharmony_ci res = vb2_core_reqbufs(vdev->queue, p->memory, p->flags, &p->count); 99662306a36Sopenharmony_ci /* If count == 0, then the owner has released all buffers and he 99762306a36Sopenharmony_ci is no longer owner of the queue. Otherwise we have a new owner. */ 99862306a36Sopenharmony_ci if (res == 0) 99962306a36Sopenharmony_ci vdev->queue->owner = p->count ? file->private_data : NULL; 100062306a36Sopenharmony_ci return res; 100162306a36Sopenharmony_ci} 100262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(vb2_ioctl_reqbufs); 100362306a36Sopenharmony_ci 100462306a36Sopenharmony_ciint vb2_ioctl_create_bufs(struct file *file, void *priv, 100562306a36Sopenharmony_ci struct v4l2_create_buffers *p) 100662306a36Sopenharmony_ci{ 100762306a36Sopenharmony_ci struct video_device *vdev = video_devdata(file); 100862306a36Sopenharmony_ci int res = vb2_verify_memory_type(vdev->queue, p->memory, 100962306a36Sopenharmony_ci p->format.type); 101062306a36Sopenharmony_ci 101162306a36Sopenharmony_ci p->index = vdev->queue->num_buffers; 101262306a36Sopenharmony_ci fill_buf_caps(vdev->queue, &p->capabilities); 101362306a36Sopenharmony_ci validate_memory_flags(vdev->queue, p->memory, &p->flags); 101462306a36Sopenharmony_ci /* 101562306a36Sopenharmony_ci * If count == 0, then just check if memory and type are valid. 101662306a36Sopenharmony_ci * Any -EBUSY result from vb2_verify_memory_type can be mapped to 0. 101762306a36Sopenharmony_ci */ 101862306a36Sopenharmony_ci if (p->count == 0) 101962306a36Sopenharmony_ci return res != -EBUSY ? res : 0; 102062306a36Sopenharmony_ci if (res) 102162306a36Sopenharmony_ci return res; 102262306a36Sopenharmony_ci if (vb2_queue_is_busy(vdev->queue, file)) 102362306a36Sopenharmony_ci return -EBUSY; 102462306a36Sopenharmony_ci 102562306a36Sopenharmony_ci res = vb2_create_bufs(vdev->queue, p); 102662306a36Sopenharmony_ci if (res == 0) 102762306a36Sopenharmony_ci vdev->queue->owner = file->private_data; 102862306a36Sopenharmony_ci return res; 102962306a36Sopenharmony_ci} 103062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(vb2_ioctl_create_bufs); 103162306a36Sopenharmony_ci 103262306a36Sopenharmony_ciint vb2_ioctl_prepare_buf(struct file *file, void *priv, 103362306a36Sopenharmony_ci struct v4l2_buffer *p) 103462306a36Sopenharmony_ci{ 103562306a36Sopenharmony_ci struct video_device *vdev = video_devdata(file); 103662306a36Sopenharmony_ci 103762306a36Sopenharmony_ci if (vb2_queue_is_busy(vdev->queue, file)) 103862306a36Sopenharmony_ci return -EBUSY; 103962306a36Sopenharmony_ci return vb2_prepare_buf(vdev->queue, vdev->v4l2_dev->mdev, p); 104062306a36Sopenharmony_ci} 104162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(vb2_ioctl_prepare_buf); 104262306a36Sopenharmony_ci 104362306a36Sopenharmony_ciint vb2_ioctl_querybuf(struct file *file, void *priv, struct v4l2_buffer *p) 104462306a36Sopenharmony_ci{ 104562306a36Sopenharmony_ci struct video_device *vdev = video_devdata(file); 104662306a36Sopenharmony_ci 104762306a36Sopenharmony_ci /* No need to call vb2_queue_is_busy(), anyone can query buffers. */ 104862306a36Sopenharmony_ci return vb2_querybuf(vdev->queue, p); 104962306a36Sopenharmony_ci} 105062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(vb2_ioctl_querybuf); 105162306a36Sopenharmony_ci 105262306a36Sopenharmony_ciint vb2_ioctl_qbuf(struct file *file, void *priv, struct v4l2_buffer *p) 105362306a36Sopenharmony_ci{ 105462306a36Sopenharmony_ci struct video_device *vdev = video_devdata(file); 105562306a36Sopenharmony_ci 105662306a36Sopenharmony_ci if (vb2_queue_is_busy(vdev->queue, file)) 105762306a36Sopenharmony_ci return -EBUSY; 105862306a36Sopenharmony_ci return vb2_qbuf(vdev->queue, vdev->v4l2_dev->mdev, p); 105962306a36Sopenharmony_ci} 106062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(vb2_ioctl_qbuf); 106162306a36Sopenharmony_ci 106262306a36Sopenharmony_ciint vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) 106362306a36Sopenharmony_ci{ 106462306a36Sopenharmony_ci struct video_device *vdev = video_devdata(file); 106562306a36Sopenharmony_ci 106662306a36Sopenharmony_ci if (vb2_queue_is_busy(vdev->queue, file)) 106762306a36Sopenharmony_ci return -EBUSY; 106862306a36Sopenharmony_ci return vb2_dqbuf(vdev->queue, p, file->f_flags & O_NONBLOCK); 106962306a36Sopenharmony_ci} 107062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(vb2_ioctl_dqbuf); 107162306a36Sopenharmony_ci 107262306a36Sopenharmony_ciint vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i) 107362306a36Sopenharmony_ci{ 107462306a36Sopenharmony_ci struct video_device *vdev = video_devdata(file); 107562306a36Sopenharmony_ci 107662306a36Sopenharmony_ci if (vb2_queue_is_busy(vdev->queue, file)) 107762306a36Sopenharmony_ci return -EBUSY; 107862306a36Sopenharmony_ci return vb2_streamon(vdev->queue, i); 107962306a36Sopenharmony_ci} 108062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(vb2_ioctl_streamon); 108162306a36Sopenharmony_ci 108262306a36Sopenharmony_ciint vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) 108362306a36Sopenharmony_ci{ 108462306a36Sopenharmony_ci struct video_device *vdev = video_devdata(file); 108562306a36Sopenharmony_ci 108662306a36Sopenharmony_ci if (vb2_queue_is_busy(vdev->queue, file)) 108762306a36Sopenharmony_ci return -EBUSY; 108862306a36Sopenharmony_ci return vb2_streamoff(vdev->queue, i); 108962306a36Sopenharmony_ci} 109062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(vb2_ioctl_streamoff); 109162306a36Sopenharmony_ci 109262306a36Sopenharmony_ciint vb2_ioctl_expbuf(struct file *file, void *priv, struct v4l2_exportbuffer *p) 109362306a36Sopenharmony_ci{ 109462306a36Sopenharmony_ci struct video_device *vdev = video_devdata(file); 109562306a36Sopenharmony_ci 109662306a36Sopenharmony_ci if (vb2_queue_is_busy(vdev->queue, file)) 109762306a36Sopenharmony_ci return -EBUSY; 109862306a36Sopenharmony_ci return vb2_expbuf(vdev->queue, p); 109962306a36Sopenharmony_ci} 110062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(vb2_ioctl_expbuf); 110162306a36Sopenharmony_ci 110262306a36Sopenharmony_ci/* v4l2_file_operations helpers */ 110362306a36Sopenharmony_ci 110462306a36Sopenharmony_ciint vb2_fop_mmap(struct file *file, struct vm_area_struct *vma) 110562306a36Sopenharmony_ci{ 110662306a36Sopenharmony_ci struct video_device *vdev = video_devdata(file); 110762306a36Sopenharmony_ci 110862306a36Sopenharmony_ci return vb2_mmap(vdev->queue, vma); 110962306a36Sopenharmony_ci} 111062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(vb2_fop_mmap); 111162306a36Sopenharmony_ci 111262306a36Sopenharmony_ciint _vb2_fop_release(struct file *file, struct mutex *lock) 111362306a36Sopenharmony_ci{ 111462306a36Sopenharmony_ci struct video_device *vdev = video_devdata(file); 111562306a36Sopenharmony_ci 111662306a36Sopenharmony_ci if (lock) 111762306a36Sopenharmony_ci mutex_lock(lock); 111862306a36Sopenharmony_ci if (file->private_data == vdev->queue->owner) { 111962306a36Sopenharmony_ci vb2_queue_release(vdev->queue); 112062306a36Sopenharmony_ci vdev->queue->owner = NULL; 112162306a36Sopenharmony_ci } 112262306a36Sopenharmony_ci if (lock) 112362306a36Sopenharmony_ci mutex_unlock(lock); 112462306a36Sopenharmony_ci return v4l2_fh_release(file); 112562306a36Sopenharmony_ci} 112662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(_vb2_fop_release); 112762306a36Sopenharmony_ci 112862306a36Sopenharmony_ciint vb2_fop_release(struct file *file) 112962306a36Sopenharmony_ci{ 113062306a36Sopenharmony_ci struct video_device *vdev = video_devdata(file); 113162306a36Sopenharmony_ci struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock; 113262306a36Sopenharmony_ci 113362306a36Sopenharmony_ci return _vb2_fop_release(file, lock); 113462306a36Sopenharmony_ci} 113562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(vb2_fop_release); 113662306a36Sopenharmony_ci 113762306a36Sopenharmony_cissize_t vb2_fop_write(struct file *file, const char __user *buf, 113862306a36Sopenharmony_ci size_t count, loff_t *ppos) 113962306a36Sopenharmony_ci{ 114062306a36Sopenharmony_ci struct video_device *vdev = video_devdata(file); 114162306a36Sopenharmony_ci struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock; 114262306a36Sopenharmony_ci int err = -EBUSY; 114362306a36Sopenharmony_ci 114462306a36Sopenharmony_ci if (!(vdev->queue->io_modes & VB2_WRITE)) 114562306a36Sopenharmony_ci return -EINVAL; 114662306a36Sopenharmony_ci if (lock && mutex_lock_interruptible(lock)) 114762306a36Sopenharmony_ci return -ERESTARTSYS; 114862306a36Sopenharmony_ci if (vb2_queue_is_busy(vdev->queue, file)) 114962306a36Sopenharmony_ci goto exit; 115062306a36Sopenharmony_ci err = vb2_write(vdev->queue, buf, count, ppos, 115162306a36Sopenharmony_ci file->f_flags & O_NONBLOCK); 115262306a36Sopenharmony_ci if (vdev->queue->fileio) 115362306a36Sopenharmony_ci vdev->queue->owner = file->private_data; 115462306a36Sopenharmony_ciexit: 115562306a36Sopenharmony_ci if (lock) 115662306a36Sopenharmony_ci mutex_unlock(lock); 115762306a36Sopenharmony_ci return err; 115862306a36Sopenharmony_ci} 115962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(vb2_fop_write); 116062306a36Sopenharmony_ci 116162306a36Sopenharmony_cissize_t vb2_fop_read(struct file *file, char __user *buf, 116262306a36Sopenharmony_ci size_t count, loff_t *ppos) 116362306a36Sopenharmony_ci{ 116462306a36Sopenharmony_ci struct video_device *vdev = video_devdata(file); 116562306a36Sopenharmony_ci struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock; 116662306a36Sopenharmony_ci int err = -EBUSY; 116762306a36Sopenharmony_ci 116862306a36Sopenharmony_ci if (!(vdev->queue->io_modes & VB2_READ)) 116962306a36Sopenharmony_ci return -EINVAL; 117062306a36Sopenharmony_ci if (lock && mutex_lock_interruptible(lock)) 117162306a36Sopenharmony_ci return -ERESTARTSYS; 117262306a36Sopenharmony_ci if (vb2_queue_is_busy(vdev->queue, file)) 117362306a36Sopenharmony_ci goto exit; 117462306a36Sopenharmony_ci vdev->queue->owner = file->private_data; 117562306a36Sopenharmony_ci err = vb2_read(vdev->queue, buf, count, ppos, 117662306a36Sopenharmony_ci file->f_flags & O_NONBLOCK); 117762306a36Sopenharmony_ci if (!vdev->queue->fileio) 117862306a36Sopenharmony_ci vdev->queue->owner = NULL; 117962306a36Sopenharmony_ciexit: 118062306a36Sopenharmony_ci if (lock) 118162306a36Sopenharmony_ci mutex_unlock(lock); 118262306a36Sopenharmony_ci return err; 118362306a36Sopenharmony_ci} 118462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(vb2_fop_read); 118562306a36Sopenharmony_ci 118662306a36Sopenharmony_ci__poll_t vb2_fop_poll(struct file *file, poll_table *wait) 118762306a36Sopenharmony_ci{ 118862306a36Sopenharmony_ci struct video_device *vdev = video_devdata(file); 118962306a36Sopenharmony_ci struct vb2_queue *q = vdev->queue; 119062306a36Sopenharmony_ci struct mutex *lock = q->lock ? q->lock : vdev->lock; 119162306a36Sopenharmony_ci __poll_t res; 119262306a36Sopenharmony_ci void *fileio; 119362306a36Sopenharmony_ci 119462306a36Sopenharmony_ci /* 119562306a36Sopenharmony_ci * If this helper doesn't know how to lock, then you shouldn't be using 119662306a36Sopenharmony_ci * it but you should write your own. 119762306a36Sopenharmony_ci */ 119862306a36Sopenharmony_ci WARN_ON(!lock); 119962306a36Sopenharmony_ci 120062306a36Sopenharmony_ci if (lock && mutex_lock_interruptible(lock)) 120162306a36Sopenharmony_ci return EPOLLERR; 120262306a36Sopenharmony_ci 120362306a36Sopenharmony_ci fileio = q->fileio; 120462306a36Sopenharmony_ci 120562306a36Sopenharmony_ci res = vb2_poll(vdev->queue, file, wait); 120662306a36Sopenharmony_ci 120762306a36Sopenharmony_ci /* If fileio was started, then we have a new queue owner. */ 120862306a36Sopenharmony_ci if (!fileio && q->fileio) 120962306a36Sopenharmony_ci q->owner = file->private_data; 121062306a36Sopenharmony_ci if (lock) 121162306a36Sopenharmony_ci mutex_unlock(lock); 121262306a36Sopenharmony_ci return res; 121362306a36Sopenharmony_ci} 121462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(vb2_fop_poll); 121562306a36Sopenharmony_ci 121662306a36Sopenharmony_ci#ifndef CONFIG_MMU 121762306a36Sopenharmony_ciunsigned long vb2_fop_get_unmapped_area(struct file *file, unsigned long addr, 121862306a36Sopenharmony_ci unsigned long len, unsigned long pgoff, unsigned long flags) 121962306a36Sopenharmony_ci{ 122062306a36Sopenharmony_ci struct video_device *vdev = video_devdata(file); 122162306a36Sopenharmony_ci 122262306a36Sopenharmony_ci return vb2_get_unmapped_area(vdev->queue, addr, len, pgoff, flags); 122362306a36Sopenharmony_ci} 122462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(vb2_fop_get_unmapped_area); 122562306a36Sopenharmony_ci#endif 122662306a36Sopenharmony_ci 122762306a36Sopenharmony_civoid vb2_video_unregister_device(struct video_device *vdev) 122862306a36Sopenharmony_ci{ 122962306a36Sopenharmony_ci /* Check if vdev was ever registered at all */ 123062306a36Sopenharmony_ci if (!vdev || !video_is_registered(vdev)) 123162306a36Sopenharmony_ci return; 123262306a36Sopenharmony_ci 123362306a36Sopenharmony_ci /* 123462306a36Sopenharmony_ci * Calling this function only makes sense if vdev->queue is set. 123562306a36Sopenharmony_ci * If it is NULL, then just call video_unregister_device() instead. 123662306a36Sopenharmony_ci */ 123762306a36Sopenharmony_ci WARN_ON(!vdev->queue); 123862306a36Sopenharmony_ci 123962306a36Sopenharmony_ci /* 124062306a36Sopenharmony_ci * Take a reference to the device since video_unregister_device() 124162306a36Sopenharmony_ci * calls device_unregister(), but we don't want that to release 124262306a36Sopenharmony_ci * the device since we want to clean up the queue first. 124362306a36Sopenharmony_ci */ 124462306a36Sopenharmony_ci get_device(&vdev->dev); 124562306a36Sopenharmony_ci video_unregister_device(vdev); 124662306a36Sopenharmony_ci if (vdev->queue && vdev->queue->owner) { 124762306a36Sopenharmony_ci struct mutex *lock = vdev->queue->lock ? 124862306a36Sopenharmony_ci vdev->queue->lock : vdev->lock; 124962306a36Sopenharmony_ci 125062306a36Sopenharmony_ci if (lock) 125162306a36Sopenharmony_ci mutex_lock(lock); 125262306a36Sopenharmony_ci vb2_queue_release(vdev->queue); 125362306a36Sopenharmony_ci vdev->queue->owner = NULL; 125462306a36Sopenharmony_ci if (lock) 125562306a36Sopenharmony_ci mutex_unlock(lock); 125662306a36Sopenharmony_ci } 125762306a36Sopenharmony_ci /* 125862306a36Sopenharmony_ci * Now we put the device, and in most cases this will release 125962306a36Sopenharmony_ci * everything. 126062306a36Sopenharmony_ci */ 126162306a36Sopenharmony_ci put_device(&vdev->dev); 126262306a36Sopenharmony_ci} 126362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(vb2_video_unregister_device); 126462306a36Sopenharmony_ci 126562306a36Sopenharmony_ci/* vb2_ops helpers. Only use if vq->lock is non-NULL. */ 126662306a36Sopenharmony_ci 126762306a36Sopenharmony_civoid vb2_ops_wait_prepare(struct vb2_queue *vq) 126862306a36Sopenharmony_ci{ 126962306a36Sopenharmony_ci mutex_unlock(vq->lock); 127062306a36Sopenharmony_ci} 127162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(vb2_ops_wait_prepare); 127262306a36Sopenharmony_ci 127362306a36Sopenharmony_civoid vb2_ops_wait_finish(struct vb2_queue *vq) 127462306a36Sopenharmony_ci{ 127562306a36Sopenharmony_ci mutex_lock(vq->lock); 127662306a36Sopenharmony_ci} 127762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(vb2_ops_wait_finish); 127862306a36Sopenharmony_ci 127962306a36Sopenharmony_ci/* 128062306a36Sopenharmony_ci * Note that this function is called during validation time and 128162306a36Sopenharmony_ci * thus the req_queue_mutex is held to ensure no request objects 128262306a36Sopenharmony_ci * can be added or deleted while validating. So there is no need 128362306a36Sopenharmony_ci * to protect the objects list. 128462306a36Sopenharmony_ci */ 128562306a36Sopenharmony_ciint vb2_request_validate(struct media_request *req) 128662306a36Sopenharmony_ci{ 128762306a36Sopenharmony_ci struct media_request_object *obj; 128862306a36Sopenharmony_ci int ret = 0; 128962306a36Sopenharmony_ci 129062306a36Sopenharmony_ci if (!vb2_request_buffer_cnt(req)) 129162306a36Sopenharmony_ci return -ENOENT; 129262306a36Sopenharmony_ci 129362306a36Sopenharmony_ci list_for_each_entry(obj, &req->objects, list) { 129462306a36Sopenharmony_ci if (!obj->ops->prepare) 129562306a36Sopenharmony_ci continue; 129662306a36Sopenharmony_ci 129762306a36Sopenharmony_ci ret = obj->ops->prepare(obj); 129862306a36Sopenharmony_ci if (ret) 129962306a36Sopenharmony_ci break; 130062306a36Sopenharmony_ci } 130162306a36Sopenharmony_ci 130262306a36Sopenharmony_ci if (ret) { 130362306a36Sopenharmony_ci list_for_each_entry_continue_reverse(obj, &req->objects, list) 130462306a36Sopenharmony_ci if (obj->ops->unprepare) 130562306a36Sopenharmony_ci obj->ops->unprepare(obj); 130662306a36Sopenharmony_ci return ret; 130762306a36Sopenharmony_ci } 130862306a36Sopenharmony_ci return 0; 130962306a36Sopenharmony_ci} 131062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(vb2_request_validate); 131162306a36Sopenharmony_ci 131262306a36Sopenharmony_civoid vb2_request_queue(struct media_request *req) 131362306a36Sopenharmony_ci{ 131462306a36Sopenharmony_ci struct media_request_object *obj, *obj_safe; 131562306a36Sopenharmony_ci 131662306a36Sopenharmony_ci /* 131762306a36Sopenharmony_ci * Queue all objects. Note that buffer objects are at the end of the 131862306a36Sopenharmony_ci * objects list, after all other object types. Once buffer objects 131962306a36Sopenharmony_ci * are queued, the driver might delete them immediately (if the driver 132062306a36Sopenharmony_ci * processes the buffer at once), so we have to use 132162306a36Sopenharmony_ci * list_for_each_entry_safe() to handle the case where the object we 132262306a36Sopenharmony_ci * queue is deleted. 132362306a36Sopenharmony_ci */ 132462306a36Sopenharmony_ci list_for_each_entry_safe(obj, obj_safe, &req->objects, list) 132562306a36Sopenharmony_ci if (obj->ops->queue) 132662306a36Sopenharmony_ci obj->ops->queue(obj); 132762306a36Sopenharmony_ci} 132862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(vb2_request_queue); 132962306a36Sopenharmony_ci 133062306a36Sopenharmony_ciMODULE_DESCRIPTION("Driver helper framework for Video for Linux 2"); 133162306a36Sopenharmony_ciMODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>, Marek Szyprowski"); 133262306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 1333