brintos

brintos / linux-shallow public Read only

0
0
Text · 43.4 KiB · 1677602 Raw
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