Merge tag 'block-5.11-2021-01-10' of git://git.kernel.dk/linux-block
[linux/fpc-iii.git] / drivers / media / platform / sunxi / sun6i-csi / sun6i_video.c
blobb55de9ab64d8b3f3c83452d1db2a8b33d939c0b4
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright (c) 2011-2018 Magewell Electronics Co., Ltd. (Nanjing)
4 * All rights reserved.
5 * Author: Yong Deng <yong.deng@magewell.com>
6 */
8 #include <linux/of.h>
10 #include <media/v4l2-device.h>
11 #include <media/v4l2-event.h>
12 #include <media/v4l2-ioctl.h>
13 #include <media/v4l2-mc.h>
14 #include <media/videobuf2-dma-contig.h>
15 #include <media/videobuf2-v4l2.h>
17 #include "sun6i_csi.h"
18 #include "sun6i_video.h"
20 /* This is got from BSP sources. */
21 #define MIN_WIDTH (32)
22 #define MIN_HEIGHT (32)
23 #define MAX_WIDTH (4800)
24 #define MAX_HEIGHT (4800)
26 struct sun6i_csi_buffer {
27 struct vb2_v4l2_buffer vb;
28 struct list_head list;
30 dma_addr_t dma_addr;
31 bool queued_to_csi;
34 static const u32 supported_pixformats[] = {
35 V4L2_PIX_FMT_SBGGR8,
36 V4L2_PIX_FMT_SGBRG8,
37 V4L2_PIX_FMT_SGRBG8,
38 V4L2_PIX_FMT_SRGGB8,
39 V4L2_PIX_FMT_SBGGR10,
40 V4L2_PIX_FMT_SGBRG10,
41 V4L2_PIX_FMT_SGRBG10,
42 V4L2_PIX_FMT_SRGGB10,
43 V4L2_PIX_FMT_SBGGR12,
44 V4L2_PIX_FMT_SGBRG12,
45 V4L2_PIX_FMT_SGRBG12,
46 V4L2_PIX_FMT_SRGGB12,
47 V4L2_PIX_FMT_YUYV,
48 V4L2_PIX_FMT_YVYU,
49 V4L2_PIX_FMT_UYVY,
50 V4L2_PIX_FMT_VYUY,
51 V4L2_PIX_FMT_HM12,
52 V4L2_PIX_FMT_NV12,
53 V4L2_PIX_FMT_NV21,
54 V4L2_PIX_FMT_YUV420,
55 V4L2_PIX_FMT_YVU420,
56 V4L2_PIX_FMT_NV16,
57 V4L2_PIX_FMT_NV61,
58 V4L2_PIX_FMT_YUV422P,
59 V4L2_PIX_FMT_RGB565,
60 V4L2_PIX_FMT_RGB565X,
61 V4L2_PIX_FMT_JPEG,
64 static bool is_pixformat_valid(unsigned int pixformat)
66 unsigned int i;
68 for (i = 0; i < ARRAY_SIZE(supported_pixformats); i++)
69 if (supported_pixformats[i] == pixformat)
70 return true;
72 return false;
75 static struct v4l2_subdev *
76 sun6i_video_remote_subdev(struct sun6i_video *video, u32 *pad)
78 struct media_pad *remote;
80 remote = media_entity_remote_pad(&video->pad);
82 if (!remote || !is_media_entity_v4l2_subdev(remote->entity))
83 return NULL;
85 if (pad)
86 *pad = remote->index;
88 return media_entity_to_v4l2_subdev(remote->entity);
91 static int sun6i_video_queue_setup(struct vb2_queue *vq,
92 unsigned int *nbuffers,
93 unsigned int *nplanes,
94 unsigned int sizes[],
95 struct device *alloc_devs[])
97 struct sun6i_video *video = vb2_get_drv_priv(vq);
98 unsigned int size = video->fmt.fmt.pix.sizeimage;
100 if (*nplanes)
101 return sizes[0] < size ? -EINVAL : 0;
103 *nplanes = 1;
104 sizes[0] = size;
106 return 0;
109 static int sun6i_video_buffer_prepare(struct vb2_buffer *vb)
111 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
112 struct sun6i_csi_buffer *buf =
113 container_of(vbuf, struct sun6i_csi_buffer, vb);
114 struct sun6i_video *video = vb2_get_drv_priv(vb->vb2_queue);
115 unsigned long size = video->fmt.fmt.pix.sizeimage;
117 if (vb2_plane_size(vb, 0) < size) {
118 v4l2_err(video->vdev.v4l2_dev, "buffer too small (%lu < %lu)\n",
119 vb2_plane_size(vb, 0), size);
120 return -EINVAL;
123 vb2_set_plane_payload(vb, 0, size);
125 buf->dma_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
127 vbuf->field = video->fmt.fmt.pix.field;
129 return 0;
132 static int sun6i_video_start_streaming(struct vb2_queue *vq, unsigned int count)
134 struct sun6i_video *video = vb2_get_drv_priv(vq);
135 struct sun6i_csi_buffer *buf;
136 struct sun6i_csi_buffer *next_buf;
137 struct sun6i_csi_config config;
138 struct v4l2_subdev *subdev;
139 unsigned long flags;
140 int ret;
142 video->sequence = 0;
144 ret = media_pipeline_start(&video->vdev.entity, &video->vdev.pipe);
145 if (ret < 0)
146 goto clear_dma_queue;
148 if (video->mbus_code == 0) {
149 ret = -EINVAL;
150 goto stop_media_pipeline;
153 subdev = sun6i_video_remote_subdev(video, NULL);
154 if (!subdev)
155 goto stop_media_pipeline;
157 config.pixelformat = video->fmt.fmt.pix.pixelformat;
158 config.code = video->mbus_code;
159 config.field = video->fmt.fmt.pix.field;
160 config.width = video->fmt.fmt.pix.width;
161 config.height = video->fmt.fmt.pix.height;
163 ret = sun6i_csi_update_config(video->csi, &config);
164 if (ret < 0)
165 goto stop_media_pipeline;
167 spin_lock_irqsave(&video->dma_queue_lock, flags);
169 buf = list_first_entry(&video->dma_queue,
170 struct sun6i_csi_buffer, list);
171 buf->queued_to_csi = true;
172 sun6i_csi_update_buf_addr(video->csi, buf->dma_addr);
174 sun6i_csi_set_stream(video->csi, true);
177 * CSI will lookup the next dma buffer for next frame before the
178 * the current frame done IRQ triggered. This is not documented
179 * but reported by Ondřej Jirman.
180 * The BSP code has workaround for this too. It skip to mark the
181 * first buffer as frame done for VB2 and pass the second buffer
182 * to CSI in the first frame done ISR call. Then in second frame
183 * done ISR call, it mark the first buffer as frame done for VB2
184 * and pass the third buffer to CSI. And so on. The bad thing is
185 * that the first buffer will be written twice and the first frame
186 * is dropped even the queued buffer is sufficient.
187 * So, I make some improvement here. Pass the next buffer to CSI
188 * just follow starting the CSI. In this case, the first frame
189 * will be stored in first buffer, second frame in second buffer.
190 * This method is used to avoid dropping the first frame, it
191 * would also drop frame when lacking of queued buffer.
193 next_buf = list_next_entry(buf, list);
194 next_buf->queued_to_csi = true;
195 sun6i_csi_update_buf_addr(video->csi, next_buf->dma_addr);
197 spin_unlock_irqrestore(&video->dma_queue_lock, flags);
199 ret = v4l2_subdev_call(subdev, video, s_stream, 1);
200 if (ret && ret != -ENOIOCTLCMD)
201 goto stop_csi_stream;
203 return 0;
205 stop_csi_stream:
206 sun6i_csi_set_stream(video->csi, false);
207 stop_media_pipeline:
208 media_pipeline_stop(&video->vdev.entity);
209 clear_dma_queue:
210 spin_lock_irqsave(&video->dma_queue_lock, flags);
211 list_for_each_entry(buf, &video->dma_queue, list)
212 vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED);
213 INIT_LIST_HEAD(&video->dma_queue);
214 spin_unlock_irqrestore(&video->dma_queue_lock, flags);
216 return ret;
219 static void sun6i_video_stop_streaming(struct vb2_queue *vq)
221 struct sun6i_video *video = vb2_get_drv_priv(vq);
222 struct v4l2_subdev *subdev;
223 unsigned long flags;
224 struct sun6i_csi_buffer *buf;
226 subdev = sun6i_video_remote_subdev(video, NULL);
227 if (subdev)
228 v4l2_subdev_call(subdev, video, s_stream, 0);
230 sun6i_csi_set_stream(video->csi, false);
232 media_pipeline_stop(&video->vdev.entity);
234 /* Release all active buffers */
235 spin_lock_irqsave(&video->dma_queue_lock, flags);
236 list_for_each_entry(buf, &video->dma_queue, list)
237 vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
238 INIT_LIST_HEAD(&video->dma_queue);
239 spin_unlock_irqrestore(&video->dma_queue_lock, flags);
242 static void sun6i_video_buffer_queue(struct vb2_buffer *vb)
244 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
245 struct sun6i_csi_buffer *buf =
246 container_of(vbuf, struct sun6i_csi_buffer, vb);
247 struct sun6i_video *video = vb2_get_drv_priv(vb->vb2_queue);
248 unsigned long flags;
250 spin_lock_irqsave(&video->dma_queue_lock, flags);
251 buf->queued_to_csi = false;
252 list_add_tail(&buf->list, &video->dma_queue);
253 spin_unlock_irqrestore(&video->dma_queue_lock, flags);
256 void sun6i_video_frame_done(struct sun6i_video *video)
258 struct sun6i_csi_buffer *buf;
259 struct sun6i_csi_buffer *next_buf;
260 struct vb2_v4l2_buffer *vbuf;
262 spin_lock(&video->dma_queue_lock);
264 buf = list_first_entry(&video->dma_queue,
265 struct sun6i_csi_buffer, list);
266 if (list_is_last(&buf->list, &video->dma_queue)) {
267 dev_dbg(video->csi->dev, "Frame dropped!\n");
268 goto unlock;
271 next_buf = list_next_entry(buf, list);
272 /* If a new buffer (#next_buf) had not been queued to CSI, the old
273 * buffer (#buf) is still holding by CSI for storing the next
274 * frame. So, we queue a new buffer (#next_buf) to CSI then wait
275 * for next ISR call.
277 if (!next_buf->queued_to_csi) {
278 next_buf->queued_to_csi = true;
279 sun6i_csi_update_buf_addr(video->csi, next_buf->dma_addr);
280 dev_dbg(video->csi->dev, "Frame dropped!\n");
281 goto unlock;
284 list_del(&buf->list);
285 vbuf = &buf->vb;
286 vbuf->vb2_buf.timestamp = ktime_get_ns();
287 vbuf->sequence = video->sequence;
288 vb2_buffer_done(&vbuf->vb2_buf, VB2_BUF_STATE_DONE);
290 /* Prepare buffer for next frame but one. */
291 if (!list_is_last(&next_buf->list, &video->dma_queue)) {
292 next_buf = list_next_entry(next_buf, list);
293 next_buf->queued_to_csi = true;
294 sun6i_csi_update_buf_addr(video->csi, next_buf->dma_addr);
295 } else {
296 dev_dbg(video->csi->dev, "Next frame will be dropped!\n");
299 unlock:
300 video->sequence++;
301 spin_unlock(&video->dma_queue_lock);
304 static const struct vb2_ops sun6i_csi_vb2_ops = {
305 .queue_setup = sun6i_video_queue_setup,
306 .wait_prepare = vb2_ops_wait_prepare,
307 .wait_finish = vb2_ops_wait_finish,
308 .buf_prepare = sun6i_video_buffer_prepare,
309 .start_streaming = sun6i_video_start_streaming,
310 .stop_streaming = sun6i_video_stop_streaming,
311 .buf_queue = sun6i_video_buffer_queue,
314 static int vidioc_querycap(struct file *file, void *priv,
315 struct v4l2_capability *cap)
317 struct sun6i_video *video = video_drvdata(file);
319 strscpy(cap->driver, "sun6i-video", sizeof(cap->driver));
320 strscpy(cap->card, video->vdev.name, sizeof(cap->card));
321 snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
322 video->csi->dev->of_node->name);
324 return 0;
327 static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
328 struct v4l2_fmtdesc *f)
330 u32 index = f->index;
332 if (index >= ARRAY_SIZE(supported_pixformats))
333 return -EINVAL;
335 f->pixelformat = supported_pixformats[index];
337 return 0;
340 static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
341 struct v4l2_format *fmt)
343 struct sun6i_video *video = video_drvdata(file);
345 *fmt = video->fmt;
347 return 0;
350 static int sun6i_video_try_fmt(struct sun6i_video *video,
351 struct v4l2_format *f)
353 struct v4l2_pix_format *pixfmt = &f->fmt.pix;
354 int bpp;
356 if (!is_pixformat_valid(pixfmt->pixelformat))
357 pixfmt->pixelformat = supported_pixformats[0];
359 v4l_bound_align_image(&pixfmt->width, MIN_WIDTH, MAX_WIDTH, 1,
360 &pixfmt->height, MIN_HEIGHT, MAX_WIDTH, 1, 1);
362 bpp = sun6i_csi_get_bpp(pixfmt->pixelformat);
363 pixfmt->bytesperline = (pixfmt->width * bpp) >> 3;
364 pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height;
366 if (pixfmt->field == V4L2_FIELD_ANY)
367 pixfmt->field = V4L2_FIELD_NONE;
369 pixfmt->colorspace = V4L2_COLORSPACE_RAW;
370 pixfmt->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
371 pixfmt->quantization = V4L2_QUANTIZATION_DEFAULT;
372 pixfmt->xfer_func = V4L2_XFER_FUNC_DEFAULT;
374 return 0;
377 static int sun6i_video_set_fmt(struct sun6i_video *video, struct v4l2_format *f)
379 int ret;
381 ret = sun6i_video_try_fmt(video, f);
382 if (ret)
383 return ret;
385 video->fmt = *f;
387 return 0;
390 static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
391 struct v4l2_format *f)
393 struct sun6i_video *video = video_drvdata(file);
395 if (vb2_is_busy(&video->vb2_vidq))
396 return -EBUSY;
398 return sun6i_video_set_fmt(video, f);
401 static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
402 struct v4l2_format *f)
404 struct sun6i_video *video = video_drvdata(file);
406 return sun6i_video_try_fmt(video, f);
409 static int vidioc_enum_input(struct file *file, void *fh,
410 struct v4l2_input *inp)
412 if (inp->index != 0)
413 return -EINVAL;
415 strscpy(inp->name, "camera", sizeof(inp->name));
416 inp->type = V4L2_INPUT_TYPE_CAMERA;
418 return 0;
421 static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
423 *i = 0;
425 return 0;
428 static int vidioc_s_input(struct file *file, void *fh, unsigned int i)
430 if (i != 0)
431 return -EINVAL;
433 return 0;
436 static const struct v4l2_ioctl_ops sun6i_video_ioctl_ops = {
437 .vidioc_querycap = vidioc_querycap,
438 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
439 .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
440 .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
441 .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
443 .vidioc_enum_input = vidioc_enum_input,
444 .vidioc_s_input = vidioc_s_input,
445 .vidioc_g_input = vidioc_g_input,
447 .vidioc_reqbufs = vb2_ioctl_reqbufs,
448 .vidioc_querybuf = vb2_ioctl_querybuf,
449 .vidioc_qbuf = vb2_ioctl_qbuf,
450 .vidioc_expbuf = vb2_ioctl_expbuf,
451 .vidioc_dqbuf = vb2_ioctl_dqbuf,
452 .vidioc_create_bufs = vb2_ioctl_create_bufs,
453 .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
454 .vidioc_streamon = vb2_ioctl_streamon,
455 .vidioc_streamoff = vb2_ioctl_streamoff,
457 .vidioc_log_status = v4l2_ctrl_log_status,
458 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
459 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
462 /* -----------------------------------------------------------------------------
463 * V4L2 file operations
465 static int sun6i_video_open(struct file *file)
467 struct sun6i_video *video = video_drvdata(file);
468 int ret;
470 if (mutex_lock_interruptible(&video->lock))
471 return -ERESTARTSYS;
473 ret = v4l2_fh_open(file);
474 if (ret < 0)
475 goto unlock;
477 ret = v4l2_pipeline_pm_get(&video->vdev.entity);
478 if (ret < 0)
479 goto fh_release;
481 /* check if already powered */
482 if (!v4l2_fh_is_singular_file(file))
483 goto unlock;
485 ret = sun6i_csi_set_power(video->csi, true);
486 if (ret < 0)
487 goto fh_release;
489 mutex_unlock(&video->lock);
490 return 0;
492 fh_release:
493 v4l2_fh_release(file);
494 unlock:
495 mutex_unlock(&video->lock);
496 return ret;
499 static int sun6i_video_close(struct file *file)
501 struct sun6i_video *video = video_drvdata(file);
502 bool last_fh;
504 mutex_lock(&video->lock);
506 last_fh = v4l2_fh_is_singular_file(file);
508 _vb2_fop_release(file, NULL);
510 v4l2_pipeline_pm_put(&video->vdev.entity);
512 if (last_fh)
513 sun6i_csi_set_power(video->csi, false);
515 mutex_unlock(&video->lock);
517 return 0;
520 static const struct v4l2_file_operations sun6i_video_fops = {
521 .owner = THIS_MODULE,
522 .open = sun6i_video_open,
523 .release = sun6i_video_close,
524 .unlocked_ioctl = video_ioctl2,
525 .mmap = vb2_fop_mmap,
526 .poll = vb2_fop_poll
529 /* -----------------------------------------------------------------------------
530 * Media Operations
532 static int sun6i_video_link_validate_get_format(struct media_pad *pad,
533 struct v4l2_subdev_format *fmt)
535 if (is_media_entity_v4l2_subdev(pad->entity)) {
536 struct v4l2_subdev *sd =
537 media_entity_to_v4l2_subdev(pad->entity);
539 fmt->which = V4L2_SUBDEV_FORMAT_ACTIVE;
540 fmt->pad = pad->index;
541 return v4l2_subdev_call(sd, pad, get_fmt, NULL, fmt);
544 return -EINVAL;
547 static int sun6i_video_link_validate(struct media_link *link)
549 struct video_device *vdev = container_of(link->sink->entity,
550 struct video_device, entity);
551 struct sun6i_video *video = video_get_drvdata(vdev);
552 struct v4l2_subdev_format source_fmt;
553 int ret;
555 video->mbus_code = 0;
557 if (!media_entity_remote_pad(link->sink->entity->pads)) {
558 dev_info(video->csi->dev,
559 "video node %s pad not connected\n", vdev->name);
560 return -ENOLINK;
563 ret = sun6i_video_link_validate_get_format(link->source, &source_fmt);
564 if (ret < 0)
565 return ret;
567 if (!sun6i_csi_is_format_supported(video->csi,
568 video->fmt.fmt.pix.pixelformat,
569 source_fmt.format.code)) {
570 dev_err(video->csi->dev,
571 "Unsupported pixformat: 0x%x with mbus code: 0x%x!\n",
572 video->fmt.fmt.pix.pixelformat,
573 source_fmt.format.code);
574 return -EPIPE;
577 if (source_fmt.format.width != video->fmt.fmt.pix.width ||
578 source_fmt.format.height != video->fmt.fmt.pix.height) {
579 dev_err(video->csi->dev,
580 "Wrong width or height %ux%u (%ux%u expected)\n",
581 video->fmt.fmt.pix.width, video->fmt.fmt.pix.height,
582 source_fmt.format.width, source_fmt.format.height);
583 return -EPIPE;
586 video->mbus_code = source_fmt.format.code;
588 return 0;
591 static const struct media_entity_operations sun6i_video_media_ops = {
592 .link_validate = sun6i_video_link_validate
595 int sun6i_video_init(struct sun6i_video *video, struct sun6i_csi *csi,
596 const char *name)
598 struct video_device *vdev = &video->vdev;
599 struct vb2_queue *vidq = &video->vb2_vidq;
600 struct v4l2_format fmt = { 0 };
601 int ret;
603 video->csi = csi;
605 /* Initialize the media entity... */
606 video->pad.flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT;
607 vdev->entity.ops = &sun6i_video_media_ops;
608 ret = media_entity_pads_init(&vdev->entity, 1, &video->pad);
609 if (ret < 0)
610 return ret;
612 mutex_init(&video->lock);
614 INIT_LIST_HEAD(&video->dma_queue);
615 spin_lock_init(&video->dma_queue_lock);
617 video->sequence = 0;
619 /* Setup default format */
620 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
621 fmt.fmt.pix.pixelformat = supported_pixformats[0];
622 fmt.fmt.pix.width = 1280;
623 fmt.fmt.pix.height = 720;
624 fmt.fmt.pix.field = V4L2_FIELD_NONE;
625 sun6i_video_set_fmt(video, &fmt);
627 /* Initialize videobuf2 queue */
628 vidq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
629 vidq->io_modes = VB2_MMAP | VB2_DMABUF;
630 vidq->drv_priv = video;
631 vidq->buf_struct_size = sizeof(struct sun6i_csi_buffer);
632 vidq->ops = &sun6i_csi_vb2_ops;
633 vidq->mem_ops = &vb2_dma_contig_memops;
634 vidq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
635 vidq->lock = &video->lock;
636 /* Make sure non-dropped frame */
637 vidq->min_buffers_needed = 3;
638 vidq->dev = csi->dev;
640 ret = vb2_queue_init(vidq);
641 if (ret) {
642 v4l2_err(&csi->v4l2_dev, "vb2_queue_init failed: %d\n", ret);
643 goto clean_entity;
646 /* Register video device */
647 strscpy(vdev->name, name, sizeof(vdev->name));
648 vdev->release = video_device_release_empty;
649 vdev->fops = &sun6i_video_fops;
650 vdev->ioctl_ops = &sun6i_video_ioctl_ops;
651 vdev->vfl_type = VFL_TYPE_VIDEO;
652 vdev->vfl_dir = VFL_DIR_RX;
653 vdev->v4l2_dev = &csi->v4l2_dev;
654 vdev->queue = vidq;
655 vdev->lock = &video->lock;
656 vdev->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE;
657 video_set_drvdata(vdev, video);
659 ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
660 if (ret < 0) {
661 v4l2_err(&csi->v4l2_dev,
662 "video_register_device failed: %d\n", ret);
663 goto clean_entity;
666 return 0;
668 clean_entity:
669 media_entity_cleanup(&video->vdev.entity);
670 mutex_destroy(&video->lock);
671 return ret;
674 void sun6i_video_cleanup(struct sun6i_video *video)
676 vb2_video_unregister_device(&video->vdev);
677 media_entity_cleanup(&video->vdev.entity);
678 mutex_destroy(&video->lock);