This source file includes following definitions.
- vimc_cap_querycap
- vimc_cap_get_format
- vimc_cap_g_fmt_vid_cap
- vimc_cap_try_fmt_vid_cap
- vimc_cap_s_fmt_vid_cap
- vimc_cap_enum_fmt_vid_cap
- vimc_cap_enum_framesizes
- vimc_cap_return_all_buffers
- vimc_cap_start_streaming
- vimc_cap_stop_streaming
- vimc_cap_buf_queue
- vimc_cap_queue_setup
- vimc_cap_buffer_prepare
- vimc_cap_release
- vimc_cap_comp_unbind
- vimc_cap_process_frame
- vimc_cap_comp_bind
- vimc_cap_probe
- vimc_cap_remove
1
2
3
4
5
6
7
8 #include <linux/component.h>
9 #include <linux/module.h>
10 #include <linux/mod_devicetable.h>
11 #include <linux/platform_device.h>
12 #include <media/v4l2-ioctl.h>
13 #include <media/videobuf2-core.h>
14 #include <media/videobuf2-vmalloc.h>
15
16 #include "vimc-common.h"
17 #include "vimc-streamer.h"
18
19 #define VIMC_CAP_DRV_NAME "vimc-capture"
20
21 struct vimc_cap_device {
22 struct vimc_ent_device ved;
23 struct video_device vdev;
24 struct device *dev;
25 struct v4l2_pix_format format;
26 struct vb2_queue queue;
27 struct list_head buf_list;
28
29
30
31
32
33
34
35 spinlock_t qlock;
36 struct mutex lock;
37 u32 sequence;
38 struct vimc_stream stream;
39 };
40
41 static const struct v4l2_pix_format fmt_default = {
42 .width = 640,
43 .height = 480,
44 .pixelformat = V4L2_PIX_FMT_RGB24,
45 .field = V4L2_FIELD_NONE,
46 .colorspace = V4L2_COLORSPACE_DEFAULT,
47 };
48
49 struct vimc_cap_buffer {
50
51
52
53
54
55
56 struct vb2_v4l2_buffer vb2;
57 struct list_head list;
58 };
59
60 static int vimc_cap_querycap(struct file *file, void *priv,
61 struct v4l2_capability *cap)
62 {
63 strscpy(cap->driver, VIMC_PDEV_NAME, sizeof(cap->driver));
64 strscpy(cap->card, KBUILD_MODNAME, sizeof(cap->card));
65 snprintf(cap->bus_info, sizeof(cap->bus_info),
66 "platform:%s", VIMC_PDEV_NAME);
67
68 return 0;
69 }
70
71 static void vimc_cap_get_format(struct vimc_ent_device *ved,
72 struct v4l2_pix_format *fmt)
73 {
74 struct vimc_cap_device *vcap = container_of(ved, struct vimc_cap_device,
75 ved);
76
77 *fmt = vcap->format;
78 }
79
80 static int vimc_cap_g_fmt_vid_cap(struct file *file, void *priv,
81 struct v4l2_format *f)
82 {
83 struct vimc_cap_device *vcap = video_drvdata(file);
84
85 f->fmt.pix = vcap->format;
86
87 return 0;
88 }
89
90 static int vimc_cap_try_fmt_vid_cap(struct file *file, void *priv,
91 struct v4l2_format *f)
92 {
93 struct v4l2_pix_format *format = &f->fmt.pix;
94 const struct vimc_pix_map *vpix;
95
96 format->width = clamp_t(u32, format->width, VIMC_FRAME_MIN_WIDTH,
97 VIMC_FRAME_MAX_WIDTH) & ~1;
98 format->height = clamp_t(u32, format->height, VIMC_FRAME_MIN_HEIGHT,
99 VIMC_FRAME_MAX_HEIGHT) & ~1;
100
101
102 vpix = vimc_pix_map_by_pixelformat(format->pixelformat);
103 if (!vpix) {
104 format->pixelformat = fmt_default.pixelformat;
105 vpix = vimc_pix_map_by_pixelformat(format->pixelformat);
106 }
107
108 format->bytesperline = format->width * vpix->bpp;
109 format->sizeimage = format->bytesperline * format->height;
110
111 if (format->field == V4L2_FIELD_ANY)
112 format->field = fmt_default.field;
113
114 vimc_colorimetry_clamp(format);
115
116 return 0;
117 }
118
119 static int vimc_cap_s_fmt_vid_cap(struct file *file, void *priv,
120 struct v4l2_format *f)
121 {
122 struct vimc_cap_device *vcap = video_drvdata(file);
123 int ret;
124
125
126 if (vb2_is_busy(&vcap->queue))
127 return -EBUSY;
128
129 ret = vimc_cap_try_fmt_vid_cap(file, priv, f);
130 if (ret)
131 return ret;
132
133 dev_dbg(vcap->dev, "%s: format update: "
134 "old:%dx%d (0x%x, %d, %d, %d, %d) "
135 "new:%dx%d (0x%x, %d, %d, %d, %d)\n", vcap->vdev.name,
136
137 vcap->format.width, vcap->format.height,
138 vcap->format.pixelformat, vcap->format.colorspace,
139 vcap->format.quantization, vcap->format.xfer_func,
140 vcap->format.ycbcr_enc,
141
142 f->fmt.pix.width, f->fmt.pix.height,
143 f->fmt.pix.pixelformat, f->fmt.pix.colorspace,
144 f->fmt.pix.quantization, f->fmt.pix.xfer_func,
145 f->fmt.pix.ycbcr_enc);
146
147 vcap->format = f->fmt.pix;
148
149 return 0;
150 }
151
152 static int vimc_cap_enum_fmt_vid_cap(struct file *file, void *priv,
153 struct v4l2_fmtdesc *f)
154 {
155 const struct vimc_pix_map *vpix = vimc_pix_map_by_index(f->index);
156
157 if (!vpix)
158 return -EINVAL;
159
160 f->pixelformat = vpix->pixelformat;
161
162 return 0;
163 }
164
165 static int vimc_cap_enum_framesizes(struct file *file, void *fh,
166 struct v4l2_frmsizeenum *fsize)
167 {
168 const struct vimc_pix_map *vpix;
169
170 if (fsize->index)
171 return -EINVAL;
172
173
174 vpix = vimc_pix_map_by_code(fsize->pixel_format);
175 if (!vpix)
176 return -EINVAL;
177
178 fsize->type = V4L2_FRMSIZE_TYPE_CONTINUOUS;
179 fsize->stepwise.min_width = VIMC_FRAME_MIN_WIDTH;
180 fsize->stepwise.max_width = VIMC_FRAME_MAX_WIDTH;
181 fsize->stepwise.min_height = VIMC_FRAME_MIN_HEIGHT;
182 fsize->stepwise.max_height = VIMC_FRAME_MAX_HEIGHT;
183 fsize->stepwise.step_width = 1;
184 fsize->stepwise.step_height = 1;
185
186 return 0;
187 }
188
189 static const struct v4l2_file_operations vimc_cap_fops = {
190 .owner = THIS_MODULE,
191 .open = v4l2_fh_open,
192 .release = vb2_fop_release,
193 .read = vb2_fop_read,
194 .poll = vb2_fop_poll,
195 .unlocked_ioctl = video_ioctl2,
196 .mmap = vb2_fop_mmap,
197 };
198
199 static const struct v4l2_ioctl_ops vimc_cap_ioctl_ops = {
200 .vidioc_querycap = vimc_cap_querycap,
201
202 .vidioc_g_fmt_vid_cap = vimc_cap_g_fmt_vid_cap,
203 .vidioc_s_fmt_vid_cap = vimc_cap_s_fmt_vid_cap,
204 .vidioc_try_fmt_vid_cap = vimc_cap_try_fmt_vid_cap,
205 .vidioc_enum_fmt_vid_cap = vimc_cap_enum_fmt_vid_cap,
206 .vidioc_enum_framesizes = vimc_cap_enum_framesizes,
207
208 .vidioc_reqbufs = vb2_ioctl_reqbufs,
209 .vidioc_create_bufs = vb2_ioctl_create_bufs,
210 .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
211 .vidioc_querybuf = vb2_ioctl_querybuf,
212 .vidioc_qbuf = vb2_ioctl_qbuf,
213 .vidioc_dqbuf = vb2_ioctl_dqbuf,
214 .vidioc_expbuf = vb2_ioctl_expbuf,
215 .vidioc_streamon = vb2_ioctl_streamon,
216 .vidioc_streamoff = vb2_ioctl_streamoff,
217 };
218
219 static void vimc_cap_return_all_buffers(struct vimc_cap_device *vcap,
220 enum vb2_buffer_state state)
221 {
222 struct vimc_cap_buffer *vbuf, *node;
223
224 spin_lock(&vcap->qlock);
225
226 list_for_each_entry_safe(vbuf, node, &vcap->buf_list, list) {
227 list_del(&vbuf->list);
228 vb2_buffer_done(&vbuf->vb2.vb2_buf, state);
229 }
230
231 spin_unlock(&vcap->qlock);
232 }
233
234 static int vimc_cap_start_streaming(struct vb2_queue *vq, unsigned int count)
235 {
236 struct vimc_cap_device *vcap = vb2_get_drv_priv(vq);
237 struct media_entity *entity = &vcap->vdev.entity;
238 int ret;
239
240 vcap->sequence = 0;
241
242
243 ret = media_pipeline_start(entity, &vcap->stream.pipe);
244 if (ret) {
245 vimc_cap_return_all_buffers(vcap, VB2_BUF_STATE_QUEUED);
246 return ret;
247 }
248
249 ret = vimc_streamer_s_stream(&vcap->stream, &vcap->ved, 1);
250 if (ret) {
251 media_pipeline_stop(entity);
252 vimc_cap_return_all_buffers(vcap, VB2_BUF_STATE_QUEUED);
253 return ret;
254 }
255
256 return 0;
257 }
258
259
260
261
262
263 static void vimc_cap_stop_streaming(struct vb2_queue *vq)
264 {
265 struct vimc_cap_device *vcap = vb2_get_drv_priv(vq);
266
267 vimc_streamer_s_stream(&vcap->stream, &vcap->ved, 0);
268
269
270 media_pipeline_stop(&vcap->vdev.entity);
271
272
273 vimc_cap_return_all_buffers(vcap, VB2_BUF_STATE_ERROR);
274 }
275
276 static void vimc_cap_buf_queue(struct vb2_buffer *vb2_buf)
277 {
278 struct vimc_cap_device *vcap = vb2_get_drv_priv(vb2_buf->vb2_queue);
279 struct vimc_cap_buffer *buf = container_of(vb2_buf,
280 struct vimc_cap_buffer,
281 vb2.vb2_buf);
282
283 spin_lock(&vcap->qlock);
284 list_add_tail(&buf->list, &vcap->buf_list);
285 spin_unlock(&vcap->qlock);
286 }
287
288 static int vimc_cap_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
289 unsigned int *nplanes, unsigned int sizes[],
290 struct device *alloc_devs[])
291 {
292 struct vimc_cap_device *vcap = vb2_get_drv_priv(vq);
293
294 if (*nplanes)
295 return sizes[0] < vcap->format.sizeimage ? -EINVAL : 0;
296
297 *nplanes = 1;
298 sizes[0] = vcap->format.sizeimage;
299
300 return 0;
301 }
302
303 static int vimc_cap_buffer_prepare(struct vb2_buffer *vb)
304 {
305 struct vimc_cap_device *vcap = vb2_get_drv_priv(vb->vb2_queue);
306 unsigned long size = vcap->format.sizeimage;
307
308 if (vb2_plane_size(vb, 0) < size) {
309 dev_err(vcap->dev, "%s: buffer too small (%lu < %lu)\n",
310 vcap->vdev.name, vb2_plane_size(vb, 0), size);
311 return -EINVAL;
312 }
313 return 0;
314 }
315
316 static const struct vb2_ops vimc_cap_qops = {
317 .start_streaming = vimc_cap_start_streaming,
318 .stop_streaming = vimc_cap_stop_streaming,
319 .buf_queue = vimc_cap_buf_queue,
320 .queue_setup = vimc_cap_queue_setup,
321 .buf_prepare = vimc_cap_buffer_prepare,
322
323
324
325
326 .wait_prepare = vb2_ops_wait_prepare,
327 .wait_finish = vb2_ops_wait_finish,
328 };
329
330 static const struct media_entity_operations vimc_cap_mops = {
331 .link_validate = vimc_link_validate,
332 };
333
334 static void vimc_cap_release(struct video_device *vdev)
335 {
336 struct vimc_cap_device *vcap =
337 container_of(vdev, struct vimc_cap_device, vdev);
338
339 vimc_pads_cleanup(vcap->ved.pads);
340 kfree(vcap);
341 }
342
343 static void vimc_cap_comp_unbind(struct device *comp, struct device *master,
344 void *master_data)
345 {
346 struct vimc_ent_device *ved = dev_get_drvdata(comp);
347 struct vimc_cap_device *vcap = container_of(ved, struct vimc_cap_device,
348 ved);
349
350 vb2_queue_release(&vcap->queue);
351 media_entity_cleanup(ved->ent);
352 video_unregister_device(&vcap->vdev);
353 }
354
355 static void *vimc_cap_process_frame(struct vimc_ent_device *ved,
356 const void *frame)
357 {
358 struct vimc_cap_device *vcap = container_of(ved, struct vimc_cap_device,
359 ved);
360 struct vimc_cap_buffer *vimc_buf;
361 void *vbuf;
362
363 spin_lock(&vcap->qlock);
364
365
366 vimc_buf = list_first_entry_or_null(&vcap->buf_list,
367 typeof(*vimc_buf), list);
368 if (!vimc_buf) {
369 spin_unlock(&vcap->qlock);
370 return ERR_PTR(-EAGAIN);
371 }
372
373
374 list_del(&vimc_buf->list);
375
376 spin_unlock(&vcap->qlock);
377
378
379 vimc_buf->vb2.vb2_buf.timestamp = ktime_get_ns();
380 vimc_buf->vb2.sequence = vcap->sequence++;
381 vimc_buf->vb2.field = vcap->format.field;
382
383 vbuf = vb2_plane_vaddr(&vimc_buf->vb2.vb2_buf, 0);
384
385 memcpy(vbuf, frame, vcap->format.sizeimage);
386
387
388 vb2_set_plane_payload(&vimc_buf->vb2.vb2_buf, 0,
389 vcap->format.sizeimage);
390 vb2_buffer_done(&vimc_buf->vb2.vb2_buf, VB2_BUF_STATE_DONE);
391 return NULL;
392 }
393
394 static int vimc_cap_comp_bind(struct device *comp, struct device *master,
395 void *master_data)
396 {
397 struct v4l2_device *v4l2_dev = master_data;
398 struct vimc_platform_data *pdata = comp->platform_data;
399 const struct vimc_pix_map *vpix;
400 struct vimc_cap_device *vcap;
401 struct video_device *vdev;
402 struct vb2_queue *q;
403 int ret;
404
405
406 vcap = kzalloc(sizeof(*vcap), GFP_KERNEL);
407 if (!vcap)
408 return -ENOMEM;
409
410
411 vcap->ved.pads =
412 vimc_pads_init(1, (const unsigned long[1]) {MEDIA_PAD_FL_SINK});
413 if (IS_ERR(vcap->ved.pads)) {
414 ret = PTR_ERR(vcap->ved.pads);
415 goto err_free_vcap;
416 }
417
418
419 vcap->vdev.entity.name = pdata->entity_name;
420 vcap->vdev.entity.function = MEDIA_ENT_F_IO_V4L;
421 ret = media_entity_pads_init(&vcap->vdev.entity,
422 1, vcap->ved.pads);
423 if (ret)
424 goto err_clean_pads;
425
426
427 mutex_init(&vcap->lock);
428
429
430 q = &vcap->queue;
431 q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
432 q->io_modes = VB2_MMAP | VB2_DMABUF | VB2_USERPTR;
433 q->drv_priv = vcap;
434 q->buf_struct_size = sizeof(struct vimc_cap_buffer);
435 q->ops = &vimc_cap_qops;
436 q->mem_ops = &vb2_vmalloc_memops;
437 q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
438 q->min_buffers_needed = 2;
439 q->lock = &vcap->lock;
440
441 ret = vb2_queue_init(q);
442 if (ret) {
443 dev_err(comp, "%s: vb2 queue init failed (err=%d)\n",
444 pdata->entity_name, ret);
445 goto err_clean_m_ent;
446 }
447
448
449 INIT_LIST_HEAD(&vcap->buf_list);
450 spin_lock_init(&vcap->qlock);
451
452
453 vcap->format = fmt_default;
454 vpix = vimc_pix_map_by_pixelformat(vcap->format.pixelformat);
455 vcap->format.bytesperline = vcap->format.width * vpix->bpp;
456 vcap->format.sizeimage = vcap->format.bytesperline *
457 vcap->format.height;
458
459
460 vcap->ved.ent = &vcap->vdev.entity;
461 vcap->ved.process_frame = vimc_cap_process_frame;
462 vcap->ved.vdev_get_format = vimc_cap_get_format;
463 dev_set_drvdata(comp, &vcap->ved);
464 vcap->dev = comp;
465
466
467 vdev = &vcap->vdev;
468 vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
469 vdev->entity.ops = &vimc_cap_mops;
470 vdev->release = vimc_cap_release;
471 vdev->fops = &vimc_cap_fops;
472 vdev->ioctl_ops = &vimc_cap_ioctl_ops;
473 vdev->lock = &vcap->lock;
474 vdev->queue = q;
475 vdev->v4l2_dev = v4l2_dev;
476 vdev->vfl_dir = VFL_DIR_RX;
477 strscpy(vdev->name, pdata->entity_name, sizeof(vdev->name));
478 video_set_drvdata(vdev, &vcap->ved);
479
480
481 ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
482 if (ret) {
483 dev_err(comp, "%s: video register failed (err=%d)\n",
484 vcap->vdev.name, ret);
485 goto err_release_queue;
486 }
487
488 return 0;
489
490 err_release_queue:
491 vb2_queue_release(q);
492 err_clean_m_ent:
493 media_entity_cleanup(&vcap->vdev.entity);
494 err_clean_pads:
495 vimc_pads_cleanup(vcap->ved.pads);
496 err_free_vcap:
497 kfree(vcap);
498
499 return ret;
500 }
501
502 static const struct component_ops vimc_cap_comp_ops = {
503 .bind = vimc_cap_comp_bind,
504 .unbind = vimc_cap_comp_unbind,
505 };
506
507 static int vimc_cap_probe(struct platform_device *pdev)
508 {
509 return component_add(&pdev->dev, &vimc_cap_comp_ops);
510 }
511
512 static int vimc_cap_remove(struct platform_device *pdev)
513 {
514 component_del(&pdev->dev, &vimc_cap_comp_ops);
515
516 return 0;
517 }
518
519 static const struct platform_device_id vimc_cap_driver_ids[] = {
520 {
521 .name = VIMC_CAP_DRV_NAME,
522 },
523 { }
524 };
525
526 static struct platform_driver vimc_cap_pdrv = {
527 .probe = vimc_cap_probe,
528 .remove = vimc_cap_remove,
529 .id_table = vimc_cap_driver_ids,
530 .driver = {
531 .name = VIMC_CAP_DRV_NAME,
532 },
533 };
534
535 module_platform_driver(vimc_cap_pdrv);
536
537 MODULE_DEVICE_TABLE(platform, vimc_cap_driver_ids);
538
539 MODULE_DESCRIPTION("Virtual Media Controller Driver (VIMC) Capture");
540 MODULE_AUTHOR("Helen Mae Koike Fornazier <helen.fornazier@gmail.com>");
541 MODULE_LICENSE("GPL");