File Index
Files and directories
Sign in
FILE

atmel-isi.c

File preview with syntax highlighting.

linux-6.19.14/drivers/media/platform/atmel/atmel-isi.c C
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (c) 2011 Atmel Corporation
   4 * Josh Wu, <josh.wu@atmel.com>
   5 *
   6 * Based on previous work by Lars Haring, <lars.haring@atmel.com>
   7 * and Sedji Gaouaou
   8 * Based on the bttv driver for Bt848 with respective copyright holders
   9 */
  10
  11#include <linux/clk.h>
  12#include <linux/completion.h>
  13#include <linux/delay.h>
  14#include <linux/fs.h>
  15#include <linux/init.h>
  16#include <linux/interrupt.h>
  17#include <linux/kernel.h>
  18#include <linux/module.h>
  19#include <linux/of_graph.h>
  20#include <linux/platform_device.h>
  21#include <linux/pm_runtime.h>
  22#include <linux/slab.h>
  23#include <linux/of.h>
  24
  25#include <linux/videodev2.h>
  26#include <media/v4l2-ctrls.h>
  27#include <media/v4l2-device.h>
  28#include <media/v4l2-dev.h>
  29#include <media/v4l2-ioctl.h>
  30#include <media/v4l2-event.h>
  31#include <media/v4l2-fwnode.h>
  32#include <media/videobuf2-dma-contig.h>
  33#include <media/v4l2-image-sizes.h>
  34
  35#include "atmel-isi.h"
  36
  37#define MAX_SUPPORT_WIDTH		2048U
  38#define MAX_SUPPORT_HEIGHT		2048U
  39#define MIN_FRAME_RATE			15
  40#define FRAME_INTERVAL_MILLI_SEC	(1000 / MIN_FRAME_RATE)
  41
  42/* Frame buffer descriptor */
  43struct fbd {
  44	/* Physical address of the frame buffer */
  45	u32 fb_address;
  46	/* DMA Control Register(only in HISI2) */
  47	u32 dma_ctrl;
  48	/* Physical address of the next fbd */
  49	u32 next_fbd_address;
  50};
  51
  52static void set_dma_ctrl(struct fbd *fb_desc, u32 ctrl)
  53{
  54	fb_desc->dma_ctrl = ctrl;
  55}
  56
  57struct isi_dma_desc {
  58	struct list_head list;
  59	struct fbd *p_fbd;
  60	dma_addr_t fbd_phys;
  61};
  62
  63/* Frame buffer data */
  64struct frame_buffer {
  65	struct vb2_v4l2_buffer vb;
  66	struct isi_dma_desc *p_dma_desc;
  67	struct list_head list;
  68};
  69
  70struct isi_graph_entity {
  71	struct device_node *node;
  72
  73	struct v4l2_subdev *subdev;
  74};
  75
  76/*
  77 * struct isi_format - ISI media bus format information
  78 * @fourcc:		Fourcc code for this format
  79 * @mbus_code:		V4L2 media bus format code.
  80 * @bpp:		Bytes per pixel (when stored in memory)
  81 * @swap:		Byte swap configuration value
  82 * @support:		Indicates format supported by subdev
  83 * @skip:		Skip duplicate format supported by subdev
  84 */
  85struct isi_format {
  86	u32	fourcc;
  87	u32	mbus_code;
  88	u8	bpp;
  89	u32	swap;
  90};
  91
  92
  93struct atmel_isi {
  94	/* Protects the access of variables shared with the ISR */
  95	spinlock_t			irqlock;
  96	struct device			*dev;
  97	void __iomem			*regs;
  98
  99	int				sequence;
 100
 101	/* Allocate descriptors for dma buffer use */
 102	struct fbd			*p_fb_descriptors;
 103	dma_addr_t			fb_descriptors_phys;
 104	struct				list_head dma_desc_head;
 105	struct isi_dma_desc		dma_desc[VIDEO_MAX_FRAME];
 106	bool				enable_preview_path;
 107
 108	struct completion		complete;
 109	/* ISI peripheral clock */
 110	struct clk			*pclk;
 111	unsigned int			irq;
 112
 113	struct isi_platform_data	pdata;
 114	u16				width_flags;	/* max 12 bits */
 115
 116	struct list_head		video_buffer_list;
 117	struct frame_buffer		*active;
 118
 119	struct v4l2_device		v4l2_dev;
 120	struct video_device		*vdev;
 121	struct v4l2_async_notifier	notifier;
 122	struct isi_graph_entity		entity;
 123	struct v4l2_format		fmt;
 124
 125	const struct isi_format		**user_formats;
 126	unsigned int			num_user_formats;
 127	const struct isi_format		*current_fmt;
 128
 129	struct mutex			lock;
 130	struct vb2_queue		queue;
 131};
 132
 133#define notifier_to_isi(n) container_of(n, struct atmel_isi, notifier)
 134
 135static void isi_writel(struct atmel_isi *isi, u32 reg, u32 val)
 136{
 137	writel(val, isi->regs + reg);
 138}
 139static u32 isi_readl(struct atmel_isi *isi, u32 reg)
 140{
 141	return readl(isi->regs + reg);
 142}
 143
 144static void configure_geometry(struct atmel_isi *isi)
 145{
 146	u32 cfg2, psize;
 147	u32 fourcc = isi->current_fmt->fourcc;
 148
 149	isi->enable_preview_path = fourcc == V4L2_PIX_FMT_RGB565 ||
 150				   fourcc == V4L2_PIX_FMT_RGB32 ||
 151				   fourcc == V4L2_PIX_FMT_Y16;
 152
 153	/* According to sensor's output format to set cfg2 */
 154	cfg2 = isi->current_fmt->swap;
 155
 156	isi_writel(isi, ISI_CTRL, ISI_CTRL_DIS);
 157	/* Set width */
 158	cfg2 |= ((isi->fmt.fmt.pix.width - 1) << ISI_CFG2_IM_HSIZE_OFFSET) &
 159			ISI_CFG2_IM_HSIZE_MASK;
 160	/* Set height */
 161	cfg2 |= ((isi->fmt.fmt.pix.height - 1) << ISI_CFG2_IM_VSIZE_OFFSET)
 162			& ISI_CFG2_IM_VSIZE_MASK;
 163	isi_writel(isi, ISI_CFG2, cfg2);
 164
 165	/* No down sampling, preview size equal to sensor output size */
 166	psize = ((isi->fmt.fmt.pix.width - 1) << ISI_PSIZE_PREV_HSIZE_OFFSET) &
 167		ISI_PSIZE_PREV_HSIZE_MASK;
 168	psize |= ((isi->fmt.fmt.pix.height - 1) << ISI_PSIZE_PREV_VSIZE_OFFSET) &
 169		ISI_PSIZE_PREV_VSIZE_MASK;
 170	isi_writel(isi, ISI_PSIZE, psize);
 171	isi_writel(isi, ISI_PDECF, ISI_PDECF_NO_SAMPLING);
 172}
 173
 174static irqreturn_t atmel_isi_handle_streaming(struct atmel_isi *isi)
 175{
 176	if (isi->active) {
 177		struct vb2_v4l2_buffer *vbuf = &isi->active->vb;
 178		struct frame_buffer *buf = isi->active;
 179
 180		list_del_init(&buf->list);
 181		vbuf->vb2_buf.timestamp = ktime_get_ns();
 182		vbuf->sequence = isi->sequence++;
 183		vbuf->field = V4L2_FIELD_NONE;
 184		vb2_buffer_done(&vbuf->vb2_buf, VB2_BUF_STATE_DONE);
 185	}
 186
 187	if (list_empty(&isi->video_buffer_list)) {
 188		isi->active = NULL;
 189	} else {
 190		/* start next dma frame. */
 191		isi->active = list_entry(isi->video_buffer_list.next,
 192					struct frame_buffer, list);
 193		if (!isi->enable_preview_path) {
 194			isi_writel(isi, ISI_DMA_C_DSCR,
 195				(u32)isi->active->p_dma_desc->fbd_phys);
 196			isi_writel(isi, ISI_DMA_C_CTRL,
 197				ISI_DMA_CTRL_FETCH | ISI_DMA_CTRL_DONE);
 198			isi_writel(isi, ISI_DMA_CHER, ISI_DMA_CHSR_C_CH);
 199		} else {
 200			isi_writel(isi, ISI_DMA_P_DSCR,
 201				(u32)isi->active->p_dma_desc->fbd_phys);
 202			isi_writel(isi, ISI_DMA_P_CTRL,
 203				ISI_DMA_CTRL_FETCH | ISI_DMA_CTRL_DONE);
 204			isi_writel(isi, ISI_DMA_CHER, ISI_DMA_CHSR_P_CH);
 205		}
 206	}
 207	return IRQ_HANDLED;
 208}
 209
 210/* ISI interrupt service routine */
 211static irqreturn_t isi_interrupt(int irq, void *dev_id)
 212{
 213	struct atmel_isi *isi = dev_id;
 214	u32 status, mask, pending;
 215	irqreturn_t ret = IRQ_NONE;
 216
 217	spin_lock(&isi->irqlock);
 218
 219	status = isi_readl(isi, ISI_STATUS);
 220	mask = isi_readl(isi, ISI_INTMASK);
 221	pending = status & mask;
 222
 223	if (pending & ISI_CTRL_SRST) {
 224		complete(&isi->complete);
 225		isi_writel(isi, ISI_INTDIS, ISI_CTRL_SRST);
 226		ret = IRQ_HANDLED;
 227	} else if (pending & ISI_CTRL_DIS) {
 228		complete(&isi->complete);
 229		isi_writel(isi, ISI_INTDIS, ISI_CTRL_DIS);
 230		ret = IRQ_HANDLED;
 231	} else {
 232		if (likely(pending & ISI_SR_CXFR_DONE) ||
 233				likely(pending & ISI_SR_PXFR_DONE))
 234			ret = atmel_isi_handle_streaming(isi);
 235	}
 236
 237	spin_unlock(&isi->irqlock);
 238	return ret;
 239}
 240
 241#define	WAIT_ISI_RESET		1
 242#define	WAIT_ISI_DISABLE	0
 243static int atmel_isi_wait_status(struct atmel_isi *isi, int wait_reset)
 244{
 245	unsigned long time_left;
 246	/*
 247	 * The reset or disable will only succeed if we have a
 248	 * pixel clock from the camera.
 249	 */
 250	init_completion(&isi->complete);
 251
 252	if (wait_reset) {
 253		isi_writel(isi, ISI_INTEN, ISI_CTRL_SRST);
 254		isi_writel(isi, ISI_CTRL, ISI_CTRL_SRST);
 255	} else {
 256		isi_writel(isi, ISI_INTEN, ISI_CTRL_DIS);
 257		isi_writel(isi, ISI_CTRL, ISI_CTRL_DIS);
 258	}
 259
 260	time_left = wait_for_completion_timeout(&isi->complete,
 261						msecs_to_jiffies(500));
 262	if (time_left == 0)
 263		return -ETIMEDOUT;
 264
 265	return 0;
 266}
 267
 268/* ------------------------------------------------------------------
 269	Videobuf operations
 270   ------------------------------------------------------------------*/
 271static int queue_setup(struct vb2_queue *vq,
 272				unsigned int *nbuffers, unsigned int *nplanes,
 273				unsigned int sizes[], struct device *alloc_devs[])
 274{
 275	struct atmel_isi *isi = vb2_get_drv_priv(vq);
 276	unsigned long size;
 277
 278	size = isi->fmt.fmt.pix.sizeimage;
 279
 280	/* Make sure the image size is large enough. */
 281	if (*nplanes)
 282		return sizes[0] < size ? -EINVAL : 0;
 283
 284	*nplanes = 1;
 285	sizes[0] = size;
 286
 287	isi->active = NULL;
 288
 289	dev_dbg(isi->dev, "%s, count=%d, size=%ld\n", __func__,
 290		*nbuffers, size);
 291
 292	return 0;
 293}
 294
 295static int buffer_init(struct vb2_buffer *vb)
 296{
 297	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 298	struct frame_buffer *buf = container_of(vbuf, struct frame_buffer, vb);
 299
 300	buf->p_dma_desc = NULL;
 301	INIT_LIST_HEAD(&buf->list);
 302
 303	return 0;
 304}
 305
 306static int buffer_prepare(struct vb2_buffer *vb)
 307{
 308	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 309	struct frame_buffer *buf = container_of(vbuf, struct frame_buffer, vb);
 310	struct atmel_isi *isi = vb2_get_drv_priv(vb->vb2_queue);
 311	unsigned long size;
 312	struct isi_dma_desc *desc;
 313
 314	size = isi->fmt.fmt.pix.sizeimage;
 315
 316	if (vb2_plane_size(vb, 0) < size) {
 317		dev_err(isi->dev, "%s data will not fit into plane (%lu < %lu)\n",
 318				__func__, vb2_plane_size(vb, 0), size);
 319		return -EINVAL;
 320	}
 321
 322	vb2_set_plane_payload(vb, 0, size);
 323
 324	if (!buf->p_dma_desc) {
 325		if (list_empty(&isi->dma_desc_head)) {
 326			dev_err(isi->dev, "Not enough dma descriptors.\n");
 327			return -EINVAL;
 328		} else {
 329			/* Get an available descriptor */
 330			desc = list_entry(isi->dma_desc_head.next,
 331						struct isi_dma_desc, list);
 332			/* Delete the descriptor since now it is used */
 333			list_del_init(&desc->list);
 334
 335			/* Initialize the dma descriptor */
 336			desc->p_fbd->fb_address =
 337					vb2_dma_contig_plane_dma_addr(vb, 0);
 338			desc->p_fbd->next_fbd_address = 0;
 339			set_dma_ctrl(desc->p_fbd, ISI_DMA_CTRL_WB);
 340
 341			buf->p_dma_desc = desc;
 342		}
 343	}
 344	return 0;
 345}
 346
 347static void buffer_cleanup(struct vb2_buffer *vb)
 348{
 349	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 350	struct atmel_isi *isi = vb2_get_drv_priv(vb->vb2_queue);
 351	struct frame_buffer *buf = container_of(vbuf, struct frame_buffer, vb);
 352
 353	/* This descriptor is available now and we add to head list */
 354	if (buf->p_dma_desc)
 355		list_add(&buf->p_dma_desc->list, &isi->dma_desc_head);
 356}
 357
 358static void start_dma(struct atmel_isi *isi, struct frame_buffer *buffer)
 359{
 360	u32 ctrl, cfg1;
 361
 362	cfg1 = isi_readl(isi, ISI_CFG1);
 363	/* Enable irq: cxfr for the codec path, pxfr for the preview path */
 364	isi_writel(isi, ISI_INTEN,
 365			ISI_SR_CXFR_DONE | ISI_SR_PXFR_DONE);
 366
 367	/* Check if already in a frame */
 368	if (!isi->enable_preview_path) {
 369		if (isi_readl(isi, ISI_STATUS) & ISI_CTRL_CDC) {
 370			dev_err(isi->dev, "Already in frame handling.\n");
 371			return;
 372		}
 373
 374		isi_writel(isi, ISI_DMA_C_DSCR,
 375				(u32)buffer->p_dma_desc->fbd_phys);
 376		isi_writel(isi, ISI_DMA_C_CTRL,
 377				ISI_DMA_CTRL_FETCH | ISI_DMA_CTRL_DONE);
 378		isi_writel(isi, ISI_DMA_CHER, ISI_DMA_CHSR_C_CH);
 379	} else {
 380		isi_writel(isi, ISI_DMA_P_DSCR,
 381				(u32)buffer->p_dma_desc->fbd_phys);
 382		isi_writel(isi, ISI_DMA_P_CTRL,
 383				ISI_DMA_CTRL_FETCH | ISI_DMA_CTRL_DONE);
 384		isi_writel(isi, ISI_DMA_CHER, ISI_DMA_CHSR_P_CH);
 385	}
 386
 387	cfg1 &= ~ISI_CFG1_FRATE_DIV_MASK;
 388	/* Enable linked list */
 389	cfg1 |= isi->pdata.frate | ISI_CFG1_DISCR;
 390
 391	/* Enable ISI */
 392	ctrl = ISI_CTRL_EN;
 393
 394	if (!isi->enable_preview_path)
 395		ctrl |= ISI_CTRL_CDC;
 396
 397	isi_writel(isi, ISI_CTRL, ctrl);
 398	isi_writel(isi, ISI_CFG1, cfg1);
 399}
 400
 401static void buffer_queue(struct vb2_buffer *vb)
 402{
 403	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 404	struct atmel_isi *isi = vb2_get_drv_priv(vb->vb2_queue);
 405	struct frame_buffer *buf = container_of(vbuf, struct frame_buffer, vb);
 406	unsigned long flags = 0;
 407
 408	spin_lock_irqsave(&isi->irqlock, flags);
 409	list_add_tail(&buf->list, &isi->video_buffer_list);
 410
 411	if (!isi->active) {
 412		isi->active = buf;
 413		if (vb2_is_streaming(vb->vb2_queue))
 414			start_dma(isi, buf);
 415	}
 416	spin_unlock_irqrestore(&isi->irqlock, flags);
 417}
 418
 419static int start_streaming(struct vb2_queue *vq, unsigned int count)
 420{
 421	struct atmel_isi *isi = vb2_get_drv_priv(vq);
 422	struct frame_buffer *buf, *node;
 423	int ret;
 424
 425	ret = pm_runtime_resume_and_get(isi->dev);
 426	if (ret < 0)
 427		return ret;
 428
 429	/* Enable stream on the sub device */
 430	ret = v4l2_subdev_call(isi->entity.subdev, video, s_stream, 1);
 431	if (ret && ret != -ENOIOCTLCMD) {
 432		dev_err(isi->dev, "stream on failed in subdev\n");
 433		goto err_start_stream;
 434	}
 435
 436	/* Reset ISI */
 437	ret = atmel_isi_wait_status(isi, WAIT_ISI_RESET);
 438	if (ret < 0) {
 439		dev_err(isi->dev, "Reset ISI timed out\n");
 440		goto err_reset;
 441	}
 442	/* Disable all interrupts */
 443	isi_writel(isi, ISI_INTDIS, (u32)~0UL);
 444
 445	isi->sequence = 0;
 446	configure_geometry(isi);
 447
 448	spin_lock_irq(&isi->irqlock);
 449	/* Clear any pending interrupt */
 450	isi_readl(isi, ISI_STATUS);
 451
 452	start_dma(isi, isi->active);
 453	spin_unlock_irq(&isi->irqlock);
 454
 455	return 0;
 456
 457err_reset:
 458	v4l2_subdev_call(isi->entity.subdev, video, s_stream, 0);
 459
 460err_start_stream:
 461	pm_runtime_put(isi->dev);
 462
 463	spin_lock_irq(&isi->irqlock);
 464	isi->active = NULL;
 465	/* Release all active buffers */
 466	list_for_each_entry_safe(buf, node, &isi->video_buffer_list, list) {
 467		list_del_init(&buf->list);
 468		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED);
 469	}
 470	spin_unlock_irq(&isi->irqlock);
 471
 472	return ret;
 473}
 474
 475/* abort streaming and wait for last buffer */
 476static void stop_streaming(struct vb2_queue *vq)
 477{
 478	struct atmel_isi *isi = vb2_get_drv_priv(vq);
 479	struct frame_buffer *buf, *node;
 480	int ret = 0;
 481	unsigned long timeout;
 482
 483	/* Disable stream on the sub device */
 484	ret = v4l2_subdev_call(isi->entity.subdev, video, s_stream, 0);
 485	if (ret && ret != -ENOIOCTLCMD)
 486		dev_err(isi->dev, "stream off failed in subdev\n");
 487
 488	spin_lock_irq(&isi->irqlock);
 489	isi->active = NULL;
 490	/* Release all active buffers */
 491	list_for_each_entry_safe(buf, node, &isi->video_buffer_list, list) {
 492		list_del_init(&buf->list);
 493		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 494	}
 495	spin_unlock_irq(&isi->irqlock);
 496
 497	if (!isi->enable_preview_path) {
 498		timeout = jiffies + (FRAME_INTERVAL_MILLI_SEC * HZ) / 1000;
 499		/* Wait until the end of the current frame. */
 500		while ((isi_readl(isi, ISI_STATUS) & ISI_CTRL_CDC) &&
 501				time_before(jiffies, timeout))
 502			msleep(1);
 503
 504		if (time_after(jiffies, timeout))
 505			dev_err(isi->dev,
 506				"Timeout waiting for finishing codec request\n");
 507	}
 508
 509	/* Disable interrupts */
 510	isi_writel(isi, ISI_INTDIS,
 511			ISI_SR_CXFR_DONE | ISI_SR_PXFR_DONE);
 512
 513	/* Disable ISI and wait for it is done */
 514	ret = atmel_isi_wait_status(isi, WAIT_ISI_DISABLE);
 515	if (ret < 0)
 516		dev_err(isi->dev, "Disable ISI timed out\n");
 517
 518	pm_runtime_put(isi->dev);
 519}
 520
 521static const struct vb2_ops isi_video_qops = {
 522	.queue_setup		= queue_setup,
 523	.buf_init		= buffer_init,
 524	.buf_prepare		= buffer_prepare,
 525	.buf_cleanup		= buffer_cleanup,
 526	.buf_queue		= buffer_queue,
 527	.start_streaming	= start_streaming,
 528	.stop_streaming		= stop_streaming,
 529};
 530
 531static int isi_g_fmt_vid_cap(struct file *file, void *priv,
 532			      struct v4l2_format *fmt)
 533{
 534	struct atmel_isi *isi = video_drvdata(file);
 535
 536	*fmt = isi->fmt;
 537
 538	return 0;
 539}
 540
 541static const struct isi_format *find_format_by_fourcc(struct atmel_isi *isi,
 542						      unsigned int fourcc)
 543{
 544	unsigned int num_formats = isi->num_user_formats;
 545	const struct isi_format *fmt;
 546	unsigned int i;
 547
 548	for (i = 0; i < num_formats; i++) {
 549		fmt = isi->user_formats[i];
 550		if (fmt->fourcc == fourcc)
 551			return fmt;
 552	}
 553
 554	return NULL;
 555}
 556
 557static void isi_try_fse(struct atmel_isi *isi, const struct isi_format *isi_fmt,
 558			struct v4l2_subdev_state *sd_state)
 559{
 560	struct v4l2_rect *try_crop =
 561		v4l2_subdev_state_get_crop(sd_state, 0);
 562	struct v4l2_subdev_frame_size_enum fse = {
 563		.code = isi_fmt->mbus_code,
 564		.which = V4L2_SUBDEV_FORMAT_TRY,
 565	};
 566	int ret;
 567
 568	ret = v4l2_subdev_call(isi->entity.subdev, pad, enum_frame_size,
 569			       sd_state, &fse);
 570	/*
 571	 * Attempt to obtain format size from subdev. If not available,
 572	 * just use the maximum ISI can receive.
 573	 */
 574	if (ret) {
 575		try_crop->width = MAX_SUPPORT_WIDTH;
 576		try_crop->height = MAX_SUPPORT_HEIGHT;
 577	} else {
 578		try_crop->width = fse.max_width;
 579		try_crop->height = fse.max_height;
 580	}
 581}
 582
 583static int isi_try_fmt(struct atmel_isi *isi, struct v4l2_format *f,
 584		       const struct isi_format **current_fmt)
 585{
 586	const struct isi_format *isi_fmt;
 587	struct v4l2_pix_format *pixfmt = &f->fmt.pix;
 588	struct v4l2_subdev_pad_config pad_cfg = {};
 589	struct v4l2_subdev_state pad_state = {
 590		.sd = isi->entity.subdev,
 591		.pads = &pad_cfg,
 592	};
 593	struct v4l2_subdev_format format = {
 594		.which = V4L2_SUBDEV_FORMAT_TRY,
 595	};
 596	int ret;
 597
 598	isi_fmt = find_format_by_fourcc(isi, pixfmt->pixelformat);
 599	if (!isi_fmt) {
 600		isi_fmt = isi->user_formats[isi->num_user_formats - 1];
 601		pixfmt->pixelformat = isi_fmt->fourcc;
 602	}
 603
 604	/* Limit to Atmel ISI hardware capabilities */
 605	pixfmt->width = clamp(pixfmt->width, 0U, MAX_SUPPORT_WIDTH);
 606	pixfmt->height = clamp(pixfmt->height, 0U, MAX_SUPPORT_HEIGHT);
 607
 608	v4l2_fill_mbus_format(&format.format, pixfmt, isi_fmt->mbus_code);
 609
 610	isi_try_fse(isi, isi_fmt, &pad_state);
 611
 612	ret = v4l2_subdev_call(isi->entity.subdev, pad, set_fmt,
 613			       &pad_state, &format);
 614	if (ret < 0)
 615		return ret;
 616
 617	v4l2_fill_pix_format(pixfmt, &format.format);
 618
 619	pixfmt->field = V4L2_FIELD_NONE;
 620	pixfmt->bytesperline = pixfmt->width * isi_fmt->bpp;
 621	pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height;
 622
 623	if (current_fmt)
 624		*current_fmt = isi_fmt;
 625
 626	return 0;
 627}
 628
 629static int isi_set_fmt(struct atmel_isi *isi, struct v4l2_format *f)
 630{
 631	struct v4l2_subdev_format format = {
 632		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
 633	};
 634	const struct isi_format *current_fmt;
 635	int ret;
 636
 637	ret = isi_try_fmt(isi, f, &current_fmt);
 638	if (ret)
 639		return ret;
 640
 641	v4l2_fill_mbus_format(&format.format, &f->fmt.pix,
 642			      current_fmt->mbus_code);
 643	ret = v4l2_subdev_call(isi->entity.subdev, pad,
 644			       set_fmt, NULL, &format);
 645	if (ret < 0)
 646		return ret;
 647
 648	isi->fmt = *f;
 649	isi->current_fmt = current_fmt;
 650
 651	return 0;
 652}
 653
 654static int isi_s_fmt_vid_cap(struct file *file, void *priv,
 655			      struct v4l2_format *f)
 656{
 657	struct atmel_isi *isi = video_drvdata(file);
 658
 659	if (vb2_is_streaming(&isi->queue))
 660		return -EBUSY;
 661
 662	return isi_set_fmt(isi, f);
 663}
 664
 665static int isi_try_fmt_vid_cap(struct file *file, void *priv,
 666				struct v4l2_format *f)
 667{
 668	struct atmel_isi *isi = video_drvdata(file);
 669
 670	return isi_try_fmt(isi, f, NULL);
 671}
 672
 673static int isi_enum_fmt_vid_cap(struct file *file, void  *priv,
 674				struct v4l2_fmtdesc *f)
 675{
 676	struct atmel_isi *isi = video_drvdata(file);
 677
 678	if (f->index >= isi->num_user_formats)
 679		return -EINVAL;
 680
 681	f->pixelformat = isi->user_formats[f->index]->fourcc;
 682	return 0;
 683}
 684
 685static int isi_querycap(struct file *file, void *priv,
 686			struct v4l2_capability *cap)
 687{
 688	strscpy(cap->driver, "atmel-isi", sizeof(cap->driver));
 689	strscpy(cap->card, "Atmel Image Sensor Interface", sizeof(cap->card));
 690	strscpy(cap->bus_info, "platform:isi", sizeof(cap->bus_info));
 691	return 0;
 692}
 693
 694static int isi_enum_input(struct file *file, void *priv,
 695			   struct v4l2_input *i)
 696{
 697	if (i->index != 0)
 698		return -EINVAL;
 699
 700	i->type = V4L2_INPUT_TYPE_CAMERA;
 701	strscpy(i->name, "Camera", sizeof(i->name));
 702	return 0;
 703}
 704
 705static int isi_g_input(struct file *file, void *priv, unsigned int *i)
 706{
 707	*i = 0;
 708	return 0;
 709}
 710
 711static int isi_s_input(struct file *file, void *priv, unsigned int i)
 712{
 713	if (i > 0)
 714		return -EINVAL;
 715	return 0;
 716}
 717
 718static int isi_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
 719{
 720	struct atmel_isi *isi = video_drvdata(file);
 721
 722	return v4l2_g_parm_cap(video_devdata(file), isi->entity.subdev, a);
 723}
 724
 725static int isi_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
 726{
 727	struct atmel_isi *isi = video_drvdata(file);
 728
 729	return v4l2_s_parm_cap(video_devdata(file), isi->entity.subdev, a);
 730}
 731
 732static int isi_enum_framesizes(struct file *file, void *fh,
 733			       struct v4l2_frmsizeenum *fsize)
 734{
 735	struct atmel_isi *isi = video_drvdata(file);
 736	const struct isi_format *isi_fmt;
 737	struct v4l2_subdev_frame_size_enum fse = {
 738		.index = fsize->index,
 739		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
 740	};
 741	int ret;
 742
 743	isi_fmt = find_format_by_fourcc(isi, fsize->pixel_format);
 744	if (!isi_fmt)
 745		return -EINVAL;
 746
 747	fse.code = isi_fmt->mbus_code;
 748
 749	ret = v4l2_subdev_call(isi->entity.subdev, pad, enum_frame_size,
 750			       NULL, &fse);
 751	if (ret)
 752		return ret;
 753
 754	fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
 755	fsize->discrete.width = fse.max_width;
 756	fsize->discrete.height = fse.max_height;
 757
 758	return 0;
 759}
 760
 761static int isi_enum_frameintervals(struct file *file, void *fh,
 762				    struct v4l2_frmivalenum *fival)
 763{
 764	struct atmel_isi *isi = video_drvdata(file);
 765	const struct isi_format *isi_fmt;
 766	struct v4l2_subdev_frame_interval_enum fie = {
 767		.index = fival->index,
 768		.width = fival->width,
 769		.height = fival->height,
 770		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
 771	};
 772	int ret;
 773
 774	isi_fmt = find_format_by_fourcc(isi, fival->pixel_format);
 775	if (!isi_fmt)
 776		return -EINVAL;
 777
 778	fie.code = isi_fmt->mbus_code;
 779
 780	ret = v4l2_subdev_call(isi->entity.subdev, pad,
 781			       enum_frame_interval, NULL, &fie);
 782	if (ret)
 783		return ret;
 784
 785	fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
 786	fival->discrete = fie.interval;
 787
 788	return 0;
 789}
 790
 791static int isi_camera_set_bus_param(struct atmel_isi *isi)
 792{
 793	u32 cfg1 = 0;
 794	int ret;
 795
 796	/* set bus param for ISI */
 797	if (isi->pdata.hsync_act_low)
 798		cfg1 |= ISI_CFG1_HSYNC_POL_ACTIVE_LOW;
 799	if (isi->pdata.vsync_act_low)
 800		cfg1 |= ISI_CFG1_VSYNC_POL_ACTIVE_LOW;
 801	if (isi->pdata.pclk_act_falling)
 802		cfg1 |= ISI_CFG1_PIXCLK_POL_ACTIVE_FALLING;
 803	if (isi->pdata.has_emb_sync)
 804		cfg1 |= ISI_CFG1_EMB_SYNC;
 805	if (isi->pdata.full_mode)
 806		cfg1 |= ISI_CFG1_FULL_MODE;
 807
 808	cfg1 |= ISI_CFG1_THMASK_BEATS_16;
 809
 810	/* Enable PM and peripheral clock before operate isi registers */
 811	ret = pm_runtime_resume_and_get(isi->dev);
 812	if (ret < 0)
 813		return ret;
 814
 815	isi_writel(isi, ISI_CTRL, ISI_CTRL_DIS);
 816	isi_writel(isi, ISI_CFG1, cfg1);
 817
 818	pm_runtime_put(isi->dev);
 819
 820	return 0;
 821}
 822
 823/* -----------------------------------------------------------------------*/
 824static int atmel_isi_parse_dt(struct atmel_isi *isi,
 825			struct platform_device *pdev)
 826{
 827	struct device_node *np = pdev->dev.of_node;
 828	struct v4l2_fwnode_endpoint ep = { .bus_type = 0 };
 829	int err;
 830
 831	/* Default settings for ISI */
 832	isi->pdata.full_mode = 1;
 833	isi->pdata.frate = ISI_CFG1_FRATE_CAPTURE_ALL;
 834
 835	np = of_graph_get_endpoint_by_regs(np, 0, -1);
 836	if (!np) {
 837		dev_err(&pdev->dev, "Could not find the endpoint\n");
 838		return -EINVAL;
 839	}
 840
 841	err = v4l2_fwnode_endpoint_parse(of_fwnode_handle(np), &ep);
 842	of_node_put(np);
 843	if (err) {
 844		dev_err(&pdev->dev, "Could not parse the endpoint\n");
 845		return err;
 846	}
 847
 848	switch (ep.bus.parallel.bus_width) {
 849	case 8:
 850		isi->pdata.data_width_flags = ISI_DATAWIDTH_8;
 851		break;
 852	case 10:
 853		isi->pdata.data_width_flags =
 854				ISI_DATAWIDTH_8 | ISI_DATAWIDTH_10;
 855		break;
 856	default:
 857		dev_err(&pdev->dev, "Unsupported bus width: %d\n",
 858				ep.bus.parallel.bus_width);
 859		return -EINVAL;
 860	}
 861
 862	if (ep.bus.parallel.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)
 863		isi->pdata.hsync_act_low = true;
 864	if (ep.bus.parallel.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
 865		isi->pdata.vsync_act_low = true;
 866	if (ep.bus.parallel.flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
 867		isi->pdata.pclk_act_falling = true;
 868
 869	if (ep.bus_type == V4L2_MBUS_BT656)
 870		isi->pdata.has_emb_sync = true;
 871
 872	return 0;
 873}
 874
 875static int isi_open(struct file *file)
 876{
 877	struct atmel_isi *isi = video_drvdata(file);
 878	struct v4l2_subdev *sd = isi->entity.subdev;
 879	int ret;
 880
 881	if (mutex_lock_interruptible(&isi->lock))
 882		return -ERESTARTSYS;
 883
 884	ret = v4l2_fh_open(file);
 885	if (ret < 0)
 886		goto unlock;
 887
 888	if (!v4l2_fh_is_singular_file(file))
 889		goto fh_rel;
 890
 891	ret = v4l2_subdev_call(sd, core, s_power, 1);
 892	if (ret < 0 && ret != -ENOIOCTLCMD)
 893		goto fh_rel;
 894
 895	ret = isi_set_fmt(isi, &isi->fmt);
 896	if (ret)
 897		v4l2_subdev_call(sd, core, s_power, 0);
 898fh_rel:
 899	if (ret)
 900		v4l2_fh_release(file);
 901unlock:
 902	mutex_unlock(&isi->lock);
 903	return ret;
 904}
 905
 906static int isi_release(struct file *file)
 907{
 908	struct atmel_isi *isi = video_drvdata(file);
 909	struct v4l2_subdev *sd = isi->entity.subdev;
 910	bool fh_singular;
 911	int ret;
 912
 913	mutex_lock(&isi->lock);
 914
 915	fh_singular = v4l2_fh_is_singular_file(file);
 916
 917	ret = _vb2_fop_release(file, NULL);
 918
 919	if (fh_singular)
 920		v4l2_subdev_call(sd, core, s_power, 0);
 921
 922	mutex_unlock(&isi->lock);
 923
 924	return ret;
 925}
 926
 927static const struct v4l2_ioctl_ops isi_ioctl_ops = {
 928	.vidioc_querycap		= isi_querycap,
 929
 930	.vidioc_try_fmt_vid_cap		= isi_try_fmt_vid_cap,
 931	.vidioc_g_fmt_vid_cap		= isi_g_fmt_vid_cap,
 932	.vidioc_s_fmt_vid_cap		= isi_s_fmt_vid_cap,
 933	.vidioc_enum_fmt_vid_cap	= isi_enum_fmt_vid_cap,
 934
 935	.vidioc_enum_input		= isi_enum_input,
 936	.vidioc_g_input			= isi_g_input,
 937	.vidioc_s_input			= isi_s_input,
 938
 939	.vidioc_g_parm			= isi_g_parm,
 940	.vidioc_s_parm			= isi_s_parm,
 941	.vidioc_enum_framesizes		= isi_enum_framesizes,
 942	.vidioc_enum_frameintervals	= isi_enum_frameintervals,
 943
 944	.vidioc_reqbufs			= vb2_ioctl_reqbufs,
 945	.vidioc_create_bufs		= vb2_ioctl_create_bufs,
 946	.vidioc_querybuf		= vb2_ioctl_querybuf,
 947	.vidioc_qbuf			= vb2_ioctl_qbuf,
 948	.vidioc_dqbuf			= vb2_ioctl_dqbuf,
 949	.vidioc_expbuf			= vb2_ioctl_expbuf,
 950	.vidioc_prepare_buf		= vb2_ioctl_prepare_buf,
 951	.vidioc_streamon		= vb2_ioctl_streamon,
 952	.vidioc_streamoff		= vb2_ioctl_streamoff,
 953
 954	.vidioc_log_status		= v4l2_ctrl_log_status,
 955	.vidioc_subscribe_event		= v4l2_ctrl_subscribe_event,
 956	.vidioc_unsubscribe_event	= v4l2_event_unsubscribe,
 957};
 958
 959static const struct v4l2_file_operations isi_fops = {
 960	.owner		= THIS_MODULE,
 961	.unlocked_ioctl	= video_ioctl2,
 962	.open		= isi_open,
 963	.release	= isi_release,
 964	.poll		= vb2_fop_poll,
 965	.mmap		= vb2_fop_mmap,
 966	.read		= vb2_fop_read,
 967};
 968
 969static int isi_set_default_fmt(struct atmel_isi *isi)
 970{
 971	struct v4l2_format f = {
 972		.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
 973		.fmt.pix = {
 974			.width		= VGA_WIDTH,
 975			.height		= VGA_HEIGHT,
 976			.field		= V4L2_FIELD_NONE,
 977			.pixelformat	= isi->user_formats[0]->fourcc,
 978		},
 979	};
 980	int ret;
 981
 982	ret = isi_try_fmt(isi, &f, NULL);
 983	if (ret)
 984		return ret;
 985	isi->current_fmt = isi->user_formats[0];
 986	isi->fmt = f;
 987	return 0;
 988}
 989
 990static const struct isi_format isi_formats[] = {
 991	{
 992		.fourcc = V4L2_PIX_FMT_YUYV,
 993		.mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
 994		.bpp = 2,
 995		.swap = ISI_CFG2_YCC_SWAP_DEFAULT,
 996	}, {
 997		.fourcc = V4L2_PIX_FMT_YUYV,
 998		.mbus_code = MEDIA_BUS_FMT_YVYU8_2X8,
 999		.bpp = 2,
1000		.swap = ISI_CFG2_YCC_SWAP_MODE_1,
1001	}, {
1002		.fourcc = V4L2_PIX_FMT_YUYV,
1003		.mbus_code = MEDIA_BUS_FMT_UYVY8_2X8,
1004		.bpp = 2,
1005		.swap = ISI_CFG2_YCC_SWAP_MODE_2,
1006	}, {
1007		.fourcc = V4L2_PIX_FMT_YUYV,
1008		.mbus_code = MEDIA_BUS_FMT_VYUY8_2X8,
1009		.bpp = 2,
1010		.swap = ISI_CFG2_YCC_SWAP_MODE_3,
1011	}, {
1012		.fourcc = V4L2_PIX_FMT_RGB565,
1013		.mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
1014		.bpp = 2,
1015		.swap = ISI_CFG2_YCC_SWAP_MODE_2,
1016	}, {
1017		.fourcc = V4L2_PIX_FMT_RGB565,
1018		.mbus_code = MEDIA_BUS_FMT_YVYU8_2X8,
1019		.bpp = 2,
1020		.swap = ISI_CFG2_YCC_SWAP_MODE_3,
1021	}, {
1022		.fourcc = V4L2_PIX_FMT_RGB565,
1023		.mbus_code = MEDIA_BUS_FMT_UYVY8_2X8,
1024		.bpp = 2,
1025		.swap = ISI_CFG2_YCC_SWAP_DEFAULT,
1026	}, {
1027		.fourcc = V4L2_PIX_FMT_RGB565,
1028		.mbus_code = MEDIA_BUS_FMT_VYUY8_2X8,
1029		.bpp = 2,
1030		.swap = ISI_CFG2_YCC_SWAP_MODE_1,
1031	}, {
1032		.fourcc = V4L2_PIX_FMT_GREY,
1033		.mbus_code = MEDIA_BUS_FMT_Y10_1X10,
1034		.bpp = 1,
1035		.swap = ISI_CFG2_GS_MODE_2_PIXEL | ISI_CFG2_GRAYSCALE,
1036	}, {
1037		.fourcc = V4L2_PIX_FMT_Y16,
1038		.mbus_code = MEDIA_BUS_FMT_Y10_1X10,
1039		.bpp = 2,
1040		.swap = ISI_CFG2_GS_MODE_2_PIXEL | ISI_CFG2_GRAYSCALE,
1041	},
1042};
1043
1044static int isi_formats_init(struct atmel_isi *isi)
1045{
1046	const struct isi_format *isi_fmts[ARRAY_SIZE(isi_formats)];
1047	unsigned int num_fmts = 0, i, j;
1048	struct v4l2_subdev *subdev = isi->entity.subdev;
1049	struct v4l2_subdev_mbus_code_enum mbus_code = {
1050		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
1051	};
1052
1053	while (!v4l2_subdev_call(subdev, pad, enum_mbus_code,
1054				 NULL, &mbus_code)) {
1055		for (i = 0; i < ARRAY_SIZE(isi_formats); i++) {
1056			if (isi_formats[i].mbus_code != mbus_code.code)
1057				continue;
1058
1059			/* Code supported, have we got this fourcc yet? */
1060			for (j = 0; j < num_fmts; j++)
1061				if (isi_fmts[j]->fourcc == isi_formats[i].fourcc)
1062					/* Already available */
1063					break;
1064			if (j == num_fmts)
1065				/* new */
1066				isi_fmts[num_fmts++] = isi_formats + i;
1067		}
1068		mbus_code.index++;
1069	}
1070
1071	if (!num_fmts)
1072		return -ENXIO;
1073
1074	isi->num_user_formats = num_fmts;
1075	isi->user_formats = devm_kmemdup_array(isi->dev, isi_fmts, num_fmts,
1076					       sizeof(*isi_fmts), GFP_KERNEL);
1077	if (!isi->user_formats)
1078		return -ENOMEM;
1079
1080	isi->current_fmt = isi->user_formats[0];
1081	return 0;
1082}
1083
1084static int isi_graph_notify_complete(struct v4l2_async_notifier *notifier)
1085{
1086	struct atmel_isi *isi = notifier_to_isi(notifier);
1087	int ret;
1088
1089	isi->vdev->ctrl_handler = isi->entity.subdev->ctrl_handler;
1090	ret = isi_formats_init(isi);
1091	if (ret) {
1092		dev_err(isi->dev, "No supported mediabus format found\n");
1093		return ret;
1094	}
1095	ret = isi_camera_set_bus_param(isi);
1096	if (ret) {
1097		dev_err(isi->dev, "Can't wake up device\n");
1098		return ret;
1099	}
1100
1101	ret = isi_set_default_fmt(isi);
1102	if (ret) {
1103		dev_err(isi->dev, "Could not set default format\n");
1104		return ret;
1105	}
1106
1107	ret = video_register_device(isi->vdev, VFL_TYPE_VIDEO, -1);
1108	if (ret) {
1109		dev_err(isi->dev, "Failed to register video device\n");
1110		return ret;
1111	}
1112
1113	dev_dbg(isi->dev, "Device registered as %s\n",
1114		video_device_node_name(isi->vdev));
1115	return 0;
1116}
1117
1118static void isi_graph_notify_unbind(struct v4l2_async_notifier *notifier,
1119				     struct v4l2_subdev *sd,
1120				     struct v4l2_async_connection *asd)
1121{
1122	struct atmel_isi *isi = notifier_to_isi(notifier);
1123
1124	dev_dbg(isi->dev, "Removing %s\n", video_device_node_name(isi->vdev));
1125
1126	/* Checks internally if vdev have been init or not */
1127	video_unregister_device(isi->vdev);
1128}
1129
1130static int isi_graph_notify_bound(struct v4l2_async_notifier *notifier,
1131				   struct v4l2_subdev *subdev,
1132				   struct v4l2_async_connection *asd)
1133{
1134	struct atmel_isi *isi = notifier_to_isi(notifier);
1135
1136	dev_dbg(isi->dev, "subdev %s bound\n", subdev->name);
1137
1138	isi->entity.subdev = subdev;
1139
1140	return 0;
1141}
1142
1143static const struct v4l2_async_notifier_operations isi_graph_notify_ops = {
1144	.bound = isi_graph_notify_bound,
1145	.unbind = isi_graph_notify_unbind,
1146	.complete = isi_graph_notify_complete,
1147};
1148
1149static int isi_graph_init(struct atmel_isi *isi)
1150{
1151	struct v4l2_async_connection *asd;
1152	struct device_node *ep;
1153	int ret;
1154
1155	ep = of_graph_get_endpoint_by_regs(isi->dev->of_node, 0, -1);
1156	if (!ep)
1157		return -EINVAL;
1158
1159	v4l2_async_nf_init(&isi->notifier, &isi->v4l2_dev);
1160
1161	asd = v4l2_async_nf_add_fwnode_remote(&isi->notifier,
1162					      of_fwnode_handle(ep),
1163					      struct v4l2_async_connection);
1164	of_node_put(ep);
1165
1166	if (IS_ERR(asd))
1167		return PTR_ERR(asd);
1168
1169	isi->notifier.ops = &isi_graph_notify_ops;
1170
1171	ret = v4l2_async_nf_register(&isi->notifier);
1172	if (ret < 0) {
1173		dev_err(isi->dev, "Notifier registration failed\n");
1174		v4l2_async_nf_cleanup(&isi->notifier);
1175		return ret;
1176	}
1177
1178	return 0;
1179}
1180
1181
1182static int atmel_isi_probe(struct platform_device *pdev)
1183{
1184	int irq;
1185	struct atmel_isi *isi;
1186	struct vb2_queue *q;
1187	int ret, i;
1188
1189	isi = devm_kzalloc(&pdev->dev, sizeof(struct atmel_isi), GFP_KERNEL);
1190	if (!isi)
1191		return -ENOMEM;
1192
1193	isi->pclk = devm_clk_get(&pdev->dev, "isi_clk");
1194	if (IS_ERR(isi->pclk))
1195		return PTR_ERR(isi->pclk);
1196
1197	ret = atmel_isi_parse_dt(isi, pdev);
1198	if (ret)
1199		return ret;
1200
1201	isi->active = NULL;
1202	isi->dev = &pdev->dev;
1203	mutex_init(&isi->lock);
1204	spin_lock_init(&isi->irqlock);
1205	INIT_LIST_HEAD(&isi->video_buffer_list);
1206	INIT_LIST_HEAD(&isi->dma_desc_head);
1207
1208	q = &isi->queue;
1209
1210	/* Initialize the top-level structure */
1211	ret = v4l2_device_register(&pdev->dev, &isi->v4l2_dev);
1212	if (ret)
1213		return ret;
1214
1215	isi->vdev = video_device_alloc();
1216	if (!isi->vdev) {
1217		ret = -ENOMEM;
1218		goto err_vdev_alloc;
1219	}
1220
1221	/* video node */
1222	isi->vdev->fops = &isi_fops;
1223	isi->vdev->v4l2_dev = &isi->v4l2_dev;
1224	isi->vdev->queue = &isi->queue;
1225	strscpy(isi->vdev->name, KBUILD_MODNAME, sizeof(isi->vdev->name));
1226	isi->vdev->release = video_device_release;
1227	isi->vdev->ioctl_ops = &isi_ioctl_ops;
1228	isi->vdev->lock = &isi->lock;
1229	isi->vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
1230		V4L2_CAP_READWRITE;
1231	video_set_drvdata(isi->vdev, isi);
1232
1233	/* buffer queue */
1234	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1235	q->io_modes = VB2_MMAP | VB2_READ | VB2_DMABUF;
1236	q->lock = &isi->lock;
1237	q->drv_priv = isi;
1238	q->buf_struct_size = sizeof(struct frame_buffer);
1239	q->ops = &isi_video_qops;
1240	q->mem_ops = &vb2_dma_contig_memops;
1241	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
1242	q->min_queued_buffers = 2;
1243	q->dev = &pdev->dev;
1244
1245	ret = vb2_queue_init(q);
1246	if (ret < 0) {
1247		dev_err(&pdev->dev, "failed to initialize VB2 queue\n");
1248		goto err_vb2_queue;
1249	}
1250	isi->p_fb_descriptors = dma_alloc_coherent(&pdev->dev,
1251				sizeof(struct fbd) * VIDEO_MAX_FRAME,
1252				&isi->fb_descriptors_phys,
1253				GFP_KERNEL);
1254	if (!isi->p_fb_descriptors) {
1255		dev_err(&pdev->dev, "Can't allocate descriptors!\n");
1256		ret = -ENOMEM;
1257		goto err_dma_alloc;
1258	}
1259
1260	for (i = 0; i < VIDEO_MAX_FRAME; i++) {
1261		isi->dma_desc[i].p_fbd = isi->p_fb_descriptors + i;
1262		isi->dma_desc[i].fbd_phys = isi->fb_descriptors_phys +
1263					i * sizeof(struct fbd);
1264		list_add(&isi->dma_desc[i].list, &isi->dma_desc_head);
1265	}
1266
1267	isi->regs = devm_platform_ioremap_resource(pdev, 0);
1268	if (IS_ERR(isi->regs)) {
1269		ret = PTR_ERR(isi->regs);
1270		goto err_ioremap;
1271	}
1272
1273	if (isi->pdata.data_width_flags & ISI_DATAWIDTH_8)
1274		isi->width_flags = 1 << 7;
1275	if (isi->pdata.data_width_flags & ISI_DATAWIDTH_10)
1276		isi->width_flags |= 1 << 9;
1277
1278	irq = platform_get_irq(pdev, 0);
1279	if (irq < 0) {
1280		ret = irq;
1281		goto err_req_irq;
1282	}
1283
1284	ret = devm_request_irq(&pdev->dev, irq, isi_interrupt, 0, "isi", isi);
1285	if (ret) {
1286		dev_err(&pdev->dev, "Unable to request irq %d\n", irq);
1287		goto err_req_irq;
1288	}
1289	isi->irq = irq;
1290
1291	ret = isi_graph_init(isi);
1292	if (ret < 0)
1293		goto err_req_irq;
1294
1295	pm_suspend_ignore_children(&pdev->dev, true);
1296	pm_runtime_enable(&pdev->dev);
1297	platform_set_drvdata(pdev, isi);
1298	return 0;
1299
1300err_req_irq:
1301err_ioremap:
1302	dma_free_coherent(&pdev->dev,
1303			sizeof(struct fbd) * VIDEO_MAX_FRAME,
1304			isi->p_fb_descriptors,
1305			isi->fb_descriptors_phys);
1306err_dma_alloc:
1307err_vb2_queue:
1308	video_device_release(isi->vdev);
1309err_vdev_alloc:
1310	v4l2_device_unregister(&isi->v4l2_dev);
1311
1312	return ret;
1313}
1314
1315static void atmel_isi_remove(struct platform_device *pdev)
1316{
1317	struct atmel_isi *isi = platform_get_drvdata(pdev);
1318
1319	dma_free_coherent(&pdev->dev,
1320			sizeof(struct fbd) * VIDEO_MAX_FRAME,
1321			isi->p_fb_descriptors,
1322			isi->fb_descriptors_phys);
1323	pm_runtime_disable(&pdev->dev);
1324	v4l2_async_nf_unregister(&isi->notifier);
1325	v4l2_async_nf_cleanup(&isi->notifier);
1326	v4l2_device_unregister(&isi->v4l2_dev);
1327}
1328
1329#ifdef CONFIG_PM
1330static int atmel_isi_runtime_suspend(struct device *dev)
1331{
1332	struct atmel_isi *isi = dev_get_drvdata(dev);
1333
1334	clk_disable_unprepare(isi->pclk);
1335
1336	return 0;
1337}
1338static int atmel_isi_runtime_resume(struct device *dev)
1339{
1340	struct atmel_isi *isi = dev_get_drvdata(dev);
1341
1342	return clk_prepare_enable(isi->pclk);
1343}
1344#endif /* CONFIG_PM */
1345
1346static const struct dev_pm_ops atmel_isi_dev_pm_ops = {
1347	SET_RUNTIME_PM_OPS(atmel_isi_runtime_suspend,
1348				atmel_isi_runtime_resume, NULL)
1349};
1350
1351static const struct of_device_id atmel_isi_of_match[] = {
1352	{ .compatible = "atmel,at91sam9g45-isi" },
1353	{ }
1354};
1355MODULE_DEVICE_TABLE(of, atmel_isi_of_match);
1356
1357static struct platform_driver atmel_isi_driver = {
1358	.driver		= {
1359		.name = "atmel_isi",
1360		.of_match_table = of_match_ptr(atmel_isi_of_match),
1361		.pm	= &atmel_isi_dev_pm_ops,
1362	},
1363	.probe		= atmel_isi_probe,
1364	.remove		= atmel_isi_remove,
1365};
1366
1367module_platform_driver(atmel_isi_driver);
1368
1369MODULE_AUTHOR("Josh Wu <josh.wu@atmel.com>");
1370MODULE_DESCRIPTION("The V4L2 driver for Atmel Linux");
1371MODULE_LICENSE("GPL");
~/ Read-only file preview.