1 // SPDX-License-Identifier: GPL-2.0+
3 * vsp1_histo.c -- R-Car VSP1 Histogram API
5 * Copyright (C) 2016 Renesas Electronics Corporation
6 * Copyright (C) 2016 Laurent Pinchart
8 * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
11 #include <linux/device.h>
12 #include <linux/gfp.h>
14 #include <media/v4l2-ioctl.h>
15 #include <media/v4l2-subdev.h>
16 #include <media/videobuf2-vmalloc.h>
19 #include "vsp1_histo.h"
20 #include "vsp1_pipe.h"
22 #define HISTO_MIN_SIZE 4U
23 #define HISTO_MAX_SIZE 8192U
25 /* -----------------------------------------------------------------------------
29 static inline struct vsp1_histogram_buffer
*
30 to_vsp1_histogram_buffer(struct vb2_v4l2_buffer
*vbuf
)
32 return container_of(vbuf
, struct vsp1_histogram_buffer
, buf
);
35 struct vsp1_histogram_buffer
*
36 vsp1_histogram_buffer_get(struct vsp1_histogram
*histo
)
38 struct vsp1_histogram_buffer
*buf
= NULL
;
41 spin_lock_irqsave(&histo
->irqlock
, flags
);
43 if (list_empty(&histo
->irqqueue
))
46 buf
= list_first_entry(&histo
->irqqueue
, struct vsp1_histogram_buffer
,
48 list_del(&buf
->queue
);
49 histo
->readout
= true;
52 spin_unlock_irqrestore(&histo
->irqlock
, flags
);
56 void vsp1_histogram_buffer_complete(struct vsp1_histogram
*histo
,
57 struct vsp1_histogram_buffer
*buf
,
60 struct vsp1_pipeline
*pipe
= histo
->entity
.pipe
;
64 * The pipeline pointer is guaranteed to be valid as this function is
65 * called from the frame completion interrupt handler, which can only
66 * occur when video streaming is active.
68 buf
->buf
.sequence
= pipe
->sequence
;
69 buf
->buf
.vb2_buf
.timestamp
= ktime_get_ns();
70 vb2_set_plane_payload(&buf
->buf
.vb2_buf
, 0, size
);
71 vb2_buffer_done(&buf
->buf
.vb2_buf
, VB2_BUF_STATE_DONE
);
73 spin_lock_irqsave(&histo
->irqlock
, flags
);
74 histo
->readout
= false;
75 wake_up(&histo
->wait_queue
);
76 spin_unlock_irqrestore(&histo
->irqlock
, flags
);
79 /* -----------------------------------------------------------------------------
80 * videobuf2 Queue Operations
83 static int histo_queue_setup(struct vb2_queue
*vq
, unsigned int *nbuffers
,
84 unsigned int *nplanes
, unsigned int sizes
[],
85 struct device
*alloc_devs
[])
87 struct vsp1_histogram
*histo
= vb2_get_drv_priv(vq
);
93 if (sizes
[0] < histo
->data_size
)
100 sizes
[0] = histo
->data_size
;
105 static int histo_buffer_prepare(struct vb2_buffer
*vb
)
107 struct vb2_v4l2_buffer
*vbuf
= to_vb2_v4l2_buffer(vb
);
108 struct vsp1_histogram
*histo
= vb2_get_drv_priv(vb
->vb2_queue
);
109 struct vsp1_histogram_buffer
*buf
= to_vsp1_histogram_buffer(vbuf
);
111 if (vb
->num_planes
!= 1)
114 if (vb2_plane_size(vb
, 0) < histo
->data_size
)
117 buf
->addr
= vb2_plane_vaddr(vb
, 0);
122 static void histo_buffer_queue(struct vb2_buffer
*vb
)
124 struct vb2_v4l2_buffer
*vbuf
= to_vb2_v4l2_buffer(vb
);
125 struct vsp1_histogram
*histo
= vb2_get_drv_priv(vb
->vb2_queue
);
126 struct vsp1_histogram_buffer
*buf
= to_vsp1_histogram_buffer(vbuf
);
129 spin_lock_irqsave(&histo
->irqlock
, flags
);
130 list_add_tail(&buf
->queue
, &histo
->irqqueue
);
131 spin_unlock_irqrestore(&histo
->irqlock
, flags
);
134 static int histo_start_streaming(struct vb2_queue
*vq
, unsigned int count
)
139 static void histo_stop_streaming(struct vb2_queue
*vq
)
141 struct vsp1_histogram
*histo
= vb2_get_drv_priv(vq
);
142 struct vsp1_histogram_buffer
*buffer
;
145 spin_lock_irqsave(&histo
->irqlock
, flags
);
147 /* Remove all buffers from the IRQ queue. */
148 list_for_each_entry(buffer
, &histo
->irqqueue
, queue
)
149 vb2_buffer_done(&buffer
->buf
.vb2_buf
, VB2_BUF_STATE_ERROR
);
150 INIT_LIST_HEAD(&histo
->irqqueue
);
152 /* Wait for the buffer being read out (if any) to complete. */
153 wait_event_lock_irq(histo
->wait_queue
, !histo
->readout
, histo
->irqlock
);
155 spin_unlock_irqrestore(&histo
->irqlock
, flags
);
158 static const struct vb2_ops histo_video_queue_qops
= {
159 .queue_setup
= histo_queue_setup
,
160 .buf_prepare
= histo_buffer_prepare
,
161 .buf_queue
= histo_buffer_queue
,
162 .wait_prepare
= vb2_ops_wait_prepare
,
163 .wait_finish
= vb2_ops_wait_finish
,
164 .start_streaming
= histo_start_streaming
,
165 .stop_streaming
= histo_stop_streaming
,
168 /* -----------------------------------------------------------------------------
169 * V4L2 Subdevice Operations
172 static int histo_enum_mbus_code(struct v4l2_subdev
*subdev
,
173 struct v4l2_subdev_pad_config
*cfg
,
174 struct v4l2_subdev_mbus_code_enum
*code
)
176 struct vsp1_histogram
*histo
= subdev_to_histo(subdev
);
178 if (code
->pad
== HISTO_PAD_SOURCE
) {
179 code
->code
= MEDIA_BUS_FMT_FIXED
;
183 return vsp1_subdev_enum_mbus_code(subdev
, cfg
, code
, histo
->formats
,
187 static int histo_enum_frame_size(struct v4l2_subdev
*subdev
,
188 struct v4l2_subdev_pad_config
*cfg
,
189 struct v4l2_subdev_frame_size_enum
*fse
)
191 if (fse
->pad
!= HISTO_PAD_SINK
)
194 return vsp1_subdev_enum_frame_size(subdev
, cfg
, fse
, HISTO_MIN_SIZE
,
195 HISTO_MIN_SIZE
, HISTO_MAX_SIZE
,
199 static int histo_get_selection(struct v4l2_subdev
*subdev
,
200 struct v4l2_subdev_pad_config
*cfg
,
201 struct v4l2_subdev_selection
*sel
)
203 struct vsp1_histogram
*histo
= subdev_to_histo(subdev
);
204 struct v4l2_subdev_pad_config
*config
;
205 struct v4l2_mbus_framefmt
*format
;
206 struct v4l2_rect
*crop
;
209 if (sel
->pad
!= HISTO_PAD_SINK
)
212 mutex_lock(&histo
->entity
.lock
);
214 config
= vsp1_entity_get_pad_config(&histo
->entity
, cfg
, sel
->which
);
220 switch (sel
->target
) {
221 case V4L2_SEL_TGT_COMPOSE_BOUNDS
:
222 case V4L2_SEL_TGT_COMPOSE_DEFAULT
:
223 crop
= vsp1_entity_get_pad_selection(&histo
->entity
, config
,
228 sel
->r
.width
= crop
->width
;
229 sel
->r
.height
= crop
->height
;
232 case V4L2_SEL_TGT_CROP_BOUNDS
:
233 case V4L2_SEL_TGT_CROP_DEFAULT
:
234 format
= vsp1_entity_get_pad_format(&histo
->entity
, config
,
238 sel
->r
.width
= format
->width
;
239 sel
->r
.height
= format
->height
;
242 case V4L2_SEL_TGT_COMPOSE
:
243 case V4L2_SEL_TGT_CROP
:
244 sel
->r
= *vsp1_entity_get_pad_selection(&histo
->entity
, config
,
245 sel
->pad
, sel
->target
);
254 mutex_unlock(&histo
->entity
.lock
);
258 static int histo_set_crop(struct v4l2_subdev
*subdev
,
259 struct v4l2_subdev_pad_config
*config
,
260 struct v4l2_subdev_selection
*sel
)
262 struct vsp1_histogram
*histo
= subdev_to_histo(subdev
);
263 struct v4l2_mbus_framefmt
*format
;
264 struct v4l2_rect
*selection
;
266 /* The crop rectangle must be inside the input frame. */
267 format
= vsp1_entity_get_pad_format(&histo
->entity
, config
,
269 sel
->r
.left
= clamp_t(unsigned int, sel
->r
.left
, 0, format
->width
- 1);
270 sel
->r
.top
= clamp_t(unsigned int, sel
->r
.top
, 0, format
->height
- 1);
271 sel
->r
.width
= clamp_t(unsigned int, sel
->r
.width
, HISTO_MIN_SIZE
,
272 format
->width
- sel
->r
.left
);
273 sel
->r
.height
= clamp_t(unsigned int, sel
->r
.height
, HISTO_MIN_SIZE
,
274 format
->height
- sel
->r
.top
);
276 /* Set the crop rectangle and reset the compose rectangle. */
277 selection
= vsp1_entity_get_pad_selection(&histo
->entity
, config
,
278 sel
->pad
, V4L2_SEL_TGT_CROP
);
281 selection
= vsp1_entity_get_pad_selection(&histo
->entity
, config
,
283 V4L2_SEL_TGT_COMPOSE
);
289 static int histo_set_compose(struct v4l2_subdev
*subdev
,
290 struct v4l2_subdev_pad_config
*config
,
291 struct v4l2_subdev_selection
*sel
)
293 struct vsp1_histogram
*histo
= subdev_to_histo(subdev
);
294 struct v4l2_rect
*compose
;
295 struct v4l2_rect
*crop
;
299 * The compose rectangle is used to configure downscaling, the top left
300 * corner is fixed to (0,0) and the size to 1/2 or 1/4 of the crop
306 crop
= vsp1_entity_get_pad_selection(&histo
->entity
, config
, sel
->pad
,
310 * Clamp the width and height to acceptable values first and then
311 * compute the closest rounded dividing ratio.
313 * Ratio Rounded ratio
314 * --------------------------
319 * The rounded ratio can be computed using
321 * 1 << (ceil(ratio * 2) / 3)
323 sel
->r
.width
= clamp(sel
->r
.width
, crop
->width
/ 4, crop
->width
);
324 ratio
= 1 << (crop
->width
* 2 / sel
->r
.width
/ 3);
325 sel
->r
.width
= crop
->width
/ ratio
;
328 sel
->r
.height
= clamp(sel
->r
.height
, crop
->height
/ 4, crop
->height
);
329 ratio
= 1 << (crop
->height
* 2 / sel
->r
.height
/ 3);
330 sel
->r
.height
= crop
->height
/ ratio
;
332 compose
= vsp1_entity_get_pad_selection(&histo
->entity
, config
,
334 V4L2_SEL_TGT_COMPOSE
);
340 static int histo_set_selection(struct v4l2_subdev
*subdev
,
341 struct v4l2_subdev_pad_config
*cfg
,
342 struct v4l2_subdev_selection
*sel
)
344 struct vsp1_histogram
*histo
= subdev_to_histo(subdev
);
345 struct v4l2_subdev_pad_config
*config
;
348 if (sel
->pad
!= HISTO_PAD_SINK
)
351 mutex_lock(&histo
->entity
.lock
);
353 config
= vsp1_entity_get_pad_config(&histo
->entity
, cfg
, sel
->which
);
359 if (sel
->target
== V4L2_SEL_TGT_CROP
)
360 ret
= histo_set_crop(subdev
, config
, sel
);
361 else if (sel
->target
== V4L2_SEL_TGT_COMPOSE
)
362 ret
= histo_set_compose(subdev
, config
, sel
);
367 mutex_unlock(&histo
->entity
.lock
);
371 static int histo_get_format(struct v4l2_subdev
*subdev
,
372 struct v4l2_subdev_pad_config
*cfg
,
373 struct v4l2_subdev_format
*fmt
)
375 if (fmt
->pad
== HISTO_PAD_SOURCE
) {
376 fmt
->format
.code
= MEDIA_BUS_FMT_FIXED
;
377 fmt
->format
.width
= 0;
378 fmt
->format
.height
= 0;
379 fmt
->format
.field
= V4L2_FIELD_NONE
;
380 fmt
->format
.colorspace
= V4L2_COLORSPACE_RAW
;
384 return vsp1_subdev_get_pad_format(subdev
, cfg
, fmt
);
387 static int histo_set_format(struct v4l2_subdev
*subdev
,
388 struct v4l2_subdev_pad_config
*cfg
,
389 struct v4l2_subdev_format
*fmt
)
391 struct vsp1_histogram
*histo
= subdev_to_histo(subdev
);
393 if (fmt
->pad
!= HISTO_PAD_SINK
)
394 return histo_get_format(subdev
, cfg
, fmt
);
396 return vsp1_subdev_set_pad_format(subdev
, cfg
, fmt
,
397 histo
->formats
, histo
->num_formats
,
398 HISTO_MIN_SIZE
, HISTO_MIN_SIZE
,
399 HISTO_MAX_SIZE
, HISTO_MAX_SIZE
);
402 static const struct v4l2_subdev_pad_ops histo_pad_ops
= {
403 .enum_mbus_code
= histo_enum_mbus_code
,
404 .enum_frame_size
= histo_enum_frame_size
,
405 .get_fmt
= histo_get_format
,
406 .set_fmt
= histo_set_format
,
407 .get_selection
= histo_get_selection
,
408 .set_selection
= histo_set_selection
,
411 static const struct v4l2_subdev_ops histo_ops
= {
412 .pad
= &histo_pad_ops
,
415 /* -----------------------------------------------------------------------------
419 static int histo_v4l2_querycap(struct file
*file
, void *fh
,
420 struct v4l2_capability
*cap
)
422 struct v4l2_fh
*vfh
= file
->private_data
;
423 struct vsp1_histogram
*histo
= vdev_to_histo(vfh
->vdev
);
425 cap
->capabilities
= V4L2_CAP_DEVICE_CAPS
| V4L2_CAP_STREAMING
426 | V4L2_CAP_VIDEO_CAPTURE_MPLANE
427 | V4L2_CAP_VIDEO_OUTPUT_MPLANE
428 | V4L2_CAP_META_CAPTURE
;
430 strscpy(cap
->driver
, "vsp1", sizeof(cap
->driver
));
431 strscpy(cap
->card
, histo
->video
.name
, sizeof(cap
->card
));
432 snprintf(cap
->bus_info
, sizeof(cap
->bus_info
), "platform:%s",
433 dev_name(histo
->entity
.vsp1
->dev
));
438 static int histo_v4l2_enum_format(struct file
*file
, void *fh
,
439 struct v4l2_fmtdesc
*f
)
441 struct v4l2_fh
*vfh
= file
->private_data
;
442 struct vsp1_histogram
*histo
= vdev_to_histo(vfh
->vdev
);
444 if (f
->index
> 0 || f
->type
!= histo
->queue
.type
)
447 f
->pixelformat
= histo
->meta_format
;
452 static int histo_v4l2_get_format(struct file
*file
, void *fh
,
453 struct v4l2_format
*format
)
455 struct v4l2_fh
*vfh
= file
->private_data
;
456 struct vsp1_histogram
*histo
= vdev_to_histo(vfh
->vdev
);
457 struct v4l2_meta_format
*meta
= &format
->fmt
.meta
;
459 if (format
->type
!= histo
->queue
.type
)
462 memset(meta
, 0, sizeof(*meta
));
464 meta
->dataformat
= histo
->meta_format
;
465 meta
->buffersize
= histo
->data_size
;
470 static const struct v4l2_ioctl_ops histo_v4l2_ioctl_ops
= {
471 .vidioc_querycap
= histo_v4l2_querycap
,
472 .vidioc_enum_fmt_meta_cap
= histo_v4l2_enum_format
,
473 .vidioc_g_fmt_meta_cap
= histo_v4l2_get_format
,
474 .vidioc_s_fmt_meta_cap
= histo_v4l2_get_format
,
475 .vidioc_try_fmt_meta_cap
= histo_v4l2_get_format
,
476 .vidioc_reqbufs
= vb2_ioctl_reqbufs
,
477 .vidioc_querybuf
= vb2_ioctl_querybuf
,
478 .vidioc_qbuf
= vb2_ioctl_qbuf
,
479 .vidioc_dqbuf
= vb2_ioctl_dqbuf
,
480 .vidioc_create_bufs
= vb2_ioctl_create_bufs
,
481 .vidioc_prepare_buf
= vb2_ioctl_prepare_buf
,
482 .vidioc_streamon
= vb2_ioctl_streamon
,
483 .vidioc_streamoff
= vb2_ioctl_streamoff
,
486 /* -----------------------------------------------------------------------------
487 * V4L2 File Operations
490 static const struct v4l2_file_operations histo_v4l2_fops
= {
491 .owner
= THIS_MODULE
,
492 .unlocked_ioctl
= video_ioctl2
,
493 .open
= v4l2_fh_open
,
494 .release
= vb2_fop_release
,
495 .poll
= vb2_fop_poll
,
496 .mmap
= vb2_fop_mmap
,
499 static void vsp1_histogram_cleanup(struct vsp1_histogram
*histo
)
501 if (video_is_registered(&histo
->video
))
502 video_unregister_device(&histo
->video
);
504 media_entity_cleanup(&histo
->video
.entity
);
507 void vsp1_histogram_destroy(struct vsp1_entity
*entity
)
509 struct vsp1_histogram
*histo
= subdev_to_histo(&entity
->subdev
);
511 vsp1_histogram_cleanup(histo
);
514 int vsp1_histogram_init(struct vsp1_device
*vsp1
, struct vsp1_histogram
*histo
,
515 enum vsp1_entity_type type
, const char *name
,
516 const struct vsp1_entity_operations
*ops
,
517 const unsigned int *formats
, unsigned int num_formats
,
518 size_t data_size
, u32 meta_format
)
522 histo
->formats
= formats
;
523 histo
->num_formats
= num_formats
;
524 histo
->data_size
= data_size
;
525 histo
->meta_format
= meta_format
;
527 histo
->pad
.flags
= MEDIA_PAD_FL_SINK
;
528 histo
->video
.vfl_dir
= VFL_DIR_RX
;
530 mutex_init(&histo
->lock
);
531 spin_lock_init(&histo
->irqlock
);
532 INIT_LIST_HEAD(&histo
->irqqueue
);
533 init_waitqueue_head(&histo
->wait_queue
);
535 /* Initialize the VSP entity... */
536 histo
->entity
.ops
= ops
;
537 histo
->entity
.type
= type
;
539 ret
= vsp1_entity_init(vsp1
, &histo
->entity
, name
, 2, &histo_ops
,
540 MEDIA_ENT_F_PROC_VIDEO_STATISTICS
);
544 /* ... and the media entity... */
545 ret
= media_entity_pads_init(&histo
->video
.entity
, 1, &histo
->pad
);
549 /* ... and the video node... */
550 histo
->video
.v4l2_dev
= &vsp1
->v4l2_dev
;
551 histo
->video
.fops
= &histo_v4l2_fops
;
552 snprintf(histo
->video
.name
, sizeof(histo
->video
.name
),
553 "%s histo", histo
->entity
.subdev
.name
);
554 histo
->video
.vfl_type
= VFL_TYPE_VIDEO
;
555 histo
->video
.release
= video_device_release_empty
;
556 histo
->video
.ioctl_ops
= &histo_v4l2_ioctl_ops
;
557 histo
->video
.device_caps
= V4L2_CAP_META_CAPTURE
| V4L2_CAP_STREAMING
;
559 video_set_drvdata(&histo
->video
, histo
);
561 /* ... and the buffers queue... */
562 histo
->queue
.type
= V4L2_BUF_TYPE_META_CAPTURE
;
563 histo
->queue
.io_modes
= VB2_MMAP
| VB2_USERPTR
| VB2_DMABUF
;
564 histo
->queue
.lock
= &histo
->lock
;
565 histo
->queue
.drv_priv
= histo
;
566 histo
->queue
.buf_struct_size
= sizeof(struct vsp1_histogram_buffer
);
567 histo
->queue
.ops
= &histo_video_queue_qops
;
568 histo
->queue
.mem_ops
= &vb2_vmalloc_memops
;
569 histo
->queue
.timestamp_flags
= V4L2_BUF_FLAG_TIMESTAMP_COPY
;
570 histo
->queue
.dev
= vsp1
->dev
;
571 ret
= vb2_queue_init(&histo
->queue
);
573 dev_err(vsp1
->dev
, "failed to initialize vb2 queue\n");
577 /* ... and register the video device. */
578 histo
->video
.queue
= &histo
->queue
;
579 ret
= video_register_device(&histo
->video
, VFL_TYPE_VIDEO
, -1);
581 dev_err(vsp1
->dev
, "failed to register video device\n");
588 vsp1_histogram_cleanup(histo
);