Lines Matching +full:not +full:- +full:swapped

1 // SPDX-License-Identifier: GPL-2.0
4 * Copyright (C) 2017-2018 Jacopo Mondi <jacopo+renesas@jmondi.org>
6 * Based on soc-camera driver "soc_camera/sh_mobile_ceu_camera.c"
9 * Based on V4L2 Driver for PXA camera host - "pxa_camera.c",
16 #include <linux/dma-mapping.h>
32 #include <media/v4l2-async.h>
33 #include <media/v4l2-common.h>
34 #include <media/v4l2-ctrls.h>
35 #include <media/v4l2-dev.h>
36 #include <media/v4l2-device.h>
37 #include <media/v4l2-event.h>
38 #include <media/v4l2-fwnode.h>
39 #include <media/v4l2-image-sizes.h>
40 #include <media/v4l2-ioctl.h>
41 #include <media/v4l2-mediabus.h>
42 #include <media/videobuf2-dma-contig.h>
44 #include <media/drv-intf/renesas-ceu.h>
46 #define DRIVER_NAME "renesas-ceu"
88 /* Swap all input data in 8-bit, 16-bits and 32-bits units (Figure 46.45). */
105 /* One-frame capture end interrupt. */
118 * ceu_bus_fmt - describe a 8-bits yuyv format the sensor can produce
122 * @fmt_order_swap: swapped CEU_CAMCR.DTARY ordering of input components
124 * @swapped: does Cr appear before Cb?
132 bool swapped; member
138 * ceu_buffer - Link vb2 buffer to the list of available buffers.
151 * ceu_subdev - Wraps v4l2 sub-device and provides async subdevice.
157 /* per-subdevice mbus configuration options */
168 * ceu_device - CEU device instance
198 /* mlock - lock access to interface reset and vb2 queue */
201 /* lock - lock access to capture buffer queue and active buffer */
204 /* base - CEU memory base address */
213 /* --- CEU memory output formats --- */
216 * ceu_fmt - describe a memory output format supported by CEU interface.
227 * ceu_format_list - List of supported memory output formats
230 * formats are available thanks to CEU re-ordering and sub-sampling
274 if (fmt->fourcc == fourcc) in get_ceu_fmt_from_fourcc()
282 switch (pix->pixelformat) { in ceu_fmt_mplane()
298 /* --- CEU HW operations --- */
302 iowrite32(data, priv->base + reg_offs); in ceu_write()
307 return ioread32(priv->base + reg_offs); in ceu_read()
311 * ceu_soft_reset() - Software reset the CEU interface.
314 * Returns 0 for success, -EIO for error.
329 dev_err(ceudev->dev, "soft reset time out\n"); in ceu_soft_reset()
330 return -EIO; in ceu_soft_reset()
339 /* If we get here, CEU has not reset properly. */ in ceu_soft_reset()
340 return -EIO; in ceu_soft_reset()
343 /* --- CEU Capture Operations --- */
346 * ceu_hw_config() - Configure CEU interface registers.
351 struct v4l2_pix_format_mplane *pix = &ceudev->v4l2_pix; in ceu_hw_config()
352 struct ceu_subdev *ceu_sd = ceudev->sd; in ceu_hw_config()
353 struct ceu_mbus_fmt *mbus_fmt = &ceu_sd->mbus_fmt; in ceu_hw_config()
354 unsigned int mbus_flags = ceu_sd->mbus_flags; in ceu_hw_config()
363 capwr = (pix->height << 16) | pix->width * mbus_fmt->bpp / 8; in ceu_hw_config()
381 * If the memory output planar format is 'swapped' (Cr before Cb) and in ceu_hw_config()
382 * input format is not, use the swapped version of CAMCR.DTARY. in ceu_hw_config()
384 * If the memory output planar format is not 'swapped' (Cb before Cr) in ceu_hw_config()
385 * and input format is, use the swapped version of CAMCR.DTARY. in ceu_hw_config()
392 switch (pix->pixelformat) { in ceu_hw_config()
400 cfzsr = (pix->height << 16) | pix->width; in ceu_hw_config()
401 cdwdr = pix->plane_fmt[0].bytesperline; in ceu_hw_config()
404 /* Non-swapped planar image capture mode. */ in ceu_hw_config()
409 if (mbus_fmt->swapped) in ceu_hw_config()
410 camcr = mbus_fmt->fmt_order_swap; in ceu_hw_config()
412 camcr = mbus_fmt->fmt_order; in ceu_hw_config()
414 cfzsr = (pix->height << 16) | pix->width; in ceu_hw_config()
415 cdwdr = pix->width; in ceu_hw_config()
418 /* Swapped planar image capture mode. */ in ceu_hw_config()
423 if (mbus_fmt->swapped) in ceu_hw_config()
424 camcr = mbus_fmt->fmt_order; in ceu_hw_config()
426 camcr = mbus_fmt->fmt_order_swap; in ceu_hw_config()
428 cfzsr = (pix->height << 16) | pix->width; in ceu_hw_config()
429 cdwdr = pix->width; in ceu_hw_config()
433 return -EINVAL; in ceu_hw_config()
451 /* TODO: 16 bit bus width require re-calculation of cdwdr and cfzsr */ in ceu_hw_config()
460 * ceu_capture() - Trigger start of a capture sequence.
466 struct v4l2_pix_format_mplane *pix = &ceudev->v4l2_pix; in ceu_capture()
470 vb2_dma_contig_plane_dma_addr(&ceudev->active->vb2_buf, 0); in ceu_capture()
473 /* Ignore CbCr plane for non multi-planar image formats. */ in ceu_capture()
476 vb2_dma_contig_plane_dma_addr(&ceudev->active->vb2_buf, in ceu_capture()
483 * one-frame capture mode. in ceu_capture()
499 ceu_write(ceudev, CEU_CETCR, ~ceudev->irq_mask); in ceu_irq()
505 spin_lock(&ceudev->lock); in ceu_irq()
508 vbuf = ceudev->active; in ceu_irq()
510 spin_unlock(&ceudev->lock); in ceu_irq()
516 * and the image of that frame is not captured correctly. in ceu_irq()
519 dev_err(ceudev->dev, "VBP interrupt: abort capture\n"); in ceu_irq()
524 vbuf->vb2_buf.timestamp = ktime_get_ns(); in ceu_irq()
525 vbuf->sequence = ceudev->sequence++; in ceu_irq()
526 vbuf->field = ceudev->field; in ceu_irq()
529 if (!list_empty(&ceudev->capture)) { in ceu_irq()
530 buf = list_first_entry(&ceudev->capture, struct ceu_buffer, in ceu_irq()
532 list_del(&buf->queue); in ceu_irq()
533 ceudev->active = &buf->vb; in ceu_irq()
539 vb2_buffer_done(&vbuf->vb2_buf, VB2_BUF_STATE_DONE); in ceu_irq()
541 spin_unlock(&ceudev->lock); in ceu_irq()
547 vb2_buffer_done(&vbuf->vb2_buf, VB2_BUF_STATE_ERROR); in ceu_irq()
549 list_for_each_entry(buf, &ceudev->capture, queue) in ceu_irq()
550 vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); in ceu_irq()
552 spin_unlock(&ceudev->lock); in ceu_irq()
557 /* --- CEU Videobuf2 operations --- */
564 plane->sizeimage = szimage; in ceu_update_plane_sizes()
565 if (plane->bytesperline < bpl || plane->bytesperline > CEU_MAX_BPL) in ceu_update_plane_sizes()
566 plane->bytesperline = bpl; in ceu_update_plane_sizes()
570 * ceu_calc_plane_sizes() - Fill per-plane 'struct v4l2_plane_pix_format'
583 switch (pix->pixelformat) { in ceu_calc_plane_sizes()
588 pix->num_planes = 1; in ceu_calc_plane_sizes()
589 bpl = pix->width * ceu_fmt->bpp / 8; in ceu_calc_plane_sizes()
590 szimage = pix->height * bpl; in ceu_calc_plane_sizes()
591 ceu_update_plane_sizes(&pix->plane_fmt[0], bpl, szimage); in ceu_calc_plane_sizes()
596 pix->num_planes = 2; in ceu_calc_plane_sizes()
597 bpl = pix->width; in ceu_calc_plane_sizes()
598 szimage = pix->height * pix->width; in ceu_calc_plane_sizes()
599 ceu_update_plane_sizes(&pix->plane_fmt[0], bpl, szimage); in ceu_calc_plane_sizes()
600 ceu_update_plane_sizes(&pix->plane_fmt[1], bpl, szimage / 2); in ceu_calc_plane_sizes()
606 pix->num_planes = 2; in ceu_calc_plane_sizes()
607 bpl = pix->width; in ceu_calc_plane_sizes()
608 szimage = pix->height * pix->width; in ceu_calc_plane_sizes()
609 ceu_update_plane_sizes(&pix->plane_fmt[0], bpl, szimage); in ceu_calc_plane_sizes()
610 ceu_update_plane_sizes(&pix->plane_fmt[1], bpl, szimage); in ceu_calc_plane_sizes()
616 * ceu_vb2_setup() - is called to check whether the driver can accept the
625 struct v4l2_pix_format_mplane *pix = &ceudev->v4l2_pix; in ceu_vb2_setup()
630 for (i = 0; i < pix->num_planes; i++) in ceu_vb2_setup()
631 if (sizes[i] < pix->plane_fmt[i].sizeimage) in ceu_vb2_setup()
632 return -EINVAL; in ceu_vb2_setup()
637 /* num_planes not set: called from REQBUFS, just set plane sizes. */ in ceu_vb2_setup()
638 *num_planes = pix->num_planes; in ceu_vb2_setup()
639 for (i = 0; i < pix->num_planes; i++) in ceu_vb2_setup()
640 sizes[i] = pix->plane_fmt[i].sizeimage; in ceu_vb2_setup()
647 struct ceu_device *ceudev = vb2_get_drv_priv(vb->vb2_queue); in ceu_vb2_queue()
652 spin_lock_irqsave(&ceudev->lock, irqflags); in ceu_vb2_queue()
653 list_add_tail(&buf->queue, &ceudev->capture); in ceu_vb2_queue()
654 spin_unlock_irqrestore(&ceudev->lock, irqflags); in ceu_vb2_queue()
659 struct ceu_device *ceudev = vb2_get_drv_priv(vb->vb2_queue); in ceu_vb2_prepare()
660 struct v4l2_pix_format_mplane *pix = &ceudev->v4l2_pix; in ceu_vb2_prepare()
663 for (i = 0; i < pix->num_planes; i++) { in ceu_vb2_prepare()
664 if (vb2_plane_size(vb, i) < pix->plane_fmt[i].sizeimage) { in ceu_vb2_prepare()
665 dev_err(ceudev->dev, in ceu_vb2_prepare()
668 pix->plane_fmt[i].sizeimage); in ceu_vb2_prepare()
669 return -EINVAL; in ceu_vb2_prepare()
672 vb2_set_plane_payload(vb, i, pix->plane_fmt[i].sizeimage); in ceu_vb2_prepare()
681 struct v4l2_subdev *v4l2_sd = ceudev->sd->v4l2_sd; in ceu_start_streaming()
692 if (ret && ret != -ENOIOCTLCMD) { in ceu_start_streaming()
693 dev_dbg(ceudev->dev, in ceu_start_streaming()
698 spin_lock_irqsave(&ceudev->lock, irqflags); in ceu_start_streaming()
699 ceudev->sequence = 0; in ceu_start_streaming()
702 buf = list_first_entry(&ceudev->capture, struct ceu_buffer, in ceu_start_streaming()
705 list_del(&buf->queue); in ceu_start_streaming()
706 ceudev->active = &buf->vb; in ceu_start_streaming()
709 ceu_write(ceudev, CEU_CETCR, ~ceudev->irq_mask); in ceu_start_streaming()
714 spin_unlock_irqrestore(&ceudev->lock, irqflags); in ceu_start_streaming()
719 spin_lock_irqsave(&ceudev->lock, irqflags); in ceu_start_streaming()
720 list_for_each_entry(buf, &ceudev->capture, queue) in ceu_start_streaming()
721 vb2_buffer_done(&ceudev->active->vb2_buf, in ceu_start_streaming()
723 ceudev->active = NULL; in ceu_start_streaming()
724 spin_unlock_irqrestore(&ceudev->lock, irqflags); in ceu_start_streaming()
732 struct v4l2_subdev *v4l2_sd = ceudev->sd->v4l2_sd; in ceu_stop_streaming()
738 ceu_read(ceudev, CEU_CETCR) & ceudev->irq_mask); in ceu_stop_streaming()
743 spin_lock_irqsave(&ceudev->lock, irqflags); in ceu_stop_streaming()
744 if (ceudev->active) { in ceu_stop_streaming()
745 vb2_buffer_done(&ceudev->active->vb2_buf, in ceu_stop_streaming()
747 ceudev->active = NULL; in ceu_stop_streaming()
751 list_for_each_entry(buf, &ceudev->capture, queue) in ceu_stop_streaming()
752 vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); in ceu_stop_streaming()
753 INIT_LIST_HEAD(&ceudev->capture); in ceu_stop_streaming()
755 spin_unlock_irqrestore(&ceudev->lock, irqflags); in ceu_stop_streaming()
770 /* --- CEU image formats handling --- */
773 * __ceu_try_fmt() - test format on CEU and sensor
783 struct ceu_subdev *ceu_sd = ceudev->sd; in __ceu_try_fmt()
784 struct v4l2_pix_format_mplane *pix = &v4l2_fmt->fmt.pix_mp; in __ceu_try_fmt()
785 struct v4l2_subdev *v4l2_sd = ceu_sd->v4l2_sd; in __ceu_try_fmt()
804 mbus_code_old = ceu_sd->mbus_fmt.mbus_code; in __ceu_try_fmt()
806 switch (pix->pixelformat) { in __ceu_try_fmt()
823 mbus_code = ceu_sd->mbus_fmt.mbus_code; in __ceu_try_fmt()
827 pix->pixelformat = V4L2_PIX_FMT_NV16; in __ceu_try_fmt()
828 mbus_code = ceu_sd->mbus_fmt.mbus_code; in __ceu_try_fmt()
832 ceu_fmt = get_ceu_fmt_from_fourcc(pix->pixelformat); in __ceu_try_fmt()
834 /* CFSZR requires height and width to be 4-pixel aligned. */ in __ceu_try_fmt()
835 v4l_bound_align_image(&pix->width, 2, CEU_MAX_WIDTH, 4, in __ceu_try_fmt()
836 &pix->height, 4, CEU_MAX_HEIGHT, 4, 0); in __ceu_try_fmt()
848 if (ret == -EINVAL) { in __ceu_try_fmt()
862 /* Calculate per-plane sizes based on image format. */ in __ceu_try_fmt()
872 * ceu_try_fmt() - Wrapper for __ceu_try_fmt; discard configured mbus_fmt
882 * ceu_set_fmt() - Apply the supplied format to both sensor and CEU
886 struct ceu_subdev *ceu_sd = ceudev->sd; in ceu_set_fmt()
887 struct v4l2_subdev *v4l2_sd = ceu_sd->v4l2_sd; in ceu_set_fmt()
904 v4l2_fill_mbus_format_mplane(&format.format, &v4l2_fmt->fmt.pix_mp); in ceu_set_fmt()
909 ceudev->v4l2_pix = v4l2_fmt->fmt.pix_mp; in ceu_set_fmt()
910 ceudev->field = V4L2_FIELD_NONE; in ceu_set_fmt()
916 * ceu_set_default_fmt() - Apply default NV16 memory output format with VGA
948 ceudev->v4l2_pix = v4l2_fmt.fmt.pix_mp; in ceu_set_default_fmt()
949 ceudev->field = V4L2_FIELD_NONE; in ceu_set_default_fmt()
955 * ceu_init_mbus_fmt() - Query sensor for supported formats and initialize
958 * Find out if sensor can produce a permutation of 8-bits YUYV bus format.
959 * From a single 8-bits YUYV bus format the CEU can produce several memory
961 * - NV[12|21|16|61] through image fetch mode;
962 * - YUYV422 if sensor provides YUYV422
969 struct ceu_subdev *ceu_sd = ceudev->sd; in ceu_init_mbus_fmt()
970 struct ceu_mbus_fmt *mbus_fmt = &ceu_sd->mbus_fmt; in ceu_init_mbus_fmt()
971 struct v4l2_subdev *v4l2_sd = ceu_sd->v4l2_sd; in ceu_init_mbus_fmt()
979 /* Find out if sensor can produce any permutation of 8-bits YUYV422. */ in ceu_init_mbus_fmt()
992 * Only support 8-bits YUYV bus formats at the moment; in ceu_init_mbus_fmt()
1004 return -ENXIO; in ceu_init_mbus_fmt()
1009 * well as for data synch fetch mode (YUYV - YVYU etc. ). in ceu_init_mbus_fmt()
1011 mbus_fmt->mbus_code = sd_mbus_fmt.code; in ceu_init_mbus_fmt()
1012 mbus_fmt->bps = 8; in ceu_init_mbus_fmt()
1017 mbus_fmt->fmt_order = CEU_CAMCR_DTARY_8_YUYV; in ceu_init_mbus_fmt()
1018 mbus_fmt->fmt_order_swap = CEU_CAMCR_DTARY_8_YVYU; in ceu_init_mbus_fmt()
1019 mbus_fmt->swapped = false; in ceu_init_mbus_fmt()
1020 mbus_fmt->bpp = 16; in ceu_init_mbus_fmt()
1024 mbus_fmt->fmt_order = CEU_CAMCR_DTARY_8_YVYU; in ceu_init_mbus_fmt()
1025 mbus_fmt->fmt_order_swap = CEU_CAMCR_DTARY_8_YUYV; in ceu_init_mbus_fmt()
1026 mbus_fmt->swapped = true; in ceu_init_mbus_fmt()
1027 mbus_fmt->bpp = 16; in ceu_init_mbus_fmt()
1031 mbus_fmt->fmt_order = CEU_CAMCR_DTARY_8_UYVY; in ceu_init_mbus_fmt()
1032 mbus_fmt->fmt_order_swap = CEU_CAMCR_DTARY_8_VYUY; in ceu_init_mbus_fmt()
1033 mbus_fmt->swapped = false; in ceu_init_mbus_fmt()
1034 mbus_fmt->bpp = 16; in ceu_init_mbus_fmt()
1038 mbus_fmt->fmt_order = CEU_CAMCR_DTARY_8_VYUY; in ceu_init_mbus_fmt()
1039 mbus_fmt->fmt_order_swap = CEU_CAMCR_DTARY_8_UYVY; in ceu_init_mbus_fmt()
1040 mbus_fmt->swapped = true; in ceu_init_mbus_fmt()
1041 mbus_fmt->bpp = 16; in ceu_init_mbus_fmt()
1048 /* --- Runtime PM Handlers --- */
1051 * ceu_runtime_resume() - soft-reset the interface and turn sensor power on.
1056 struct v4l2_subdev *v4l2_sd = ceudev->sd->v4l2_sd; in ceu_runtime_resume()
1066 * ceu_runtime_suspend() - disable capture and interrupts and soft-reset.
1072 struct v4l2_subdev *v4l2_sd = ceudev->sd->v4l2_sd; in ceu_runtime_suspend()
1082 /* --- File Operations --- */
1093 mutex_lock(&ceudev->mlock); in ceu_open()
1094 /* Causes soft-reset and sensor power on on first open */ in ceu_open()
1095 ret = pm_runtime_resume_and_get(ceudev->dev); in ceu_open()
1096 mutex_unlock(&ceudev->mlock); in ceu_open()
1107 mutex_lock(&ceudev->mlock); in ceu_release()
1108 /* Causes soft-reset and sensor power down on last close */ in ceu_release()
1109 pm_runtime_put(ceudev->dev); in ceu_release()
1110 mutex_unlock(&ceudev->mlock); in ceu_release()
1124 /* --- Video Device IOCTLs --- */
1131 strscpy(cap->card, "Renesas CEU", sizeof(cap->card)); in ceu_querycap()
1132 strscpy(cap->driver, DRIVER_NAME, sizeof(cap->driver)); in ceu_querycap()
1133 snprintf(cap->bus_info, sizeof(cap->bus_info), in ceu_querycap()
1134 "platform:renesas-ceu-%s", dev_name(ceudev->dev)); in ceu_querycap()
1144 if (f->index >= ARRAY_SIZE(ceu_fmt_list)) in ceu_enum_fmt_vid_cap()
1145 return -EINVAL; in ceu_enum_fmt_vid_cap()
1147 fmt = &ceu_fmt_list[f->index]; in ceu_enum_fmt_vid_cap()
1148 f->pixelformat = fmt->fourcc; in ceu_enum_fmt_vid_cap()
1166 if (vb2_is_streaming(&ceudev->vb2_vq)) in ceu_s_fmt_vid_cap()
1167 return -EBUSY; in ceu_s_fmt_vid_cap()
1177 f->fmt.pix_mp = ceudev->v4l2_pix; in ceu_g_fmt_vid_cap()
1188 if (inp->index >= ceudev->num_sd) in ceu_enum_input()
1189 return -EINVAL; in ceu_enum_input()
1191 ceusd = ceudev->subdevs[inp->index]; in ceu_enum_input()
1193 inp->type = V4L2_INPUT_TYPE_CAMERA; in ceu_enum_input()
1194 inp->std = 0; in ceu_enum_input()
1195 snprintf(inp->name, sizeof(inp->name), "Camera%u: %s", in ceu_enum_input()
1196 inp->index, ceusd->v4l2_sd->name); in ceu_enum_input()
1205 *i = ceudev->sd_index; in ceu_g_input()
1216 if (i >= ceudev->num_sd) in ceu_s_input()
1217 return -EINVAL; in ceu_s_input()
1219 if (vb2_is_streaming(&ceudev->vb2_vq)) in ceu_s_input()
1220 return -EBUSY; in ceu_s_input()
1222 if (i == ceudev->sd_index) in ceu_s_input()
1225 ceu_sd_old = ceudev->sd; in ceu_s_input()
1226 ceudev->sd = ceudev->subdevs[i]; in ceu_s_input()
1234 ceudev->sd = ceu_sd_old; in ceu_s_input()
1235 return -EINVAL; in ceu_s_input()
1240 ceudev->sd = ceu_sd_old; in ceu_s_input()
1241 return -EINVAL; in ceu_s_input()
1245 v4l2_subdev_call(ceu_sd_old->v4l2_sd, core, s_power, 0); in ceu_s_input()
1246 v4l2_subdev_call(ceudev->sd->v4l2_sd, core, s_power, 1); in ceu_s_input()
1248 ceudev->sd_index = i; in ceu_s_input()
1257 return v4l2_g_parm_cap(video_devdata(file), ceudev->sd->v4l2_sd, a); in ceu_g_parm()
1264 return v4l2_s_parm_cap(video_devdata(file), ceudev->sd->v4l2_sd, a); in ceu_s_parm()
1271 struct ceu_subdev *ceu_sd = ceudev->sd; in ceu_enum_framesizes()
1273 struct v4l2_subdev *v4l2_sd = ceu_sd->v4l2_sd; in ceu_enum_framesizes()
1277 .code = ceu_sd->mbus_fmt.mbus_code, in ceu_enum_framesizes()
1278 .index = fsize->index, in ceu_enum_framesizes()
1283 ceu_fmt = get_ceu_fmt_from_fourcc(fsize->pixel_format); in ceu_enum_framesizes()
1285 return -EINVAL; in ceu_enum_framesizes()
1292 fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; in ceu_enum_framesizes()
1293 fsize->discrete.width = CEU_W_MAX(fse.max_width); in ceu_enum_framesizes()
1294 fsize->discrete.height = CEU_H_MAX(fse.max_height); in ceu_enum_framesizes()
1303 struct ceu_subdev *ceu_sd = ceudev->sd; in ceu_enum_frameintervals()
1305 struct v4l2_subdev *v4l2_sd = ceu_sd->v4l2_sd; in ceu_enum_frameintervals()
1309 .code = ceu_sd->mbus_fmt.mbus_code, in ceu_enum_frameintervals()
1310 .index = fival->index, in ceu_enum_frameintervals()
1311 .width = fival->width, in ceu_enum_frameintervals()
1312 .height = fival->height, in ceu_enum_frameintervals()
1317 ceu_fmt = get_ceu_fmt_from_fourcc(fival->pixel_format); in ceu_enum_frameintervals()
1319 return -EINVAL; in ceu_enum_frameintervals()
1326 fival->type = V4L2_FRMIVAL_TYPE_DISCRETE; in ceu_enum_frameintervals()
1327 fival->discrete = fie.interval; in ceu_enum_frameintervals()
1365 * ceu_vdev_release() - release CEU video device memory when last reference
1379 struct v4l2_device *v4l2_dev = notifier->v4l2_dev; in ceu_notify_bound()
1383 ceu_sd->v4l2_sd = v4l2_sd; in ceu_notify_bound()
1384 ceudev->num_sd++; in ceu_notify_bound()
1391 struct v4l2_device *v4l2_dev = notifier->v4l2_dev; in ceu_notify_complete()
1393 struct video_device *vdev = &ceudev->vdev; in ceu_notify_complete()
1394 struct vb2_queue *q = &ceudev->vb2_vq; in ceu_notify_complete()
1399 q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; in ceu_notify_complete()
1400 q->io_modes = VB2_MMAP | VB2_DMABUF; in ceu_notify_complete()
1401 q->drv_priv = ceudev; in ceu_notify_complete()
1402 q->ops = &ceu_vb2_ops; in ceu_notify_complete()
1403 q->mem_ops = &vb2_dma_contig_memops; in ceu_notify_complete()
1404 q->buf_struct_size = sizeof(struct ceu_buffer); in ceu_notify_complete()
1405 q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; in ceu_notify_complete()
1406 q->min_buffers_needed = 2; in ceu_notify_complete()
1407 q->lock = &ceudev->mlock; in ceu_notify_complete()
1408 q->dev = ceudev->v4l2_dev.dev; in ceu_notify_complete()
1418 if (!ceudev->sd) { in ceu_notify_complete()
1419 ceudev->sd = ceudev->subdevs[0]; in ceu_notify_complete()
1420 ceudev->sd_index = 0; in ceu_notify_complete()
1423 v4l2_sd = ceudev->sd->v4l2_sd; in ceu_notify_complete()
1434 strscpy(vdev->name, DRIVER_NAME, sizeof(vdev->name)); in ceu_notify_complete()
1435 vdev->v4l2_dev = v4l2_dev; in ceu_notify_complete()
1436 vdev->lock = &ceudev->mlock; in ceu_notify_complete()
1437 vdev->queue = &ceudev->vb2_vq; in ceu_notify_complete()
1438 vdev->ctrl_handler = v4l2_sd->ctrl_handler; in ceu_notify_complete()
1439 vdev->fops = &ceu_fops; in ceu_notify_complete()
1440 vdev->ioctl_ops = &ceu_ioctl_ops; in ceu_notify_complete()
1441 vdev->release = ceu_vdev_release; in ceu_notify_complete()
1442 vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE | in ceu_notify_complete()
1446 ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); in ceu_notify_complete()
1448 v4l2_err(vdev->v4l2_dev, in ceu_notify_complete()
1462 * ceu_init_async_subdevs() - Initialize CEU subdevices and async_subdevs in
1466 * Returns 0 for success, -ENOMEM for failure.
1471 ceudev->subdevs = devm_kcalloc(ceudev->dev, n_sd, in ceu_init_async_subdevs()
1472 sizeof(*ceudev->subdevs), GFP_KERNEL); in ceu_init_async_subdevs()
1473 if (!ceudev->subdevs) in ceu_init_async_subdevs()
1474 return -ENOMEM; in ceu_init_async_subdevs()
1476 ceudev->sd = NULL; in ceu_init_async_subdevs()
1477 ceudev->sd_index = 0; in ceu_init_async_subdevs()
1478 ceudev->num_sd = 0; in ceu_init_async_subdevs()
1484 * ceu_parse_platform_data() - Initialize async_subdevices using platform
1495 if (pdata->num_subdevs == 0) in ceu_parse_platform_data()
1496 return -ENODEV; in ceu_parse_platform_data()
1498 ret = ceu_init_async_subdevs(ceudev, pdata->num_subdevs); in ceu_parse_platform_data()
1502 for (i = 0; i < pdata->num_subdevs; i++) { in ceu_parse_platform_data()
1505 async_sd = &pdata->subdevs[i]; in ceu_parse_platform_data()
1506 ceu_sd = v4l2_async_nf_add_i2c(&ceudev->notifier, in ceu_parse_platform_data()
1507 async_sd->i2c_adapter_id, in ceu_parse_platform_data()
1508 async_sd->i2c_address, in ceu_parse_platform_data()
1511 v4l2_async_nf_cleanup(&ceudev->notifier); in ceu_parse_platform_data()
1514 ceu_sd->mbus_flags = async_sd->flags; in ceu_parse_platform_data()
1515 ceudev->subdevs[i] = ceu_sd; in ceu_parse_platform_data()
1518 return pdata->num_subdevs; in ceu_parse_platform_data()
1522 * ceu_parse_dt() - Initialize async_subdevs parsing device tree graph.
1526 struct device_node *of = ceudev->dev->of_node; in ceu_parse_dt()
1535 return -ENODEV; in ceu_parse_dt()
1555 dev_err(ceudev->dev, in ceu_parse_dt()
1557 ret = -ENODEV; in ceu_parse_dt()
1563 dev_err(ceudev->dev, in ceu_parse_dt()
1569 ceu_sd = v4l2_async_nf_add_fwnode_remote(&ceudev->notifier, in ceu_parse_dt()
1576 ceu_sd->mbus_flags = fw_ep.bus.parallel.flags; in ceu_parse_dt()
1577 ceudev->subdevs[i] = ceu_sd; in ceu_parse_dt()
1585 v4l2_async_nf_cleanup(&ceudev->notifier); in ceu_parse_dt()
1591 * struct ceu_data - Platform specific CEU data
1609 { .compatible = "renesas,r7s72100-ceu", .data = &ceu_data_rz },
1610 { .compatible = "renesas,r8a7740-ceu", .data = &ceu_data_rz },
1618 struct device *dev = &pdev->dev; in ceu_probe()
1627 return -ENOMEM; in ceu_probe()
1630 ceudev->dev = dev; in ceu_probe()
1632 INIT_LIST_HEAD(&ceudev->capture); in ceu_probe()
1633 spin_lock_init(&ceudev->lock); in ceu_probe()
1634 mutex_init(&ceudev->mlock); in ceu_probe()
1636 ceudev->base = devm_platform_ioremap_resource(pdev, 0); in ceu_probe()
1637 if (IS_ERR(ceudev->base)) { in ceu_probe()
1638 ret = PTR_ERR(ceudev->base); in ceu_probe()
1650 dev_err(&pdev->dev, "Unable to request CEU interrupt.\n"); in ceu_probe()
1656 ret = v4l2_device_register(dev, &ceudev->v4l2_dev); in ceu_probe()
1660 v4l2_async_nf_init(&ceudev->notifier, &ceudev->v4l2_dev); in ceu_probe()
1662 if (IS_ENABLED(CONFIG_OF) && dev->of_node) { in ceu_probe()
1665 } else if (dev->platform_data) { in ceu_probe()
1669 dev->platform_data); in ceu_probe()
1671 num_subdevs = -EINVAL; in ceu_probe()
1678 ceudev->irq_mask = ceu_data->irq_mask; in ceu_probe()
1680 ceudev->notifier.v4l2_dev = &ceudev->v4l2_dev; in ceu_probe()
1681 ceudev->notifier.ops = &ceu_notify_ops; in ceu_probe()
1682 ret = v4l2_async_nf_register(&ceudev->notifier); in ceu_probe()
1691 v4l2_async_nf_cleanup(&ceudev->notifier); in ceu_probe()
1693 v4l2_device_unregister(&ceudev->v4l2_dev); in ceu_probe()
1706 pm_runtime_disable(ceudev->dev); in ceu_remove()
1708 v4l2_async_nf_unregister(&ceudev->notifier); in ceu_remove()
1710 v4l2_async_nf_cleanup(&ceudev->notifier); in ceu_remove()
1712 v4l2_device_unregister(&ceudev->v4l2_dev); in ceu_remove()
1714 video_unregister_device(&ceudev->vdev); in ceu_remove()