1734 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * V4L2 Driver for Renesas Capture Engine Unit (CEU) interface4 * Copyright (C) 2017-2018 Jacopo Mondi <jacopo+renesas@jmondi.org>5 *6 * Based on soc-camera driver "soc_camera/sh_mobile_ceu_camera.c"7 * Copyright (C) 2008 Magnus Damm8 *9 * Based on V4L2 Driver for PXA camera host - "pxa_camera.c",10 * Copyright (C) 2006, Sascha Hauer, Pengutronix11 * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>12 */13 14#include <linux/delay.h>15#include <linux/device.h>16#include <linux/dma-mapping.h>17#include <linux/err.h>18#include <linux/errno.h>19#include <linux/interrupt.h>20#include <linux/io.h>21#include <linux/kernel.h>22#include <linux/mm.h>23#include <linux/module.h>24#include <linux/of.h>25#include <linux/of_graph.h>26#include <linux/platform_device.h>27#include <linux/pm_runtime.h>28#include <linux/slab.h>29#include <linux/time.h>30#include <linux/videodev2.h>31 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>43 44#include <media/drv-intf/renesas-ceu.h>45 46#define DRIVER_NAME "renesas-ceu"47 48/* CEU registers offsets and masks. */49#define CEU_CAPSR 0x00 /* Capture start register */50#define CEU_CAPCR 0x04 /* Capture control register */51#define CEU_CAMCR 0x08 /* Capture interface control register */52#define CEU_CAMOR 0x10 /* Capture interface offset register */53#define CEU_CAPWR 0x14 /* Capture interface width register */54#define CEU_CAIFR 0x18 /* Capture interface input format register */55#define CEU_CRCNTR 0x28 /* CEU register control register */56#define CEU_CRCMPR 0x2c /* CEU register forcible control register */57#define CEU_CFLCR 0x30 /* Capture filter control register */58#define CEU_CFSZR 0x34 /* Capture filter size clip register */59#define CEU_CDWDR 0x38 /* Capture destination width register */60#define CEU_CDAYR 0x3c /* Capture data address Y register */61#define CEU_CDACR 0x40 /* Capture data address C register */62#define CEU_CFWCR 0x5c /* Firewall operation control register */63#define CEU_CDOCR 0x64 /* Capture data output control register */64#define CEU_CEIER 0x70 /* Capture event interrupt enable register */65#define CEU_CETCR 0x74 /* Capture event flag clear register */66#define CEU_CSTSR 0x7c /* Capture status register */67#define CEU_CSRTR 0x80 /* Capture software reset register */68 69/* Data synchronous fetch mode. */70#define CEU_CAMCR_JPEG BIT(4)71 72/* Input components ordering: CEU_CAMCR.DTARY field. */73#define CEU_CAMCR_DTARY_8_UYVY (0x00 << 8)74#define CEU_CAMCR_DTARY_8_VYUY (0x01 << 8)75#define CEU_CAMCR_DTARY_8_YUYV (0x02 << 8)76#define CEU_CAMCR_DTARY_8_YVYU (0x03 << 8)77/* TODO: input components ordering for 16 bits input. */78 79/* Bus transfer MTU. */80#define CEU_CAPCR_BUS_WIDTH256 (0x3 << 20)81 82/* Bus width configuration. */83#define CEU_CAMCR_DTIF_16BITS BIT(12)84 85/* No downsampling to planar YUV420 in image fetch mode. */86#define CEU_CDOCR_NO_DOWSAMPLE BIT(4)87 88/* Swap all input data in 8-bit, 16-bits and 32-bits units (Figure 46.45). */89#define CEU_CDOCR_SWAP_ENDIANNESS (7)90 91/* Capture reset and enable bits. */92#define CEU_CAPSR_CPKIL BIT(16)93#define CEU_CAPSR_CE BIT(0)94 95/* CEU operating flag bit. */96#define CEU_CAPCR_CTNCP BIT(16)97#define CEU_CSTRST_CPTON BIT(0)98 99/* Platform specific IRQ source flags. */100#define CEU_CETCR_ALL_IRQS_RZ 0x397f313101#define CEU_CETCR_ALL_IRQS_SH4 0x3d7f313102 103/* Prohibited register access interrupt bit. */104#define CEU_CETCR_IGRW BIT(4)105/* One-frame capture end interrupt. */106#define CEU_CEIER_CPE BIT(0)107/* VBP error. */108#define CEU_CEIER_VBP BIT(20)109#define CEU_CEIER_MASK (CEU_CEIER_CPE | CEU_CEIER_VBP)110 111#define CEU_MAX_WIDTH 2560112#define CEU_MAX_HEIGHT 1920113#define CEU_MAX_BPL 8188114#define CEU_W_MAX(w) ((w) < CEU_MAX_WIDTH ? (w) : CEU_MAX_WIDTH)115#define CEU_H_MAX(h) ((h) < CEU_MAX_HEIGHT ? (h) : CEU_MAX_HEIGHT)116 117/*118 * ceu_bus_fmt - describe a 8-bits yuyv format the sensor can produce119 *120 * @mbus_code: bus format code121 * @fmt_order: CEU_CAMCR.DTARY ordering of input components (Y, Cb, Cr)122 * @fmt_order_swap: swapped CEU_CAMCR.DTARY ordering of input components123 * (Y, Cr, Cb)124 * @swapped: does Cr appear before Cb?125 * @bps: number of bits sent over bus for each sample126 * @bpp: number of bits per pixels unit127 */128struct ceu_mbus_fmt {129 u32 mbus_code;130 u32 fmt_order;131 u32 fmt_order_swap;132 bool swapped;133 u8 bps;134 u8 bpp;135};136 137/*138 * ceu_buffer - Link vb2 buffer to the list of available buffers.139 */140struct ceu_buffer {141 struct vb2_v4l2_buffer vb;142 struct list_head queue;143};144 145static inline struct ceu_buffer *vb2_to_ceu(struct vb2_v4l2_buffer *vbuf)146{147 return container_of(vbuf, struct ceu_buffer, vb);148}149 150/*151 * ceu_subdev - Wraps v4l2 sub-device and provides async subdevice.152 */153struct ceu_subdev {154 struct v4l2_async_connection asd;155 struct v4l2_subdev *v4l2_sd;156 157 /* per-subdevice mbus configuration options */158 unsigned int mbus_flags;159 struct ceu_mbus_fmt mbus_fmt;160};161 162static struct ceu_subdev *to_ceu_subdev(struct v4l2_async_connection *asd)163{164 return container_of(asd, struct ceu_subdev, asd);165}166 167/*168 * ceu_device - CEU device instance169 */170struct ceu_device {171 struct device *dev;172 struct video_device vdev;173 struct v4l2_device v4l2_dev;174 175 /* subdevices descriptors */176 struct ceu_subdev **subdevs;177 /* the subdevice currently in use */178 struct ceu_subdev *sd;179 unsigned int sd_index;180 unsigned int num_sd;181 182 /* platform specific mask with all IRQ sources flagged */183 u32 irq_mask;184 185 /* currently configured field and pixel format */186 enum v4l2_field field;187 struct v4l2_pix_format_mplane v4l2_pix;188 189 /* async subdev notification helpers */190 struct v4l2_async_notifier notifier;191 192 /* vb2 queue, capture buffer list and active buffer pointer */193 struct vb2_queue vb2_vq;194 struct list_head capture;195 struct vb2_v4l2_buffer *active;196 unsigned int sequence;197 198 /* mlock - lock access to interface reset and vb2 queue */199 struct mutex mlock;200 201 /* lock - lock access to capture buffer queue and active buffer */202 spinlock_t lock;203 204 /* base - CEU memory base address */205 void __iomem *base;206};207 208static inline struct ceu_device *v4l2_to_ceu(struct v4l2_device *v4l2_dev)209{210 return container_of(v4l2_dev, struct ceu_device, v4l2_dev);211}212 213/* --- CEU memory output formats --- */214 215/*216 * ceu_fmt - describe a memory output format supported by CEU interface.217 *218 * @fourcc: memory layout fourcc format code219 * @bpp: number of bits for each pixel stored in memory220 */221struct ceu_fmt {222 u32 fourcc;223 u32 bpp;224};225 226/*227 * ceu_format_list - List of supported memory output formats228 *229 * If sensor provides any YUYV bus format, all the following planar memory230 * formats are available thanks to CEU re-ordering and sub-sampling231 * capabilities.232 */233static const struct ceu_fmt ceu_fmt_list[] = {234 {235 .fourcc = V4L2_PIX_FMT_NV16,236 .bpp = 16,237 },238 {239 .fourcc = V4L2_PIX_FMT_NV61,240 .bpp = 16,241 },242 {243 .fourcc = V4L2_PIX_FMT_NV12,244 .bpp = 12,245 },246 {247 .fourcc = V4L2_PIX_FMT_NV21,248 .bpp = 12,249 },250 {251 .fourcc = V4L2_PIX_FMT_YUYV,252 .bpp = 16,253 },254 {255 .fourcc = V4L2_PIX_FMT_UYVY,256 .bpp = 16,257 },258 {259 .fourcc = V4L2_PIX_FMT_YVYU,260 .bpp = 16,261 },262 {263 .fourcc = V4L2_PIX_FMT_VYUY,264 .bpp = 16,265 },266};267 268static const struct ceu_fmt *get_ceu_fmt_from_fourcc(unsigned int fourcc)269{270 const struct ceu_fmt *fmt = &ceu_fmt_list[0];271 unsigned int i;272 273 for (i = 0; i < ARRAY_SIZE(ceu_fmt_list); i++, fmt++)274 if (fmt->fourcc == fourcc)275 return fmt;276 277 return NULL;278}279 280static bool ceu_fmt_mplane(struct v4l2_pix_format_mplane *pix)281{282 switch (pix->pixelformat) {283 case V4L2_PIX_FMT_YUYV:284 case V4L2_PIX_FMT_UYVY:285 case V4L2_PIX_FMT_YVYU:286 case V4L2_PIX_FMT_VYUY:287 return false;288 case V4L2_PIX_FMT_NV16:289 case V4L2_PIX_FMT_NV61:290 case V4L2_PIX_FMT_NV12:291 case V4L2_PIX_FMT_NV21:292 return true;293 default:294 return false;295 }296}297 298/* --- CEU HW operations --- */299 300static void ceu_write(struct ceu_device *priv, unsigned int reg_offs, u32 data)301{302 iowrite32(data, priv->base + reg_offs);303}304 305static u32 ceu_read(struct ceu_device *priv, unsigned int reg_offs)306{307 return ioread32(priv->base + reg_offs);308}309 310/*311 * ceu_soft_reset() - Software reset the CEU interface.312 * @ceu_device: CEU device.313 *314 * Returns 0 for success, -EIO for error.315 */316static int ceu_soft_reset(struct ceu_device *ceudev)317{318 unsigned int i;319 320 ceu_write(ceudev, CEU_CAPSR, CEU_CAPSR_CPKIL);321 322 for (i = 0; i < 100; i++) {323 if (!(ceu_read(ceudev, CEU_CSTSR) & CEU_CSTRST_CPTON))324 break;325 udelay(1);326 }327 328 if (i == 100) {329 dev_err(ceudev->dev, "soft reset time out\n");330 return -EIO;331 }332 333 for (i = 0; i < 100; i++) {334 if (!(ceu_read(ceudev, CEU_CAPSR) & CEU_CAPSR_CPKIL))335 return 0;336 udelay(1);337 }338 339 /* If we get here, CEU has not reset properly. */340 return -EIO;341}342 343/* --- CEU Capture Operations --- */344 345/*346 * ceu_hw_config() - Configure CEU interface registers.347 */348static int ceu_hw_config(struct ceu_device *ceudev)349{350 u32 camcr, cdocr, cfzsr, cdwdr, capwr;351 struct v4l2_pix_format_mplane *pix = &ceudev->v4l2_pix;352 struct ceu_subdev *ceu_sd = ceudev->sd;353 struct ceu_mbus_fmt *mbus_fmt = &ceu_sd->mbus_fmt;354 unsigned int mbus_flags = ceu_sd->mbus_flags;355 356 /* Start configuring CEU registers */357 ceu_write(ceudev, CEU_CAIFR, 0);358 ceu_write(ceudev, CEU_CFWCR, 0);359 ceu_write(ceudev, CEU_CRCNTR, 0);360 ceu_write(ceudev, CEU_CRCMPR, 0);361 362 /* Set the frame capture period for both image capture and data sync. */363 capwr = (pix->height << 16) | pix->width * mbus_fmt->bpp / 8;364 365 /*366 * Swap input data endianness by default.367 * In data fetch mode bytes are received in chunks of 8 bytes.368 * D0, D1, D2, D3, D4, D5, D6, D7 (D0 received first)369 * The data is however by default written to memory in reverse order:370 * D7, D6, D5, D4, D3, D2, D1, D0 (D7 written to lowest byte)371 *372 * Use CEU_CDOCR[2:0] to swap data ordering.373 */374 cdocr = CEU_CDOCR_SWAP_ENDIANNESS;375 376 /*377 * Configure CAMCR and CDOCR:378 * match input components ordering with memory output format and379 * handle downsampling to YUV420.380 *381 * If the memory output planar format is 'swapped' (Cr before Cb) and382 * input format is not, use the swapped version of CAMCR.DTARY.383 *384 * If the memory output planar format is not 'swapped' (Cb before Cr)385 * and input format is, use the swapped version of CAMCR.DTARY.386 *387 * CEU by default downsample to planar YUV420 (CDCOR[4] = 0).388 * If output is planar YUV422 set CDOCR[4] = 1389 *390 * No downsample for data fetch sync mode.391 */392 switch (pix->pixelformat) {393 /* Data fetch sync mode */394 case V4L2_PIX_FMT_YUYV:395 case V4L2_PIX_FMT_YVYU:396 case V4L2_PIX_FMT_UYVY:397 case V4L2_PIX_FMT_VYUY:398 camcr = CEU_CAMCR_JPEG;399 cdocr |= CEU_CDOCR_NO_DOWSAMPLE;400 cfzsr = (pix->height << 16) | pix->width;401 cdwdr = pix->plane_fmt[0].bytesperline;402 break;403 404 /* Non-swapped planar image capture mode. */405 case V4L2_PIX_FMT_NV16:406 cdocr |= CEU_CDOCR_NO_DOWSAMPLE;407 fallthrough;408 case V4L2_PIX_FMT_NV12:409 if (mbus_fmt->swapped)410 camcr = mbus_fmt->fmt_order_swap;411 else412 camcr = mbus_fmt->fmt_order;413 414 cfzsr = (pix->height << 16) | pix->width;415 cdwdr = pix->width;416 break;417 418 /* Swapped planar image capture mode. */419 case V4L2_PIX_FMT_NV61:420 cdocr |= CEU_CDOCR_NO_DOWSAMPLE;421 fallthrough;422 case V4L2_PIX_FMT_NV21:423 if (mbus_fmt->swapped)424 camcr = mbus_fmt->fmt_order;425 else426 camcr = mbus_fmt->fmt_order_swap;427 428 cfzsr = (pix->height << 16) | pix->width;429 cdwdr = pix->width;430 break;431 432 default:433 return -EINVAL;434 }435 436 camcr |= mbus_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW ? 1 << 1 : 0;437 camcr |= mbus_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW ? 1 << 0 : 0;438 439 /* TODO: handle 16 bit bus width with DTIF bit in CAMCR */440 ceu_write(ceudev, CEU_CAMCR, camcr);441 ceu_write(ceudev, CEU_CDOCR, cdocr);442 ceu_write(ceudev, CEU_CAPCR, CEU_CAPCR_BUS_WIDTH256);443 444 /*445 * TODO: make CAMOR offsets configurable.446 * CAMOR wants to know the number of blanks between a VS/HS signal447 * and valid data. This value should actually come from the sensor...448 */449 ceu_write(ceudev, CEU_CAMOR, 0);450 451 /* TODO: 16 bit bus width require re-calculation of cdwdr and cfzsr */452 ceu_write(ceudev, CEU_CAPWR, capwr);453 ceu_write(ceudev, CEU_CFSZR, cfzsr);454 ceu_write(ceudev, CEU_CDWDR, cdwdr);455 456 return 0;457}458 459/*460 * ceu_capture() - Trigger start of a capture sequence.461 *462 * Program the CEU DMA registers with addresses where to transfer image data.463 */464static int ceu_capture(struct ceu_device *ceudev)465{466 struct v4l2_pix_format_mplane *pix = &ceudev->v4l2_pix;467 dma_addr_t phys_addr_top;468 469 phys_addr_top =470 vb2_dma_contig_plane_dma_addr(&ceudev->active->vb2_buf, 0);471 ceu_write(ceudev, CEU_CDAYR, phys_addr_top);472 473 /* Ignore CbCr plane for non multi-planar image formats. */474 if (ceu_fmt_mplane(pix)) {475 phys_addr_top =476 vb2_dma_contig_plane_dma_addr(&ceudev->active->vb2_buf,477 1);478 ceu_write(ceudev, CEU_CDACR, phys_addr_top);479 }480 481 /*482 * Trigger new capture start: once for each frame, as we work in483 * one-frame capture mode.484 */485 ceu_write(ceudev, CEU_CAPSR, CEU_CAPSR_CE);486 487 return 0;488}489 490static irqreturn_t ceu_irq(int irq, void *data)491{492 struct ceu_device *ceudev = data;493 struct vb2_v4l2_buffer *vbuf;494 struct ceu_buffer *buf;495 u32 status;496 497 /* Clean interrupt status. */498 status = ceu_read(ceudev, CEU_CETCR);499 ceu_write(ceudev, CEU_CETCR, ~ceudev->irq_mask);500 501 /* Unexpected interrupt. */502 if (!(status & CEU_CEIER_MASK))503 return IRQ_NONE;504 505 spin_lock(&ceudev->lock);506 507 /* Stale interrupt from a released buffer, ignore it. */508 vbuf = ceudev->active;509 if (!vbuf) {510 spin_unlock(&ceudev->lock);511 return IRQ_HANDLED;512 }513 514 /*515 * When a VBP interrupt occurs, no capture end interrupt will occur516 * and the image of that frame is not captured correctly.517 */518 if (status & CEU_CEIER_VBP) {519 dev_err(ceudev->dev, "VBP interrupt: abort capture\n");520 goto error_irq_out;521 }522 523 /* Prepare to return the 'previous' buffer. */524 vbuf->vb2_buf.timestamp = ktime_get_ns();525 vbuf->sequence = ceudev->sequence++;526 vbuf->field = ceudev->field;527 528 /* Prepare a new 'active' buffer and trigger a new capture. */529 if (!list_empty(&ceudev->capture)) {530 buf = list_first_entry(&ceudev->capture, struct ceu_buffer,531 queue);532 list_del(&buf->queue);533 ceudev->active = &buf->vb;534 535 ceu_capture(ceudev);536 }537 538 /* Return the 'previous' buffer. */539 vb2_buffer_done(&vbuf->vb2_buf, VB2_BUF_STATE_DONE);540 541 spin_unlock(&ceudev->lock);542 543 return IRQ_HANDLED;544 545error_irq_out:546 /* Return the 'previous' buffer and all queued ones. */547 vb2_buffer_done(&vbuf->vb2_buf, VB2_BUF_STATE_ERROR);548 549 list_for_each_entry(buf, &ceudev->capture, queue)550 vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);551 552 spin_unlock(&ceudev->lock);553 554 return IRQ_HANDLED;555}556 557/* --- CEU Videobuf2 operations --- */558 559static void ceu_update_plane_sizes(struct v4l2_plane_pix_format *plane,560 unsigned int bpl, unsigned int szimage)561{562 memset(plane, 0, sizeof(*plane));563 564 plane->sizeimage = szimage;565 if (plane->bytesperline < bpl || plane->bytesperline > CEU_MAX_BPL)566 plane->bytesperline = bpl;567}568 569/*570 * ceu_calc_plane_sizes() - Fill per-plane 'struct v4l2_plane_pix_format'571 * information according to the currently configured572 * pixel format.573 * @ceu_device: CEU device.574 * @ceu_fmt: Active image format.575 * @pix: Pixel format information (store line width and image sizes)576 */577static void ceu_calc_plane_sizes(struct ceu_device *ceudev,578 const struct ceu_fmt *ceu_fmt,579 struct v4l2_pix_format_mplane *pix)580{581 unsigned int bpl, szimage;582 583 switch (pix->pixelformat) {584 case V4L2_PIX_FMT_YUYV:585 case V4L2_PIX_FMT_UYVY:586 case V4L2_PIX_FMT_YVYU:587 case V4L2_PIX_FMT_VYUY:588 pix->num_planes = 1;589 bpl = pix->width * ceu_fmt->bpp / 8;590 szimage = pix->height * bpl;591 ceu_update_plane_sizes(&pix->plane_fmt[0], bpl, szimage);592 break;593 594 case V4L2_PIX_FMT_NV12:595 case V4L2_PIX_FMT_NV21:596 pix->num_planes = 2;597 bpl = pix->width;598 szimage = pix->height * pix->width;599 ceu_update_plane_sizes(&pix->plane_fmt[0], bpl, szimage);600 ceu_update_plane_sizes(&pix->plane_fmt[1], bpl, szimage / 2);601 break;602 603 case V4L2_PIX_FMT_NV16:604 case V4L2_PIX_FMT_NV61:605 default:606 pix->num_planes = 2;607 bpl = pix->width;608 szimage = pix->height * pix->width;609 ceu_update_plane_sizes(&pix->plane_fmt[0], bpl, szimage);610 ceu_update_plane_sizes(&pix->plane_fmt[1], bpl, szimage);611 break;612 }613}614 615/*616 * ceu_vb2_setup() - is called to check whether the driver can accept the617 * requested number of buffers and to fill in plane sizes618 * for the current frame format, if required.619 */620static int ceu_vb2_setup(struct vb2_queue *vq, unsigned int *count,621 unsigned int *num_planes, unsigned int sizes[],622 struct device *alloc_devs[])623{624 struct ceu_device *ceudev = vb2_get_drv_priv(vq);625 struct v4l2_pix_format_mplane *pix = &ceudev->v4l2_pix;626 unsigned int i;627 628 /* num_planes is set: just check plane sizes. */629 if (*num_planes) {630 for (i = 0; i < pix->num_planes; i++)631 if (sizes[i] < pix->plane_fmt[i].sizeimage)632 return -EINVAL;633 634 return 0;635 }636 637 /* num_planes not set: called from REQBUFS, just set plane sizes. */638 *num_planes = pix->num_planes;639 for (i = 0; i < pix->num_planes; i++)640 sizes[i] = pix->plane_fmt[i].sizeimage;641 642 return 0;643}644 645static void ceu_vb2_queue(struct vb2_buffer *vb)646{647 struct ceu_device *ceudev = vb2_get_drv_priv(vb->vb2_queue);648 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);649 struct ceu_buffer *buf = vb2_to_ceu(vbuf);650 unsigned long irqflags;651 652 spin_lock_irqsave(&ceudev->lock, irqflags);653 list_add_tail(&buf->queue, &ceudev->capture);654 spin_unlock_irqrestore(&ceudev->lock, irqflags);655}656 657static int ceu_vb2_prepare(struct vb2_buffer *vb)658{659 struct ceu_device *ceudev = vb2_get_drv_priv(vb->vb2_queue);660 struct v4l2_pix_format_mplane *pix = &ceudev->v4l2_pix;661 unsigned int i;662 663 for (i = 0; i < pix->num_planes; i++) {664 if (vb2_plane_size(vb, i) < pix->plane_fmt[i].sizeimage) {665 dev_err(ceudev->dev,666 "Plane size too small (%lu < %u)\n",667 vb2_plane_size(vb, i),668 pix->plane_fmt[i].sizeimage);669 return -EINVAL;670 }671 672 vb2_set_plane_payload(vb, i, pix->plane_fmt[i].sizeimage);673 }674 675 return 0;676}677 678static int ceu_start_streaming(struct vb2_queue *vq, unsigned int count)679{680 struct ceu_device *ceudev = vb2_get_drv_priv(vq);681 struct v4l2_subdev *v4l2_sd = ceudev->sd->v4l2_sd;682 struct ceu_buffer *buf;683 unsigned long irqflags;684 int ret;685 686 /* Program the CEU interface according to the CEU image format. */687 ret = ceu_hw_config(ceudev);688 if (ret)689 goto error_return_bufs;690 691 ret = v4l2_subdev_call(v4l2_sd, video, s_stream, 1);692 if (ret && ret != -ENOIOCTLCMD) {693 dev_dbg(ceudev->dev,694 "Subdevice failed to start streaming: %d\n", ret);695 goto error_return_bufs;696 }697 698 spin_lock_irqsave(&ceudev->lock, irqflags);699 ceudev->sequence = 0;700 701 /* Grab the first available buffer and trigger the first capture. */702 buf = list_first_entry(&ceudev->capture, struct ceu_buffer,703 queue);704 705 list_del(&buf->queue);706 ceudev->active = &buf->vb;707 708 /* Clean and program interrupts for first capture. */709 ceu_write(ceudev, CEU_CETCR, ~ceudev->irq_mask);710 ceu_write(ceudev, CEU_CEIER, CEU_CEIER_MASK);711 712 ceu_capture(ceudev);713 714 spin_unlock_irqrestore(&ceudev->lock, irqflags);715 716 return 0;717 718error_return_bufs:719 spin_lock_irqsave(&ceudev->lock, irqflags);720 list_for_each_entry(buf, &ceudev->capture, queue)721 vb2_buffer_done(&ceudev->active->vb2_buf,722 VB2_BUF_STATE_QUEUED);723 ceudev->active = NULL;724 spin_unlock_irqrestore(&ceudev->lock, irqflags);725 726 return ret;727}728 729static void ceu_stop_streaming(struct vb2_queue *vq)730{731 struct ceu_device *ceudev = vb2_get_drv_priv(vq);732 struct v4l2_subdev *v4l2_sd = ceudev->sd->v4l2_sd;733 struct ceu_buffer *buf;734 unsigned long irqflags;735 736 /* Clean and disable interrupt sources. */737 ceu_write(ceudev, CEU_CETCR,738 ceu_read(ceudev, CEU_CETCR) & ceudev->irq_mask);739 ceu_write(ceudev, CEU_CEIER, CEU_CEIER_MASK);740 741 v4l2_subdev_call(v4l2_sd, video, s_stream, 0);742 743 spin_lock_irqsave(&ceudev->lock, irqflags);744 if (ceudev->active) {745 vb2_buffer_done(&ceudev->active->vb2_buf,746 VB2_BUF_STATE_ERROR);747 ceudev->active = NULL;748 }749 750 /* Release all queued buffers. */751 list_for_each_entry(buf, &ceudev->capture, queue)752 vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);753 INIT_LIST_HEAD(&ceudev->capture);754 755 spin_unlock_irqrestore(&ceudev->lock, irqflags);756 757 ceu_soft_reset(ceudev);758}759 760static const struct vb2_ops ceu_vb2_ops = {761 .queue_setup = ceu_vb2_setup,762 .buf_queue = ceu_vb2_queue,763 .buf_prepare = ceu_vb2_prepare,764 .wait_prepare = vb2_ops_wait_prepare,765 .wait_finish = vb2_ops_wait_finish,766 .start_streaming = ceu_start_streaming,767 .stop_streaming = ceu_stop_streaming,768};769 770/* --- CEU image formats handling --- */771 772/*773 * __ceu_try_fmt() - test format on CEU and sensor774 * @ceudev: The CEU device.775 * @v4l2_fmt: format to test.776 * @sd_mbus_code: the media bus code accepted by the subdevice; output param.777 *778 * Returns 0 for success, < 0 for errors.779 */780static int __ceu_try_fmt(struct ceu_device *ceudev, struct v4l2_format *v4l2_fmt,781 u32 *sd_mbus_code)782{783 struct ceu_subdev *ceu_sd = ceudev->sd;784 struct v4l2_pix_format_mplane *pix = &v4l2_fmt->fmt.pix_mp;785 struct v4l2_subdev *v4l2_sd = ceu_sd->v4l2_sd;786 struct v4l2_subdev_pad_config pad_cfg;787 struct v4l2_subdev_state pad_state = {788 .pads = &pad_cfg,789 };790 const struct ceu_fmt *ceu_fmt;791 u32 mbus_code_old;792 u32 mbus_code;793 int ret;794 795 /*796 * Set format on sensor sub device: bus format used to produce memory797 * format is selected depending on YUV component ordering or798 * at initialization time.799 */800 struct v4l2_subdev_format sd_format = {801 .which = V4L2_SUBDEV_FORMAT_TRY,802 };803 804 mbus_code_old = ceu_sd->mbus_fmt.mbus_code;805 806 switch (pix->pixelformat) {807 case V4L2_PIX_FMT_YUYV:808 mbus_code = MEDIA_BUS_FMT_YUYV8_2X8;809 break;810 case V4L2_PIX_FMT_UYVY:811 mbus_code = MEDIA_BUS_FMT_UYVY8_2X8;812 break;813 case V4L2_PIX_FMT_YVYU:814 mbus_code = MEDIA_BUS_FMT_YVYU8_2X8;815 break;816 case V4L2_PIX_FMT_VYUY:817 mbus_code = MEDIA_BUS_FMT_VYUY8_2X8;818 break;819 case V4L2_PIX_FMT_NV16:820 case V4L2_PIX_FMT_NV61:821 case V4L2_PIX_FMT_NV12:822 case V4L2_PIX_FMT_NV21:823 mbus_code = ceu_sd->mbus_fmt.mbus_code;824 break;825 826 default:827 pix->pixelformat = V4L2_PIX_FMT_NV16;828 mbus_code = ceu_sd->mbus_fmt.mbus_code;829 break;830 }831 832 ceu_fmt = get_ceu_fmt_from_fourcc(pix->pixelformat);833 834 /* CFSZR requires height and width to be 4-pixel aligned. */835 v4l_bound_align_image(&pix->width, 2, CEU_MAX_WIDTH, 4,836 &pix->height, 4, CEU_MAX_HEIGHT, 4, 0);837 838 v4l2_fill_mbus_format_mplane(&sd_format.format, pix);839 840 /*841 * Try with the mbus_code matching YUYV components ordering first,842 * if that one fails, fallback to default selected at initialization843 * time.844 */845 sd_format.format.code = mbus_code;846 ret = v4l2_subdev_call(v4l2_sd, pad, set_fmt, &pad_state, &sd_format);847 if (ret) {848 if (ret == -EINVAL) {849 /* fallback */850 sd_format.format.code = mbus_code_old;851 ret = v4l2_subdev_call(v4l2_sd, pad, set_fmt,852 &pad_state, &sd_format);853 }854 855 if (ret)856 return ret;857 }858 859 /* Apply size returned by sensor as the CEU can't scale. */860 v4l2_fill_pix_format_mplane(pix, &sd_format.format);861 862 /* Calculate per-plane sizes based on image format. */863 ceu_calc_plane_sizes(ceudev, ceu_fmt, pix);864 865 /* Report to caller the configured mbus format. */866 *sd_mbus_code = sd_format.format.code;867 868 return 0;869}870 871/*872 * ceu_try_fmt() - Wrapper for __ceu_try_fmt; discard configured mbus_fmt873 */874static int ceu_try_fmt(struct ceu_device *ceudev, struct v4l2_format *v4l2_fmt)875{876 u32 mbus_code;877 878 return __ceu_try_fmt(ceudev, v4l2_fmt, &mbus_code);879}880 881/*882 * ceu_set_fmt() - Apply the supplied format to both sensor and CEU883 */884static int ceu_set_fmt(struct ceu_device *ceudev, struct v4l2_format *v4l2_fmt)885{886 struct ceu_subdev *ceu_sd = ceudev->sd;887 struct v4l2_subdev *v4l2_sd = ceu_sd->v4l2_sd;888 u32 mbus_code;889 int ret;890 891 /*892 * Set format on sensor sub device: bus format used to produce memory893 * format is selected at initialization time.894 */895 struct v4l2_subdev_format format = {896 .which = V4L2_SUBDEV_FORMAT_ACTIVE,897 };898 899 ret = __ceu_try_fmt(ceudev, v4l2_fmt, &mbus_code);900 if (ret)901 return ret;902 903 format.format.code = mbus_code;904 v4l2_fill_mbus_format_mplane(&format.format, &v4l2_fmt->fmt.pix_mp);905 ret = v4l2_subdev_call(v4l2_sd, pad, set_fmt, NULL, &format);906 if (ret)907 return ret;908 909 ceudev->v4l2_pix = v4l2_fmt->fmt.pix_mp;910 ceudev->field = V4L2_FIELD_NONE;911 912 return 0;913}914 915/*916 * ceu_set_default_fmt() - Apply default NV16 memory output format with VGA917 * sizes.918 */919static int ceu_set_default_fmt(struct ceu_device *ceudev)920{921 int ret;922 923 struct v4l2_format v4l2_fmt = {924 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,925 .fmt.pix_mp = {926 .width = VGA_WIDTH,927 .height = VGA_HEIGHT,928 .field = V4L2_FIELD_NONE,929 .pixelformat = V4L2_PIX_FMT_NV16,930 .num_planes = 2,931 .plane_fmt = {932 [0] = {933 .sizeimage = VGA_WIDTH * VGA_HEIGHT * 2,934 .bytesperline = VGA_WIDTH * 2,935 },936 [1] = {937 .sizeimage = VGA_WIDTH * VGA_HEIGHT * 2,938 .bytesperline = VGA_WIDTH * 2,939 },940 },941 },942 };943 944 ret = ceu_try_fmt(ceudev, &v4l2_fmt);945 if (ret)946 return ret;947 948 ceudev->v4l2_pix = v4l2_fmt.fmt.pix_mp;949 ceudev->field = V4L2_FIELD_NONE;950 951 return 0;952}953 954/*955 * ceu_init_mbus_fmt() - Query sensor for supported formats and initialize956 * CEU media bus format used to produce memory formats.957 *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 memory960 * output formats:961 * - NV[12|21|16|61] through image fetch mode;962 * - YUYV422 if sensor provides YUYV422963 *964 * TODO: Other YUYV422 permutations through data fetch sync mode and DTARY965 * TODO: Binary data (eg. JPEG) and raw formats through data fetch sync mode966 */967static int ceu_init_mbus_fmt(struct ceu_device *ceudev)968{969 struct ceu_subdev *ceu_sd = ceudev->sd;970 struct ceu_mbus_fmt *mbus_fmt = &ceu_sd->mbus_fmt;971 struct v4l2_subdev *v4l2_sd = ceu_sd->v4l2_sd;972 bool yuyv_bus_fmt = false;973 974 struct v4l2_subdev_mbus_code_enum sd_mbus_fmt = {975 .which = V4L2_SUBDEV_FORMAT_ACTIVE,976 .index = 0,977 };978 979 /* Find out if sensor can produce any permutation of 8-bits YUYV422. */980 while (!yuyv_bus_fmt &&981 !v4l2_subdev_call(v4l2_sd, pad, enum_mbus_code,982 NULL, &sd_mbus_fmt)) {983 switch (sd_mbus_fmt.code) {984 case MEDIA_BUS_FMT_YUYV8_2X8:985 case MEDIA_BUS_FMT_YVYU8_2X8:986 case MEDIA_BUS_FMT_UYVY8_2X8:987 case MEDIA_BUS_FMT_VYUY8_2X8:988 yuyv_bus_fmt = true;989 break;990 default:991 /*992 * Only support 8-bits YUYV bus formats at the moment;993 *994 * TODO: add support for binary formats (data sync995 * fetch mode).996 */997 break;998 }999 1000 sd_mbus_fmt.index++;1001 }1002 1003 if (!yuyv_bus_fmt)1004 return -ENXIO;1005 1006 /*1007 * Save the first encountered YUYV format as "mbus_fmt" and use it1008 * to output all planar YUV422 and YUV420 (NV*) formats to memory as1009 * well as for data synch fetch mode (YUYV - YVYU etc. ).1010 */1011 mbus_fmt->mbus_code = sd_mbus_fmt.code;1012 mbus_fmt->bps = 8;1013 1014 /* Annotate the selected bus format components ordering. */1015 switch (sd_mbus_fmt.code) {1016 case MEDIA_BUS_FMT_YUYV8_2X8:1017 mbus_fmt->fmt_order = CEU_CAMCR_DTARY_8_YUYV;1018 mbus_fmt->fmt_order_swap = CEU_CAMCR_DTARY_8_YVYU;1019 mbus_fmt->swapped = false;1020 mbus_fmt->bpp = 16;1021 break;1022 1023 case MEDIA_BUS_FMT_YVYU8_2X8:1024 mbus_fmt->fmt_order = CEU_CAMCR_DTARY_8_YVYU;1025 mbus_fmt->fmt_order_swap = CEU_CAMCR_DTARY_8_YUYV;1026 mbus_fmt->swapped = true;1027 mbus_fmt->bpp = 16;1028 break;1029 1030 case MEDIA_BUS_FMT_UYVY8_2X8:1031 mbus_fmt->fmt_order = CEU_CAMCR_DTARY_8_UYVY;1032 mbus_fmt->fmt_order_swap = CEU_CAMCR_DTARY_8_VYUY;1033 mbus_fmt->swapped = false;1034 mbus_fmt->bpp = 16;1035 break;1036 1037 case MEDIA_BUS_FMT_VYUY8_2X8:1038 mbus_fmt->fmt_order = CEU_CAMCR_DTARY_8_VYUY;1039 mbus_fmt->fmt_order_swap = CEU_CAMCR_DTARY_8_UYVY;1040 mbus_fmt->swapped = true;1041 mbus_fmt->bpp = 16;1042 break;1043 }1044 1045 return 0;1046}1047 1048/* --- Runtime PM Handlers --- */1049 1050/*1051 * ceu_runtime_resume() - soft-reset the interface and turn sensor power on.1052 */1053static int __maybe_unused ceu_runtime_resume(struct device *dev)1054{1055 struct ceu_device *ceudev = dev_get_drvdata(dev);1056 struct v4l2_subdev *v4l2_sd = ceudev->sd->v4l2_sd;1057 1058 v4l2_subdev_call(v4l2_sd, core, s_power, 1);1059 1060 ceu_soft_reset(ceudev);1061 1062 return 0;1063}1064 1065/*1066 * ceu_runtime_suspend() - disable capture and interrupts and soft-reset.1067 * Turn sensor power off.1068 */1069static int __maybe_unused ceu_runtime_suspend(struct device *dev)1070{1071 struct ceu_device *ceudev = dev_get_drvdata(dev);1072 struct v4l2_subdev *v4l2_sd = ceudev->sd->v4l2_sd;1073 1074 v4l2_subdev_call(v4l2_sd, core, s_power, 0);1075 1076 ceu_write(ceudev, CEU_CEIER, 0);1077 ceu_soft_reset(ceudev);1078 1079 return 0;1080}1081 1082/* --- File Operations --- */1083 1084static int ceu_open(struct file *file)1085{1086 struct ceu_device *ceudev = video_drvdata(file);1087 int ret;1088 1089 ret = v4l2_fh_open(file);1090 if (ret)1091 return ret;1092 1093 mutex_lock(&ceudev->mlock);1094 /* Causes soft-reset and sensor power on on first open */1095 ret = pm_runtime_resume_and_get(ceudev->dev);1096 mutex_unlock(&ceudev->mlock);1097 1098 return ret;1099}1100 1101static int ceu_release(struct file *file)1102{1103 struct ceu_device *ceudev = video_drvdata(file);1104 1105 vb2_fop_release(file);1106 1107 mutex_lock(&ceudev->mlock);1108 /* Causes soft-reset and sensor power down on last close */1109 pm_runtime_put(ceudev->dev);1110 mutex_unlock(&ceudev->mlock);1111 1112 return 0;1113}1114 1115static const struct v4l2_file_operations ceu_fops = {1116 .owner = THIS_MODULE,1117 .open = ceu_open,1118 .release = ceu_release,1119 .unlocked_ioctl = video_ioctl2,1120 .mmap = vb2_fop_mmap,1121 .poll = vb2_fop_poll,1122};1123 1124/* --- Video Device IOCTLs --- */1125 1126static int ceu_querycap(struct file *file, void *priv,1127 struct v4l2_capability *cap)1128{1129 struct ceu_device *ceudev = video_drvdata(file);1130 1131 strscpy(cap->card, "Renesas CEU", sizeof(cap->card));1132 strscpy(cap->driver, DRIVER_NAME, sizeof(cap->driver));1133 snprintf(cap->bus_info, sizeof(cap->bus_info),1134 "platform:renesas-ceu-%s", dev_name(ceudev->dev));1135 1136 return 0;1137}1138 1139static int ceu_enum_fmt_vid_cap(struct file *file, void *priv,1140 struct v4l2_fmtdesc *f)1141{1142 const struct ceu_fmt *fmt;1143 1144 if (f->index >= ARRAY_SIZE(ceu_fmt_list))1145 return -EINVAL;1146 1147 fmt = &ceu_fmt_list[f->index];1148 f->pixelformat = fmt->fourcc;1149 1150 return 0;1151}1152 1153static int ceu_try_fmt_vid_cap(struct file *file, void *priv,1154 struct v4l2_format *f)1155{1156 struct ceu_device *ceudev = video_drvdata(file);1157 1158 return ceu_try_fmt(ceudev, f);1159}1160 1161static int ceu_s_fmt_vid_cap(struct file *file, void *priv,1162 struct v4l2_format *f)1163{1164 struct ceu_device *ceudev = video_drvdata(file);1165 1166 if (vb2_is_streaming(&ceudev->vb2_vq))1167 return -EBUSY;1168 1169 return ceu_set_fmt(ceudev, f);1170}1171 1172static int ceu_g_fmt_vid_cap(struct file *file, void *priv,1173 struct v4l2_format *f)1174{1175 struct ceu_device *ceudev = video_drvdata(file);1176 1177 f->fmt.pix_mp = ceudev->v4l2_pix;1178 1179 return 0;1180}1181 1182static int ceu_enum_input(struct file *file, void *priv,1183 struct v4l2_input *inp)1184{1185 struct ceu_device *ceudev = video_drvdata(file);1186 1187 if (inp->index >= ceudev->num_sd)1188 return -EINVAL;1189 1190 inp->type = V4L2_INPUT_TYPE_CAMERA;1191 inp->std = 0;1192 snprintf(inp->name, sizeof(inp->name), "Camera %u", inp->index);1193 1194 return 0;1195}1196 1197static int ceu_g_input(struct file *file, void *priv, unsigned int *i)1198{1199 struct ceu_device *ceudev = video_drvdata(file);1200 1201 *i = ceudev->sd_index;1202 1203 return 0;1204}1205 1206static int ceu_s_input(struct file *file, void *priv, unsigned int i)1207{1208 struct ceu_device *ceudev = video_drvdata(file);1209 struct ceu_subdev *ceu_sd_old;1210 int ret;1211 1212 if (i >= ceudev->num_sd)1213 return -EINVAL;1214 1215 if (vb2_is_streaming(&ceudev->vb2_vq))1216 return -EBUSY;1217 1218 if (i == ceudev->sd_index)1219 return 0;1220 1221 ceu_sd_old = ceudev->sd;1222 ceudev->sd = ceudev->subdevs[i];1223 1224 /*1225 * Make sure we can generate output image formats and apply1226 * default one.1227 */1228 ret = ceu_init_mbus_fmt(ceudev);1229 if (ret) {1230 ceudev->sd = ceu_sd_old;1231 return -EINVAL;1232 }1233 1234 ret = ceu_set_default_fmt(ceudev);1235 if (ret) {1236 ceudev->sd = ceu_sd_old;1237 return -EINVAL;1238 }1239 1240 /* Now that we're sure we can use the sensor, power off the old one. */1241 v4l2_subdev_call(ceu_sd_old->v4l2_sd, core, s_power, 0);1242 v4l2_subdev_call(ceudev->sd->v4l2_sd, core, s_power, 1);1243 1244 ceudev->sd_index = i;1245 1246 return 0;1247}1248 1249static int ceu_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a)1250{1251 struct ceu_device *ceudev = video_drvdata(file);1252 1253 return v4l2_g_parm_cap(video_devdata(file), ceudev->sd->v4l2_sd, a);1254}1255 1256static int ceu_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a)1257{1258 struct ceu_device *ceudev = video_drvdata(file);1259 1260 return v4l2_s_parm_cap(video_devdata(file), ceudev->sd->v4l2_sd, a);1261}1262 1263static int ceu_enum_framesizes(struct file *file, void *fh,1264 struct v4l2_frmsizeenum *fsize)1265{1266 struct ceu_device *ceudev = video_drvdata(file);1267 struct ceu_subdev *ceu_sd = ceudev->sd;1268 const struct ceu_fmt *ceu_fmt;1269 struct v4l2_subdev *v4l2_sd = ceu_sd->v4l2_sd;1270 int ret;1271 1272 struct v4l2_subdev_frame_size_enum fse = {1273 .code = ceu_sd->mbus_fmt.mbus_code,1274 .index = fsize->index,1275 .which = V4L2_SUBDEV_FORMAT_ACTIVE,1276 };1277 1278 /* Just check if user supplied pixel format is supported. */1279 ceu_fmt = get_ceu_fmt_from_fourcc(fsize->pixel_format);1280 if (!ceu_fmt)1281 return -EINVAL;1282 1283 ret = v4l2_subdev_call(v4l2_sd, pad, enum_frame_size,1284 NULL, &fse);1285 if (ret)1286 return ret;1287 1288 fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;1289 fsize->discrete.width = CEU_W_MAX(fse.max_width);1290 fsize->discrete.height = CEU_H_MAX(fse.max_height);1291 1292 return 0;1293}1294 1295static int ceu_enum_frameintervals(struct file *file, void *fh,1296 struct v4l2_frmivalenum *fival)1297{1298 struct ceu_device *ceudev = video_drvdata(file);1299 struct ceu_subdev *ceu_sd = ceudev->sd;1300 const struct ceu_fmt *ceu_fmt;1301 struct v4l2_subdev *v4l2_sd = ceu_sd->v4l2_sd;1302 int ret;1303 1304 struct v4l2_subdev_frame_interval_enum fie = {1305 .code = ceu_sd->mbus_fmt.mbus_code,1306 .index = fival->index,1307 .width = fival->width,1308 .height = fival->height,1309 .which = V4L2_SUBDEV_FORMAT_ACTIVE,1310 };1311 1312 /* Just check if user supplied pixel format is supported. */1313 ceu_fmt = get_ceu_fmt_from_fourcc(fival->pixel_format);1314 if (!ceu_fmt)1315 return -EINVAL;1316 1317 ret = v4l2_subdev_call(v4l2_sd, pad, enum_frame_interval, NULL,1318 &fie);1319 if (ret)1320 return ret;1321 1322 fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;1323 fival->discrete = fie.interval;1324 1325 return 0;1326}1327 1328static const struct v4l2_ioctl_ops ceu_ioctl_ops = {1329 .vidioc_querycap = ceu_querycap,1330 1331 .vidioc_enum_fmt_vid_cap = ceu_enum_fmt_vid_cap,1332 .vidioc_try_fmt_vid_cap_mplane = ceu_try_fmt_vid_cap,1333 .vidioc_s_fmt_vid_cap_mplane = ceu_s_fmt_vid_cap,1334 .vidioc_g_fmt_vid_cap_mplane = ceu_g_fmt_vid_cap,1335 1336 .vidioc_enum_input = ceu_enum_input,1337 .vidioc_g_input = ceu_g_input,1338 .vidioc_s_input = ceu_s_input,1339 1340 .vidioc_reqbufs = vb2_ioctl_reqbufs,1341 .vidioc_querybuf = vb2_ioctl_querybuf,1342 .vidioc_qbuf = vb2_ioctl_qbuf,1343 .vidioc_expbuf = vb2_ioctl_expbuf,1344 .vidioc_dqbuf = vb2_ioctl_dqbuf,1345 .vidioc_create_bufs = vb2_ioctl_create_bufs,1346 .vidioc_prepare_buf = vb2_ioctl_prepare_buf,1347 .vidioc_streamon = vb2_ioctl_streamon,1348 .vidioc_streamoff = vb2_ioctl_streamoff,1349 1350 .vidioc_g_parm = ceu_g_parm,1351 .vidioc_s_parm = ceu_s_parm,1352 .vidioc_enum_framesizes = ceu_enum_framesizes,1353 .vidioc_enum_frameintervals = ceu_enum_frameintervals,1354 1355 .vidioc_log_status = v4l2_ctrl_log_status,1356 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,1357 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,1358};1359 1360/*1361 * ceu_vdev_release() - release CEU video device memory when last reference1362 * to this driver is closed1363 */1364static void ceu_vdev_release(struct video_device *vdev)1365{1366 struct ceu_device *ceudev = video_get_drvdata(vdev);1367 1368 kfree(ceudev);1369}1370 1371static int ceu_notify_bound(struct v4l2_async_notifier *notifier,1372 struct v4l2_subdev *v4l2_sd,1373 struct v4l2_async_connection *asd)1374{1375 struct v4l2_device *v4l2_dev = notifier->v4l2_dev;1376 struct ceu_device *ceudev = v4l2_to_ceu(v4l2_dev);1377 struct ceu_subdev *ceu_sd = to_ceu_subdev(asd);1378 1379 ceu_sd->v4l2_sd = v4l2_sd;1380 ceudev->num_sd++;1381 1382 return 0;1383}1384 1385static int ceu_notify_complete(struct v4l2_async_notifier *notifier)1386{1387 struct v4l2_device *v4l2_dev = notifier->v4l2_dev;1388 struct ceu_device *ceudev = v4l2_to_ceu(v4l2_dev);1389 struct video_device *vdev = &ceudev->vdev;1390 struct vb2_queue *q = &ceudev->vb2_vq;1391 struct v4l2_subdev *v4l2_sd;1392 int ret;1393 1394 /* Initialize vb2 queue. */1395 q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;1396 q->io_modes = VB2_MMAP | VB2_DMABUF;1397 q->drv_priv = ceudev;1398 q->ops = &ceu_vb2_ops;1399 q->mem_ops = &vb2_dma_contig_memops;1400 q->buf_struct_size = sizeof(struct ceu_buffer);1401 q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;1402 q->min_queued_buffers = 2;1403 q->lock = &ceudev->mlock;1404 q->dev = ceudev->v4l2_dev.dev;1405 1406 ret = vb2_queue_init(q);1407 if (ret)1408 return ret;1409 1410 /*1411 * Make sure at least one sensor is primary and use it to initialize1412 * ceu formats.1413 */1414 if (!ceudev->sd) {1415 ceudev->sd = ceudev->subdevs[0];1416 ceudev->sd_index = 0;1417 }1418 1419 v4l2_sd = ceudev->sd->v4l2_sd;1420 1421 ret = ceu_init_mbus_fmt(ceudev);1422 if (ret)1423 return ret;1424 1425 ret = ceu_set_default_fmt(ceudev);1426 if (ret)1427 return ret;1428 1429 /* Register the video device. */1430 strscpy(vdev->name, DRIVER_NAME, sizeof(vdev->name));1431 vdev->v4l2_dev = v4l2_dev;1432 vdev->lock = &ceudev->mlock;1433 vdev->queue = &ceudev->vb2_vq;1434 vdev->ctrl_handler = v4l2_sd->ctrl_handler;1435 vdev->fops = &ceu_fops;1436 vdev->ioctl_ops = &ceu_ioctl_ops;1437 vdev->release = ceu_vdev_release;1438 vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE |1439 V4L2_CAP_STREAMING;1440 video_set_drvdata(vdev, ceudev);1441 1442 ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);1443 if (ret < 0) {1444 v4l2_err(vdev->v4l2_dev,1445 "video_register_device failed: %d\n", ret);1446 return ret;1447 }1448 1449 return 0;1450}1451 1452static const struct v4l2_async_notifier_operations ceu_notify_ops = {1453 .bound = ceu_notify_bound,1454 .complete = ceu_notify_complete,1455};1456 1457/*1458 * ceu_init_async_subdevs() - Initialize CEU subdevices and async_subdevs in1459 * ceu device. Both DT and platform data parsing use1460 * this routine.1461 *1462 * Returns 0 for success, -ENOMEM for failure.1463 */1464static int ceu_init_async_subdevs(struct ceu_device *ceudev, unsigned int n_sd)1465{1466 /* Reserve memory for 'n_sd' ceu_subdev descriptors. */1467 ceudev->subdevs = devm_kcalloc(ceudev->dev, n_sd,1468 sizeof(*ceudev->subdevs), GFP_KERNEL);1469 if (!ceudev->subdevs)1470 return -ENOMEM;1471 1472 ceudev->sd = NULL;1473 ceudev->sd_index = 0;1474 ceudev->num_sd = 0;1475 1476 return 0;1477}1478 1479/*1480 * ceu_parse_platform_data() - Initialize async_subdevices using platform1481 * device provided data.1482 */1483static int ceu_parse_platform_data(struct ceu_device *ceudev,1484 const struct ceu_platform_data *pdata)1485{1486 const struct ceu_async_subdev *async_sd;1487 struct ceu_subdev *ceu_sd;1488 unsigned int i;1489 int ret;1490 1491 if (pdata->num_subdevs == 0)1492 return -ENODEV;1493 1494 ret = ceu_init_async_subdevs(ceudev, pdata->num_subdevs);1495 if (ret)1496 return ret;1497 1498 for (i = 0; i < pdata->num_subdevs; i++) {1499 1500 /* Setup the ceu subdevice and the async subdevice. */1501 async_sd = &pdata->subdevs[i];1502 ceu_sd = v4l2_async_nf_add_i2c(&ceudev->notifier,1503 async_sd->i2c_adapter_id,1504 async_sd->i2c_address,1505 struct ceu_subdev);1506 if (IS_ERR(ceu_sd)) {1507 v4l2_async_nf_cleanup(&ceudev->notifier);1508 return PTR_ERR(ceu_sd);1509 }1510 ceu_sd->mbus_flags = async_sd->flags;1511 ceudev->subdevs[i] = ceu_sd;1512 }1513 1514 return pdata->num_subdevs;1515}1516 1517/*1518 * ceu_parse_dt() - Initialize async_subdevs parsing device tree graph.1519 */1520static int ceu_parse_dt(struct ceu_device *ceudev)1521{1522 struct device_node *of = ceudev->dev->of_node;1523 struct device_node *ep;1524 struct ceu_subdev *ceu_sd;1525 unsigned int i;1526 int num_ep;1527 int ret;1528 1529 num_ep = of_graph_get_endpoint_count(of);1530 if (!num_ep)1531 return -ENODEV;1532 1533 ret = ceu_init_async_subdevs(ceudev, num_ep);1534 if (ret)1535 return ret;1536 1537 for (i = 0; i < num_ep; i++) {1538 struct v4l2_fwnode_endpoint fw_ep = {1539 .bus_type = V4L2_MBUS_PARALLEL,1540 .bus = {1541 .parallel = {1542 .flags = V4L2_MBUS_HSYNC_ACTIVE_HIGH |1543 V4L2_MBUS_VSYNC_ACTIVE_HIGH,1544 .bus_width = 8,1545 },1546 },1547 };1548 1549 ep = of_graph_get_endpoint_by_regs(of, 0, i);1550 if (!ep) {1551 dev_err(ceudev->dev,1552 "No subdevice connected on endpoint %u.\n", i);1553 ret = -ENODEV;1554 goto error_cleanup;1555 }1556 1557 ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep), &fw_ep);1558 if (ret) {1559 dev_err(ceudev->dev,1560 "Unable to parse endpoint #%u: %d.\n", i, ret);1561 goto error_cleanup;1562 }1563 1564 /* Setup the ceu subdevice and the async subdevice. */1565 ceu_sd = v4l2_async_nf_add_fwnode_remote(&ceudev->notifier,1566 of_fwnode_handle(ep),1567 struct ceu_subdev);1568 if (IS_ERR(ceu_sd)) {1569 ret = PTR_ERR(ceu_sd);1570 goto error_cleanup;1571 }1572 ceu_sd->mbus_flags = fw_ep.bus.parallel.flags;1573 ceudev->subdevs[i] = ceu_sd;1574 1575 of_node_put(ep);1576 }1577 1578 return num_ep;1579 1580error_cleanup:1581 v4l2_async_nf_cleanup(&ceudev->notifier);1582 of_node_put(ep);1583 return ret;1584}1585 1586/*1587 * struct ceu_data - Platform specific CEU data1588 * @irq_mask: CETCR mask with all interrupt sources enabled. The mask differs1589 * between SH4 and RZ platforms.1590 */1591struct ceu_data {1592 u32 irq_mask;1593};1594 1595static const struct ceu_data ceu_data_sh4 = {1596 .irq_mask = CEU_CETCR_ALL_IRQS_SH4,1597};1598 1599#if IS_ENABLED(CONFIG_OF)1600static const struct ceu_data ceu_data_rz = {1601 .irq_mask = CEU_CETCR_ALL_IRQS_RZ,1602};1603 1604static const struct of_device_id ceu_of_match[] = {1605 { .compatible = "renesas,r7s72100-ceu", .data = &ceu_data_rz },1606 { .compatible = "renesas,r8a7740-ceu", .data = &ceu_data_rz },1607 { }1608};1609MODULE_DEVICE_TABLE(of, ceu_of_match);1610#endif1611 1612static int ceu_probe(struct platform_device *pdev)1613{1614 struct device *dev = &pdev->dev;1615 const struct ceu_data *ceu_data;1616 struct ceu_device *ceudev;1617 unsigned int irq;1618 int num_subdevs;1619 int ret;1620 1621 ceudev = kzalloc(sizeof(*ceudev), GFP_KERNEL);1622 if (!ceudev)1623 return -ENOMEM;1624 1625 platform_set_drvdata(pdev, ceudev);1626 ceudev->dev = dev;1627 1628 INIT_LIST_HEAD(&ceudev->capture);1629 spin_lock_init(&ceudev->lock);1630 mutex_init(&ceudev->mlock);1631 1632 ceudev->base = devm_platform_ioremap_resource(pdev, 0);1633 if (IS_ERR(ceudev->base)) {1634 ret = PTR_ERR(ceudev->base);1635 goto error_free_ceudev;1636 }1637 1638 ret = platform_get_irq(pdev, 0);1639 if (ret < 0)1640 goto error_free_ceudev;1641 irq = ret;1642 1643 ret = devm_request_irq(dev, irq, ceu_irq,1644 0, dev_name(dev), ceudev);1645 if (ret) {1646 dev_err(&pdev->dev, "Unable to request CEU interrupt.\n");1647 goto error_free_ceudev;1648 }1649 1650 pm_runtime_enable(dev);1651 1652 ret = v4l2_device_register(dev, &ceudev->v4l2_dev);1653 if (ret)1654 goto error_pm_disable;1655 1656 v4l2_async_nf_init(&ceudev->notifier, &ceudev->v4l2_dev);1657 1658 if (IS_ENABLED(CONFIG_OF) && dev->of_node) {1659 ceu_data = of_device_get_match_data(dev);1660 num_subdevs = ceu_parse_dt(ceudev);1661 } else if (dev->platform_data) {1662 /* Assume SH4 if booting with platform data. */1663 ceu_data = &ceu_data_sh4;1664 num_subdevs = ceu_parse_platform_data(ceudev,1665 dev->platform_data);1666 } else {1667 num_subdevs = -EINVAL;1668 }1669 1670 if (num_subdevs < 0) {1671 ret = num_subdevs;1672 goto error_v4l2_unregister;1673 }1674 ceudev->irq_mask = ceu_data->irq_mask;1675 1676 ceudev->notifier.v4l2_dev = &ceudev->v4l2_dev;1677 ceudev->notifier.ops = &ceu_notify_ops;1678 ret = v4l2_async_nf_register(&ceudev->notifier);1679 if (ret)1680 goto error_cleanup;1681 1682 dev_info(dev, "Renesas Capture Engine Unit %s\n", dev_name(dev));1683 1684 return 0;1685 1686error_cleanup:1687 v4l2_async_nf_cleanup(&ceudev->notifier);1688error_v4l2_unregister:1689 v4l2_device_unregister(&ceudev->v4l2_dev);1690error_pm_disable:1691 pm_runtime_disable(dev);1692error_free_ceudev:1693 kfree(ceudev);1694 1695 return ret;1696}1697 1698static void ceu_remove(struct platform_device *pdev)1699{1700 struct ceu_device *ceudev = platform_get_drvdata(pdev);1701 1702 pm_runtime_disable(ceudev->dev);1703 1704 v4l2_async_nf_unregister(&ceudev->notifier);1705 1706 v4l2_async_nf_cleanup(&ceudev->notifier);1707 1708 v4l2_device_unregister(&ceudev->v4l2_dev);1709 1710 video_unregister_device(&ceudev->vdev);1711}1712 1713static const struct dev_pm_ops ceu_pm_ops = {1714 SET_RUNTIME_PM_OPS(ceu_runtime_suspend,1715 ceu_runtime_resume,1716 NULL)1717};1718 1719static struct platform_driver ceu_driver = {1720 .driver = {1721 .name = DRIVER_NAME,1722 .pm = &ceu_pm_ops,1723 .of_match_table = of_match_ptr(ceu_of_match),1724 },1725 .probe = ceu_probe,1726 .remove_new = ceu_remove,1727};1728 1729module_platform_driver(ceu_driver);1730 1731MODULE_DESCRIPTION("Renesas CEU camera driver");1732MODULE_AUTHOR("Jacopo Mondi <jacopo+renesas@jmondi.org>");1733MODULE_LICENSE("GPL v2");1734