Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v5.7-rc4 480 lines 13 kB view raw
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * vimc-capture.c Virtual Media Controller Driver 4 * 5 * Copyright (C) 2015-2017 Helen Koike <helen.fornazier@gmail.com> 6 */ 7 8#include <media/v4l2-ioctl.h> 9#include <media/videobuf2-core.h> 10#include <media/videobuf2-vmalloc.h> 11 12#include "vimc-common.h" 13#include "vimc-streamer.h" 14 15struct vimc_cap_device { 16 struct vimc_ent_device ved; 17 struct video_device vdev; 18 struct v4l2_pix_format format; 19 struct vb2_queue queue; 20 struct list_head buf_list; 21 /* 22 * NOTE: in a real driver, a spin lock must be used to access the 23 * queue because the frames are generated from a hardware interruption 24 * and the isr is not allowed to sleep. 25 * Even if it is not necessary a spinlock in the vimc driver, we 26 * use it here as a code reference 27 */ 28 spinlock_t qlock; 29 struct mutex lock; 30 u32 sequence; 31 struct vimc_stream stream; 32 struct media_pad pad; 33}; 34 35static const struct v4l2_pix_format fmt_default = { 36 .width = 640, 37 .height = 480, 38 .pixelformat = V4L2_PIX_FMT_RGB24, 39 .field = V4L2_FIELD_NONE, 40 .colorspace = V4L2_COLORSPACE_DEFAULT, 41}; 42 43struct vimc_cap_buffer { 44 /* 45 * struct vb2_v4l2_buffer must be the first element 46 * the videobuf2 framework will allocate this struct based on 47 * buf_struct_size and use the first sizeof(struct vb2_buffer) bytes of 48 * memory as a vb2_buffer 49 */ 50 struct vb2_v4l2_buffer vb2; 51 struct list_head list; 52}; 53 54static int vimc_cap_querycap(struct file *file, void *priv, 55 struct v4l2_capability *cap) 56{ 57 strscpy(cap->driver, VIMC_PDEV_NAME, sizeof(cap->driver)); 58 strscpy(cap->card, KBUILD_MODNAME, sizeof(cap->card)); 59 snprintf(cap->bus_info, sizeof(cap->bus_info), 60 "platform:%s", VIMC_PDEV_NAME); 61 62 return 0; 63} 64 65static void vimc_cap_get_format(struct vimc_ent_device *ved, 66 struct v4l2_pix_format *fmt) 67{ 68 struct vimc_cap_device *vcap = container_of(ved, struct vimc_cap_device, 69 ved); 70 71 *fmt = vcap->format; 72} 73 74static int vimc_cap_g_fmt_vid_cap(struct file *file, void *priv, 75 struct v4l2_format *f) 76{ 77 struct vimc_cap_device *vcap = video_drvdata(file); 78 79 f->fmt.pix = vcap->format; 80 81 return 0; 82} 83 84static int vimc_cap_try_fmt_vid_cap(struct file *file, void *priv, 85 struct v4l2_format *f) 86{ 87 struct v4l2_pix_format *format = &f->fmt.pix; 88 const struct vimc_pix_map *vpix; 89 90 format->width = clamp_t(u32, format->width, VIMC_FRAME_MIN_WIDTH, 91 VIMC_FRAME_MAX_WIDTH) & ~1; 92 format->height = clamp_t(u32, format->height, VIMC_FRAME_MIN_HEIGHT, 93 VIMC_FRAME_MAX_HEIGHT) & ~1; 94 95 /* Don't accept a pixelformat that is not on the table */ 96 vpix = vimc_pix_map_by_pixelformat(format->pixelformat); 97 if (!vpix) { 98 format->pixelformat = fmt_default.pixelformat; 99 vpix = vimc_pix_map_by_pixelformat(format->pixelformat); 100 } 101 /* TODO: Add support for custom bytesperline values */ 102 format->bytesperline = format->width * vpix->bpp; 103 format->sizeimage = format->bytesperline * format->height; 104 105 if (format->field == V4L2_FIELD_ANY) 106 format->field = fmt_default.field; 107 108 vimc_colorimetry_clamp(format); 109 110 return 0; 111} 112 113static int vimc_cap_s_fmt_vid_cap(struct file *file, void *priv, 114 struct v4l2_format *f) 115{ 116 struct vimc_cap_device *vcap = video_drvdata(file); 117 int ret; 118 119 /* Do not change the format while stream is on */ 120 if (vb2_is_busy(&vcap->queue)) 121 return -EBUSY; 122 123 ret = vimc_cap_try_fmt_vid_cap(file, priv, f); 124 if (ret) 125 return ret; 126 127 dev_dbg(vcap->ved.dev, "%s: format update: " 128 "old:%dx%d (0x%x, %d, %d, %d, %d) " 129 "new:%dx%d (0x%x, %d, %d, %d, %d)\n", vcap->vdev.name, 130 /* old */ 131 vcap->format.width, vcap->format.height, 132 vcap->format.pixelformat, vcap->format.colorspace, 133 vcap->format.quantization, vcap->format.xfer_func, 134 vcap->format.ycbcr_enc, 135 /* new */ 136 f->fmt.pix.width, f->fmt.pix.height, 137 f->fmt.pix.pixelformat, f->fmt.pix.colorspace, 138 f->fmt.pix.quantization, f->fmt.pix.xfer_func, 139 f->fmt.pix.ycbcr_enc); 140 141 vcap->format = f->fmt.pix; 142 143 return 0; 144} 145 146static int vimc_cap_enum_fmt_vid_cap(struct file *file, void *priv, 147 struct v4l2_fmtdesc *f) 148{ 149 const struct vimc_pix_map *vpix = vimc_pix_map_by_index(f->index); 150 151 if (!vpix) 152 return -EINVAL; 153 154 f->pixelformat = vpix->pixelformat; 155 156 return 0; 157} 158 159static int vimc_cap_enum_framesizes(struct file *file, void *fh, 160 struct v4l2_frmsizeenum *fsize) 161{ 162 const struct vimc_pix_map *vpix; 163 164 if (fsize->index) 165 return -EINVAL; 166 167 /* Only accept code in the pix map table */ 168 vpix = vimc_pix_map_by_code(fsize->pixel_format); 169 if (!vpix) 170 return -EINVAL; 171 172 fsize->type = V4L2_FRMSIZE_TYPE_CONTINUOUS; 173 fsize->stepwise.min_width = VIMC_FRAME_MIN_WIDTH; 174 fsize->stepwise.max_width = VIMC_FRAME_MAX_WIDTH; 175 fsize->stepwise.min_height = VIMC_FRAME_MIN_HEIGHT; 176 fsize->stepwise.max_height = VIMC_FRAME_MAX_HEIGHT; 177 fsize->stepwise.step_width = 1; 178 fsize->stepwise.step_height = 1; 179 180 return 0; 181} 182 183static const struct v4l2_file_operations vimc_cap_fops = { 184 .owner = THIS_MODULE, 185 .open = v4l2_fh_open, 186 .release = vb2_fop_release, 187 .read = vb2_fop_read, 188 .poll = vb2_fop_poll, 189 .unlocked_ioctl = video_ioctl2, 190 .mmap = vb2_fop_mmap, 191}; 192 193static const struct v4l2_ioctl_ops vimc_cap_ioctl_ops = { 194 .vidioc_querycap = vimc_cap_querycap, 195 196 .vidioc_g_fmt_vid_cap = vimc_cap_g_fmt_vid_cap, 197 .vidioc_s_fmt_vid_cap = vimc_cap_s_fmt_vid_cap, 198 .vidioc_try_fmt_vid_cap = vimc_cap_try_fmt_vid_cap, 199 .vidioc_enum_fmt_vid_cap = vimc_cap_enum_fmt_vid_cap, 200 .vidioc_enum_framesizes = vimc_cap_enum_framesizes, 201 202 .vidioc_reqbufs = vb2_ioctl_reqbufs, 203 .vidioc_create_bufs = vb2_ioctl_create_bufs, 204 .vidioc_prepare_buf = vb2_ioctl_prepare_buf, 205 .vidioc_querybuf = vb2_ioctl_querybuf, 206 .vidioc_qbuf = vb2_ioctl_qbuf, 207 .vidioc_dqbuf = vb2_ioctl_dqbuf, 208 .vidioc_expbuf = vb2_ioctl_expbuf, 209 .vidioc_streamon = vb2_ioctl_streamon, 210 .vidioc_streamoff = vb2_ioctl_streamoff, 211}; 212 213static void vimc_cap_return_all_buffers(struct vimc_cap_device *vcap, 214 enum vb2_buffer_state state) 215{ 216 struct vimc_cap_buffer *vbuf, *node; 217 218 spin_lock(&vcap->qlock); 219 220 list_for_each_entry_safe(vbuf, node, &vcap->buf_list, list) { 221 list_del(&vbuf->list); 222 vb2_buffer_done(&vbuf->vb2.vb2_buf, state); 223 } 224 225 spin_unlock(&vcap->qlock); 226} 227 228static int vimc_cap_start_streaming(struct vb2_queue *vq, unsigned int count) 229{ 230 struct vimc_cap_device *vcap = vb2_get_drv_priv(vq); 231 struct media_entity *entity = &vcap->vdev.entity; 232 int ret; 233 234 vcap->sequence = 0; 235 236 /* Start the media pipeline */ 237 ret = media_pipeline_start(entity, &vcap->stream.pipe); 238 if (ret) { 239 vimc_cap_return_all_buffers(vcap, VB2_BUF_STATE_QUEUED); 240 return ret; 241 } 242 243 ret = vimc_streamer_s_stream(&vcap->stream, &vcap->ved, 1); 244 if (ret) { 245 media_pipeline_stop(entity); 246 vimc_cap_return_all_buffers(vcap, VB2_BUF_STATE_QUEUED); 247 return ret; 248 } 249 250 return 0; 251} 252 253/* 254 * Stop the stream engine. Any remaining buffers in the stream queue are 255 * dequeued and passed on to the vb2 framework marked as STATE_ERROR. 256 */ 257static void vimc_cap_stop_streaming(struct vb2_queue *vq) 258{ 259 struct vimc_cap_device *vcap = vb2_get_drv_priv(vq); 260 261 vimc_streamer_s_stream(&vcap->stream, &vcap->ved, 0); 262 263 /* Stop the media pipeline */ 264 media_pipeline_stop(&vcap->vdev.entity); 265 266 /* Release all active buffers */ 267 vimc_cap_return_all_buffers(vcap, VB2_BUF_STATE_ERROR); 268} 269 270static void vimc_cap_buf_queue(struct vb2_buffer *vb2_buf) 271{ 272 struct vimc_cap_device *vcap = vb2_get_drv_priv(vb2_buf->vb2_queue); 273 struct vimc_cap_buffer *buf = container_of(vb2_buf, 274 struct vimc_cap_buffer, 275 vb2.vb2_buf); 276 277 spin_lock(&vcap->qlock); 278 list_add_tail(&buf->list, &vcap->buf_list); 279 spin_unlock(&vcap->qlock); 280} 281 282static int vimc_cap_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, 283 unsigned int *nplanes, unsigned int sizes[], 284 struct device *alloc_devs[]) 285{ 286 struct vimc_cap_device *vcap = vb2_get_drv_priv(vq); 287 288 if (*nplanes) 289 return sizes[0] < vcap->format.sizeimage ? -EINVAL : 0; 290 /* We don't support multiplanes for now */ 291 *nplanes = 1; 292 sizes[0] = vcap->format.sizeimage; 293 294 return 0; 295} 296 297static int vimc_cap_buffer_prepare(struct vb2_buffer *vb) 298{ 299 struct vimc_cap_device *vcap = vb2_get_drv_priv(vb->vb2_queue); 300 unsigned long size = vcap->format.sizeimage; 301 302 if (vb2_plane_size(vb, 0) < size) { 303 dev_err(vcap->ved.dev, "%s: buffer too small (%lu < %lu)\n", 304 vcap->vdev.name, vb2_plane_size(vb, 0), size); 305 return -EINVAL; 306 } 307 return 0; 308} 309 310static const struct vb2_ops vimc_cap_qops = { 311 .start_streaming = vimc_cap_start_streaming, 312 .stop_streaming = vimc_cap_stop_streaming, 313 .buf_queue = vimc_cap_buf_queue, 314 .queue_setup = vimc_cap_queue_setup, 315 .buf_prepare = vimc_cap_buffer_prepare, 316 /* 317 * Since q->lock is set we can use the standard 318 * vb2_ops_wait_prepare/finish helper functions. 319 */ 320 .wait_prepare = vb2_ops_wait_prepare, 321 .wait_finish = vb2_ops_wait_finish, 322}; 323 324static const struct media_entity_operations vimc_cap_mops = { 325 .link_validate = vimc_vdev_link_validate, 326}; 327 328void vimc_cap_release(struct vimc_ent_device *ved) 329{ 330 struct vimc_cap_device *vcap = 331 container_of(ved, struct vimc_cap_device, ved); 332 333 media_entity_cleanup(vcap->ved.ent); 334 kfree(vcap); 335} 336 337void vimc_cap_unregister(struct vimc_ent_device *ved) 338{ 339 struct vimc_cap_device *vcap = 340 container_of(ved, struct vimc_cap_device, ved); 341 342 vb2_queue_release(&vcap->queue); 343 video_unregister_device(&vcap->vdev); 344} 345 346static void *vimc_cap_process_frame(struct vimc_ent_device *ved, 347 const void *frame) 348{ 349 struct vimc_cap_device *vcap = container_of(ved, struct vimc_cap_device, 350 ved); 351 struct vimc_cap_buffer *vimc_buf; 352 void *vbuf; 353 354 spin_lock(&vcap->qlock); 355 356 /* Get the first entry of the list */ 357 vimc_buf = list_first_entry_or_null(&vcap->buf_list, 358 typeof(*vimc_buf), list); 359 if (!vimc_buf) { 360 spin_unlock(&vcap->qlock); 361 return ERR_PTR(-EAGAIN); 362 } 363 364 /* Remove this entry from the list */ 365 list_del(&vimc_buf->list); 366 367 spin_unlock(&vcap->qlock); 368 369 /* Fill the buffer */ 370 vimc_buf->vb2.vb2_buf.timestamp = ktime_get_ns(); 371 vimc_buf->vb2.sequence = vcap->sequence++; 372 vimc_buf->vb2.field = vcap->format.field; 373 374 vbuf = vb2_plane_vaddr(&vimc_buf->vb2.vb2_buf, 0); 375 376 memcpy(vbuf, frame, vcap->format.sizeimage); 377 378 /* Set it as ready */ 379 vb2_set_plane_payload(&vimc_buf->vb2.vb2_buf, 0, 380 vcap->format.sizeimage); 381 vb2_buffer_done(&vimc_buf->vb2.vb2_buf, VB2_BUF_STATE_DONE); 382 return NULL; 383} 384 385struct vimc_ent_device *vimc_cap_add(struct vimc_device *vimc, 386 const char *vcfg_name) 387{ 388 struct v4l2_device *v4l2_dev = &vimc->v4l2_dev; 389 const struct vimc_pix_map *vpix; 390 struct vimc_cap_device *vcap; 391 struct video_device *vdev; 392 struct vb2_queue *q; 393 int ret; 394 395 /* Allocate the vimc_cap_device struct */ 396 vcap = kzalloc(sizeof(*vcap), GFP_KERNEL); 397 if (!vcap) 398 return NULL; 399 400 /* Initialize the media entity */ 401 vcap->vdev.entity.name = vcfg_name; 402 vcap->vdev.entity.function = MEDIA_ENT_F_IO_V4L; 403 vcap->pad.flags = MEDIA_PAD_FL_SINK; 404 ret = media_entity_pads_init(&vcap->vdev.entity, 405 1, &vcap->pad); 406 if (ret) 407 goto err_free_vcap; 408 409 /* Initialize the lock */ 410 mutex_init(&vcap->lock); 411 412 /* Initialize the vb2 queue */ 413 q = &vcap->queue; 414 q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 415 q->io_modes = VB2_MMAP | VB2_DMABUF | VB2_USERPTR; 416 q->drv_priv = vcap; 417 q->buf_struct_size = sizeof(struct vimc_cap_buffer); 418 q->ops = &vimc_cap_qops; 419 q->mem_ops = &vb2_vmalloc_memops; 420 q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; 421 q->min_buffers_needed = 2; 422 q->lock = &vcap->lock; 423 424 ret = vb2_queue_init(q); 425 if (ret) { 426 dev_err(vimc->mdev.dev, "%s: vb2 queue init failed (err=%d)\n", 427 vcfg_name, ret); 428 goto err_clean_m_ent; 429 } 430 431 /* Initialize buffer list and its lock */ 432 INIT_LIST_HEAD(&vcap->buf_list); 433 spin_lock_init(&vcap->qlock); 434 435 /* Set default frame format */ 436 vcap->format = fmt_default; 437 vpix = vimc_pix_map_by_pixelformat(vcap->format.pixelformat); 438 vcap->format.bytesperline = vcap->format.width * vpix->bpp; 439 vcap->format.sizeimage = vcap->format.bytesperline * 440 vcap->format.height; 441 442 /* Fill the vimc_ent_device struct */ 443 vcap->ved.ent = &vcap->vdev.entity; 444 vcap->ved.process_frame = vimc_cap_process_frame; 445 vcap->ved.vdev_get_format = vimc_cap_get_format; 446 vcap->ved.dev = vimc->mdev.dev; 447 448 /* Initialize the video_device struct */ 449 vdev = &vcap->vdev; 450 vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; 451 vdev->entity.ops = &vimc_cap_mops; 452 vdev->release = video_device_release_empty; 453 vdev->fops = &vimc_cap_fops; 454 vdev->ioctl_ops = &vimc_cap_ioctl_ops; 455 vdev->lock = &vcap->lock; 456 vdev->queue = q; 457 vdev->v4l2_dev = v4l2_dev; 458 vdev->vfl_dir = VFL_DIR_RX; 459 strscpy(vdev->name, vcfg_name, sizeof(vdev->name)); 460 video_set_drvdata(vdev, &vcap->ved); 461 462 /* Register the video_device with the v4l2 and the media framework */ 463 ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); 464 if (ret) { 465 dev_err(vimc->mdev.dev, "%s: video register failed (err=%d)\n", 466 vcap->vdev.name, ret); 467 goto err_release_queue; 468 } 469 470 return &vcap->ved; 471 472err_release_queue: 473 vb2_queue_release(q); 474err_clean_m_ent: 475 media_entity_cleanup(&vcap->vdev.entity); 476err_free_vcap: 477 kfree(vcap); 478 479 return NULL; 480}