Linux Audio

Check our new training course

Loading...
   1/*
   2 * Support eMMa-PrP through mem2mem framework.
   3 *
   4 * eMMa-PrP is a piece of HW that allows fetching buffers
   5 * from one memory location and do several operations on
   6 * them such as scaling or format conversion giving, as a result
   7 * a new processed buffer in another memory location.
   8 *
   9 * Based on mem2mem_testdev.c by Pawel Osciak.
  10 *
  11 * Copyright (c) 2011 Vista Silicon S.L.
  12 * Javier Martin <javier.martin@vista-silicon.com>
  13 *
  14 * This program is free software; you can redistribute it and/or modify
  15 * it under the terms of the GNU General Public License as published by the
  16 * Free Software Foundation; either version 2 of the
  17 * License, or (at your option) any later version
  18 */
  19#include <linux/module.h>
  20#include <linux/clk.h>
  21#include <linux/slab.h>
  22#include <linux/interrupt.h>
  23#include <linux/io.h>
  24
  25#include <linux/platform_device.h>
  26#include <media/v4l2-mem2mem.h>
  27#include <media/v4l2-device.h>
  28#include <media/v4l2-ioctl.h>
  29#include <media/videobuf2-dma-contig.h>
  30#include <asm/sizes.h>
  31
  32#define EMMAPRP_MODULE_NAME "mem2mem-emmaprp"
  33
  34MODULE_DESCRIPTION("Mem-to-mem device which supports eMMa-PrP present in mx2 SoCs");
  35MODULE_AUTHOR("Javier Martin <javier.martin@vista-silicon.com");
  36MODULE_LICENSE("GPL");
  37MODULE_VERSION("0.0.1");
  38
  39static bool debug;
  40module_param(debug, bool, 0644);
  41
  42#define MIN_W 32
  43#define MIN_H 32
  44#define MAX_W 2040
  45#define MAX_H 2046
  46
  47#define S_ALIGN		1 /* multiple of 2 */
  48#define W_ALIGN_YUV420	3 /* multiple of 8 */
  49#define W_ALIGN_OTHERS	2 /* multiple of 4 */
  50#define H_ALIGN		1 /* multiple of 2 */
  51
  52/* Flags that indicate a format can be used for capture/output */
  53#define MEM2MEM_CAPTURE	(1 << 0)
  54#define MEM2MEM_OUTPUT	(1 << 1)
  55
  56#define MEM2MEM_NAME		"m2m-emmaprp"
  57
  58/* In bytes, per queue */
  59#define MEM2MEM_VID_MEM_LIMIT	SZ_16M
  60
  61#define dprintk(dev, fmt, arg...) \
  62	v4l2_dbg(1, debug, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg)
  63
  64/* EMMA PrP */
  65#define PRP_CNTL                        0x00
  66#define PRP_INTR_CNTL                   0x04
  67#define PRP_INTRSTATUS                  0x08
  68#define PRP_SOURCE_Y_PTR                0x0c
  69#define PRP_SOURCE_CB_PTR               0x10
  70#define PRP_SOURCE_CR_PTR               0x14
  71#define PRP_DEST_RGB1_PTR               0x18
  72#define PRP_DEST_RGB2_PTR               0x1c
  73#define PRP_DEST_Y_PTR                  0x20
  74#define PRP_DEST_CB_PTR                 0x24
  75#define PRP_DEST_CR_PTR                 0x28
  76#define PRP_SRC_FRAME_SIZE              0x2c
  77#define PRP_DEST_CH1_LINE_STRIDE        0x30
  78#define PRP_SRC_PIXEL_FORMAT_CNTL       0x34
  79#define PRP_CH1_PIXEL_FORMAT_CNTL       0x38
  80#define PRP_CH1_OUT_IMAGE_SIZE          0x3c
  81#define PRP_CH2_OUT_IMAGE_SIZE          0x40
  82#define PRP_SRC_LINE_STRIDE             0x44
  83#define PRP_CSC_COEF_012                0x48
  84#define PRP_CSC_COEF_345                0x4c
  85#define PRP_CSC_COEF_678                0x50
  86#define PRP_CH1_RZ_HORI_COEF1           0x54
  87#define PRP_CH1_RZ_HORI_COEF2           0x58
  88#define PRP_CH1_RZ_HORI_VALID           0x5c
  89#define PRP_CH1_RZ_VERT_COEF1           0x60
  90#define PRP_CH1_RZ_VERT_COEF2           0x64
  91#define PRP_CH1_RZ_VERT_VALID           0x68
  92#define PRP_CH2_RZ_HORI_COEF1           0x6c
  93#define PRP_CH2_RZ_HORI_COEF2           0x70
  94#define PRP_CH2_RZ_HORI_VALID           0x74
  95#define PRP_CH2_RZ_VERT_COEF1           0x78
  96#define PRP_CH2_RZ_VERT_COEF2           0x7c
  97#define PRP_CH2_RZ_VERT_VALID           0x80
  98
  99#define PRP_CNTL_CH1EN          (1 << 0)
 100#define PRP_CNTL_CH2EN          (1 << 1)
 101#define PRP_CNTL_CSIEN          (1 << 2)
 102#define PRP_CNTL_DATA_IN_YUV420 (0 << 3)
 103#define PRP_CNTL_DATA_IN_YUV422 (1 << 3)
 104#define PRP_CNTL_DATA_IN_RGB16  (2 << 3)
 105#define PRP_CNTL_DATA_IN_RGB32  (3 << 3)
 106#define PRP_CNTL_CH1_OUT_RGB8   (0 << 5)
 107#define PRP_CNTL_CH1_OUT_RGB16  (1 << 5)
 108#define PRP_CNTL_CH1_OUT_RGB32  (2 << 5)
 109#define PRP_CNTL_CH1_OUT_YUV422 (3 << 5)
 110#define PRP_CNTL_CH2_OUT_YUV420 (0 << 7)
 111#define PRP_CNTL_CH2_OUT_YUV422 (1 << 7)
 112#define PRP_CNTL_CH2_OUT_YUV444 (2 << 7)
 113#define PRP_CNTL_CH1_LEN        (1 << 9)
 114#define PRP_CNTL_CH2_LEN        (1 << 10)
 115#define PRP_CNTL_SKIP_FRAME     (1 << 11)
 116#define PRP_CNTL_SWRST          (1 << 12)
 117#define PRP_CNTL_CLKEN          (1 << 13)
 118#define PRP_CNTL_WEN            (1 << 14)
 119#define PRP_CNTL_CH1BYP         (1 << 15)
 120#define PRP_CNTL_IN_TSKIP(x)    ((x) << 16)
 121#define PRP_CNTL_CH1_TSKIP(x)   ((x) << 19)
 122#define PRP_CNTL_CH2_TSKIP(x)   ((x) << 22)
 123#define PRP_CNTL_INPUT_FIFO_LEVEL(x)    ((x) << 25)
 124#define PRP_CNTL_RZ_FIFO_LEVEL(x)       ((x) << 27)
 125#define PRP_CNTL_CH2B1EN        (1 << 29)
 126#define PRP_CNTL_CH2B2EN        (1 << 30)
 127#define PRP_CNTL_CH2FEN         (1 << 31)
 128
 129#define PRP_SIZE_HEIGHT(x)	(x)
 130#define PRP_SIZE_WIDTH(x)	((x) << 16)
 131
 132/* IRQ Enable and status register */
 133#define PRP_INTR_RDERR          (1 << 0)
 134#define PRP_INTR_CH1WERR        (1 << 1)
 135#define PRP_INTR_CH2WERR        (1 << 2)
 136#define PRP_INTR_CH1FC          (1 << 3)
 137#define PRP_INTR_CH2FC          (1 << 5)
 138#define PRP_INTR_LBOVF          (1 << 7)
 139#define PRP_INTR_CH2OVF         (1 << 8)
 140
 141#define PRP_INTR_ST_RDERR	(1 << 0)
 142#define PRP_INTR_ST_CH1WERR	(1 << 1)
 143#define PRP_INTR_ST_CH2WERR	(1 << 2)
 144#define PRP_INTR_ST_CH2B2CI	(1 << 3)
 145#define PRP_INTR_ST_CH2B1CI	(1 << 4)
 146#define PRP_INTR_ST_CH1B2CI	(1 << 5)
 147#define PRP_INTR_ST_CH1B1CI	(1 << 6)
 148#define PRP_INTR_ST_LBOVF	(1 << 7)
 149#define PRP_INTR_ST_CH2OVF	(1 << 8)
 150
 151struct emmaprp_fmt {
 152	char	*name;
 153	u32	fourcc;
 154	/* Types the format can be used for */
 155	u32	types;
 156};
 157
 158static struct emmaprp_fmt formats[] = {
 159	{
 160		.name	= "YUV 4:2:0 Planar",
 161		.fourcc	= V4L2_PIX_FMT_YUV420,
 162		.types	= MEM2MEM_CAPTURE,
 163	},
 164	{
 165		.name	= "4:2:2, packed, YUYV",
 166		.fourcc	= V4L2_PIX_FMT_YUYV,
 167		.types	= MEM2MEM_OUTPUT,
 168	},
 169};
 170
 171/* Per-queue, driver-specific private data */
 172struct emmaprp_q_data {
 173	unsigned int		width;
 174	unsigned int		height;
 175	unsigned int		sizeimage;
 176	struct emmaprp_fmt	*fmt;
 177};
 178
 179enum {
 180	V4L2_M2M_SRC = 0,
 181	V4L2_M2M_DST = 1,
 182};
 183
 184#define NUM_FORMATS ARRAY_SIZE(formats)
 185
 186static struct emmaprp_fmt *find_format(struct v4l2_format *f)
 187{
 188	struct emmaprp_fmt *fmt;
 189	unsigned int k;
 190
 191	for (k = 0; k < NUM_FORMATS; k++) {
 192		fmt = &formats[k];
 193		if (fmt->fourcc == f->fmt.pix.pixelformat)
 194			break;
 195	}
 196
 197	if (k == NUM_FORMATS)
 198		return NULL;
 199
 200	return &formats[k];
 201}
 202
 203struct emmaprp_dev {
 204	struct v4l2_device	v4l2_dev;
 205	struct video_device	*vfd;
 206
 207	struct mutex		dev_mutex;
 208	spinlock_t		irqlock;
 209
 210	int			irq_emma;
 211	void __iomem		*base_emma;
 212	struct clk		*clk_emma;
 213	struct resource		*res_emma;
 214
 215	struct v4l2_m2m_dev	*m2m_dev;
 216	struct vb2_alloc_ctx	*alloc_ctx;
 217};
 218
 219struct emmaprp_ctx {
 220	struct emmaprp_dev	*dev;
 221	/* Abort requested by m2m */
 222	int			aborting;
 223	struct emmaprp_q_data	q_data[2];
 224	struct v4l2_m2m_ctx	*m2m_ctx;
 225};
 226
 227static struct emmaprp_q_data *get_q_data(struct emmaprp_ctx *ctx,
 228					 enum v4l2_buf_type type)
 229{
 230	switch (type) {
 231	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
 232		return &(ctx->q_data[V4L2_M2M_SRC]);
 233	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
 234		return &(ctx->q_data[V4L2_M2M_DST]);
 235	default:
 236		BUG();
 237	}
 238	return NULL;
 239}
 240
 241/*
 242 * mem2mem callbacks
 243 */
 244static void emmaprp_job_abort(void *priv)
 245{
 246	struct emmaprp_ctx *ctx = priv;
 247	struct emmaprp_dev *pcdev = ctx->dev;
 248
 249	ctx->aborting = 1;
 250
 251	dprintk(pcdev, "Aborting task\n");
 252
 253	v4l2_m2m_job_finish(pcdev->m2m_dev, ctx->m2m_ctx);
 254}
 255
 256static void emmaprp_lock(void *priv)
 257{
 258	struct emmaprp_ctx *ctx = priv;
 259	struct emmaprp_dev *pcdev = ctx->dev;
 260	mutex_lock(&pcdev->dev_mutex);
 261}
 262
 263static void emmaprp_unlock(void *priv)
 264{
 265	struct emmaprp_ctx *ctx = priv;
 266	struct emmaprp_dev *pcdev = ctx->dev;
 267	mutex_unlock(&pcdev->dev_mutex);
 268}
 269
 270static inline void emmaprp_dump_regs(struct emmaprp_dev *pcdev)
 271{
 272	dprintk(pcdev,
 273		"eMMa-PrP Registers:\n"
 274		"  SOURCE_Y_PTR = 0x%08X\n"
 275		"  SRC_FRAME_SIZE = 0x%08X\n"
 276		"  DEST_Y_PTR = 0x%08X\n"
 277		"  DEST_CR_PTR = 0x%08X\n"
 278		"  DEST_CB_PTR = 0x%08X\n"
 279		"  CH2_OUT_IMAGE_SIZE = 0x%08X\n"
 280		"  CNTL = 0x%08X\n",
 281		readl(pcdev->base_emma + PRP_SOURCE_Y_PTR),
 282		readl(pcdev->base_emma + PRP_SRC_FRAME_SIZE),
 283		readl(pcdev->base_emma + PRP_DEST_Y_PTR),
 284		readl(pcdev->base_emma + PRP_DEST_CR_PTR),
 285		readl(pcdev->base_emma + PRP_DEST_CB_PTR),
 286		readl(pcdev->base_emma + PRP_CH2_OUT_IMAGE_SIZE),
 287		readl(pcdev->base_emma + PRP_CNTL));
 288}
 289
 290static void emmaprp_device_run(void *priv)
 291{
 292	struct emmaprp_ctx *ctx = priv;
 293	struct emmaprp_q_data *s_q_data, *d_q_data;
 294	struct vb2_buffer *src_buf, *dst_buf;
 295	struct emmaprp_dev *pcdev = ctx->dev;
 296	unsigned int s_width, s_height;
 297	unsigned int d_width, d_height;
 298	unsigned int d_size;
 299	dma_addr_t p_in, p_out;
 300	u32 tmp;
 301
 302	src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
 303	dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
 304
 305	s_q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
 306	s_width	= s_q_data->width;
 307	s_height = s_q_data->height;
 308
 309	d_q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
 310	d_width = d_q_data->width;
 311	d_height = d_q_data->height;
 312	d_size = d_width * d_height;
 313
 314	p_in = vb2_dma_contig_plane_dma_addr(src_buf, 0);
 315	p_out = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
 316	if (!p_in || !p_out) {
 317		v4l2_err(&pcdev->v4l2_dev,
 318			 "Acquiring kernel pointers to buffers failed\n");
 319		return;
 320	}
 321
 322	/* Input frame parameters */
 323	writel(p_in, pcdev->base_emma + PRP_SOURCE_Y_PTR);
 324	writel(PRP_SIZE_WIDTH(s_width) | PRP_SIZE_HEIGHT(s_height),
 325	       pcdev->base_emma + PRP_SRC_FRAME_SIZE);
 326
 327	/* Output frame parameters */
 328	writel(p_out, pcdev->base_emma + PRP_DEST_Y_PTR);
 329	writel(p_out + d_size, pcdev->base_emma + PRP_DEST_CB_PTR);
 330	writel(p_out + d_size + (d_size >> 2),
 331	       pcdev->base_emma + PRP_DEST_CR_PTR);
 332	writel(PRP_SIZE_WIDTH(d_width) | PRP_SIZE_HEIGHT(d_height),
 333	       pcdev->base_emma + PRP_CH2_OUT_IMAGE_SIZE);
 334
 335	/* IRQ configuration */
 336	tmp = readl(pcdev->base_emma + PRP_INTR_CNTL);
 337	writel(tmp | PRP_INTR_RDERR |
 338		PRP_INTR_CH2WERR |
 339		PRP_INTR_CH2FC,
 340		pcdev->base_emma + PRP_INTR_CNTL);
 341
 342	emmaprp_dump_regs(pcdev);
 343
 344	/* Enable transfer */
 345	tmp = readl(pcdev->base_emma + PRP_CNTL);
 346	writel(tmp | PRP_CNTL_CH2_OUT_YUV420 |
 347		PRP_CNTL_DATA_IN_YUV422 |
 348		PRP_CNTL_CH2EN,
 349		pcdev->base_emma + PRP_CNTL);
 350}
 351
 352static irqreturn_t emmaprp_irq(int irq_emma, void *data)
 353{
 354	struct emmaprp_dev *pcdev = data;
 355	struct emmaprp_ctx *curr_ctx;
 356	struct vb2_buffer *src_vb, *dst_vb;
 357	unsigned long flags;
 358	u32 irqst;
 359
 360	/* Check irq flags and clear irq */
 361	irqst = readl(pcdev->base_emma + PRP_INTRSTATUS);
 362	writel(irqst, pcdev->base_emma + PRP_INTRSTATUS);
 363	dprintk(pcdev, "irqst = 0x%08x\n", irqst);
 364
 365	curr_ctx = v4l2_m2m_get_curr_priv(pcdev->m2m_dev);
 366	if (curr_ctx == NULL) {
 367		pr_err("Instance released before the end of transaction\n");
 368		return IRQ_HANDLED;
 369	}
 370
 371	if (!curr_ctx->aborting) {
 372		if ((irqst & PRP_INTR_ST_RDERR) ||
 373		(irqst & PRP_INTR_ST_CH2WERR)) {
 374			pr_err("PrP bus error ocurred, this transfer is probably corrupted\n");
 375			writel(PRP_CNTL_SWRST, pcdev->base_emma + PRP_CNTL);
 376		} else if (irqst & PRP_INTR_ST_CH2B1CI) { /* buffer ready */
 377			src_vb = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx);
 378			dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->m2m_ctx);
 379
 380			spin_lock_irqsave(&pcdev->irqlock, flags);
 381			v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE);
 382			v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE);
 383			spin_unlock_irqrestore(&pcdev->irqlock, flags);
 384		}
 385	}
 386
 387	v4l2_m2m_job_finish(pcdev->m2m_dev, curr_ctx->m2m_ctx);
 388	return IRQ_HANDLED;
 389}
 390
 391/*
 392 * video ioctls
 393 */
 394static int vidioc_querycap(struct file *file, void *priv,
 395			   struct v4l2_capability *cap)
 396{
 397	strncpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver) - 1);
 398	strncpy(cap->card, MEM2MEM_NAME, sizeof(cap->card) - 1);
 399	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT
 400			  | V4L2_CAP_STREAMING;
 401
 402	return 0;
 403}
 404
 405static int enum_fmt(struct v4l2_fmtdesc *f, u32 type)
 406{
 407	int i, num;
 408	struct emmaprp_fmt *fmt;
 409
 410	num = 0;
 411
 412	for (i = 0; i < NUM_FORMATS; ++i) {
 413		if (formats[i].types & type) {
 414			/* index-th format of type type found ? */
 415			if (num == f->index)
 416				break;
 417			/* Correct type but haven't reached our index yet,
 418			 * just increment per-type index */
 419			++num;
 420		}
 421	}
 422
 423	if (i < NUM_FORMATS) {
 424		/* Format found */
 425		fmt = &formats[i];
 426		strlcpy(f->description, fmt->name, sizeof(f->description) - 1);
 427		f->pixelformat = fmt->fourcc;
 428		return 0;
 429	}
 430
 431	/* Format not found */
 432	return -EINVAL;
 433}
 434
 435static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
 436				   struct v4l2_fmtdesc *f)
 437{
 438	return enum_fmt(f, MEM2MEM_CAPTURE);
 439}
 440
 441static int vidioc_enum_fmt_vid_out(struct file *file, void *priv,
 442				   struct v4l2_fmtdesc *f)
 443{
 444	return enum_fmt(f, MEM2MEM_OUTPUT);
 445}
 446
 447static int vidioc_g_fmt(struct emmaprp_ctx *ctx, struct v4l2_format *f)
 448{
 449	struct vb2_queue *vq;
 450	struct emmaprp_q_data *q_data;
 451
 452	vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
 453	if (!vq)
 454		return -EINVAL;
 455
 456	q_data = get_q_data(ctx, f->type);
 457
 458	f->fmt.pix.width	= q_data->width;
 459	f->fmt.pix.height	= q_data->height;
 460	f->fmt.pix.field	= V4L2_FIELD_NONE;
 461	f->fmt.pix.pixelformat	= q_data->fmt->fourcc;
 462	if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420)
 463		f->fmt.pix.bytesperline = q_data->width * 3 / 2;
 464	else /* YUYV */
 465		f->fmt.pix.bytesperline = q_data->width * 2;
 466	f->fmt.pix.sizeimage	= q_data->sizeimage;
 467
 468	return 0;
 469}
 470
 471static int vidioc_g_fmt_vid_out(struct file *file, void *priv,
 472				struct v4l2_format *f)
 473{
 474	return vidioc_g_fmt(priv, f);
 475}
 476
 477static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
 478				struct v4l2_format *f)
 479{
 480	return vidioc_g_fmt(priv, f);
 481}
 482
 483static int vidioc_try_fmt(struct v4l2_format *f)
 484{
 485	enum v4l2_field field;
 486
 487
 488	if (!find_format(f))
 489		return -EINVAL;
 490
 491	field = f->fmt.pix.field;
 492	if (field == V4L2_FIELD_ANY)
 493		field = V4L2_FIELD_NONE;
 494	else if (V4L2_FIELD_NONE != field)
 495		return -EINVAL;
 496
 497	/* V4L2 specification suggests the driver corrects the format struct
 498	 * if any of the dimensions is unsupported */
 499	f->fmt.pix.field = field;
 500
 501	if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420) {
 502		v4l_bound_align_image(&f->fmt.pix.width, MIN_W, MAX_W,
 503				      W_ALIGN_YUV420, &f->fmt.pix.height,
 504				      MIN_H, MAX_H, H_ALIGN, S_ALIGN);
 505		f->fmt.pix.bytesperline = f->fmt.pix.width * 3 / 2;
 506	} else {
 507		v4l_bound_align_image(&f->fmt.pix.width, MIN_W, MAX_W,
 508				      W_ALIGN_OTHERS, &f->fmt.pix.height,
 509				      MIN_H, MAX_H, H_ALIGN, S_ALIGN);
 510		f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
 511	}
 512	f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
 513
 514	return 0;
 515}
 516
 517static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
 518				  struct v4l2_format *f)
 519{
 520	struct emmaprp_fmt *fmt;
 521	struct emmaprp_ctx *ctx = priv;
 522
 523	fmt = find_format(f);
 524	if (!fmt || !(fmt->types & MEM2MEM_CAPTURE)) {
 525		v4l2_err(&ctx->dev->v4l2_dev,
 526			 "Fourcc format (0x%08x) invalid.\n",
 527			 f->fmt.pix.pixelformat);
 528		return -EINVAL;
 529	}
 530
 531	return vidioc_try_fmt(f);
 532}
 533
 534static int vidioc_try_fmt_vid_out(struct file *file, void *priv,
 535				  struct v4l2_format *f)
 536{
 537	struct emmaprp_fmt *fmt;
 538	struct emmaprp_ctx *ctx = priv;
 539
 540	fmt = find_format(f);
 541	if (!fmt || !(fmt->types & MEM2MEM_OUTPUT)) {
 542		v4l2_err(&ctx->dev->v4l2_dev,
 543			 "Fourcc format (0x%08x) invalid.\n",
 544			 f->fmt.pix.pixelformat);
 545		return -EINVAL;
 546	}
 547
 548	return vidioc_try_fmt(f);
 549}
 550
 551static int vidioc_s_fmt(struct emmaprp_ctx *ctx, struct v4l2_format *f)
 552{
 553	struct emmaprp_q_data *q_data;
 554	struct vb2_queue *vq;
 555	int ret;
 556
 557	vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
 558	if (!vq)
 559		return -EINVAL;
 560
 561	q_data = get_q_data(ctx, f->type);
 562	if (!q_data)
 563		return -EINVAL;
 564
 565	if (vb2_is_busy(vq)) {
 566		v4l2_err(&ctx->dev->v4l2_dev, "%s queue busy\n", __func__);
 567		return -EBUSY;
 568	}
 569
 570	ret = vidioc_try_fmt(f);
 571	if (ret)
 572		return ret;
 573
 574	q_data->fmt		= find_format(f);
 575	q_data->width		= f->fmt.pix.width;
 576	q_data->height		= f->fmt.pix.height;
 577	if (q_data->fmt->fourcc == V4L2_PIX_FMT_YUV420)
 578		q_data->sizeimage = q_data->width * q_data->height * 3 / 2;
 579	else /* YUYV */
 580		q_data->sizeimage = q_data->width * q_data->height * 2;
 581
 582	dprintk(ctx->dev,
 583		"Setting format for type %d, wxh: %dx%d, fmt: %d\n",
 584		f->type, q_data->width, q_data->height, q_data->fmt->fourcc);
 585
 586	return 0;
 587}
 588
 589static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
 590				struct v4l2_format *f)
 591{
 592	int ret;
 593
 594	ret = vidioc_try_fmt_vid_cap(file, priv, f);
 595	if (ret)
 596		return ret;
 597
 598	return vidioc_s_fmt(priv, f);
 599}
 600
 601static int vidioc_s_fmt_vid_out(struct file *file, void *priv,
 602				struct v4l2_format *f)
 603{
 604	int ret;
 605
 606	ret = vidioc_try_fmt_vid_out(file, priv, f);
 607	if (ret)
 608		return ret;
 609
 610	return vidioc_s_fmt(priv, f);
 611}
 612
 613static int vidioc_reqbufs(struct file *file, void *priv,
 614			  struct v4l2_requestbuffers *reqbufs)
 615{
 616	struct emmaprp_ctx *ctx = priv;
 617
 618	return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs);
 619}
 620
 621static int vidioc_querybuf(struct file *file, void *priv,
 622			   struct v4l2_buffer *buf)
 623{
 624	struct emmaprp_ctx *ctx = priv;
 625
 626	return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf);
 627}
 628
 629static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
 630{
 631	struct emmaprp_ctx *ctx = priv;
 632
 633	return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf);
 634}
 635
 636static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
 637{
 638	struct emmaprp_ctx *ctx = priv;
 639
 640	return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
 641}
 642
 643static int vidioc_streamon(struct file *file, void *priv,
 644			   enum v4l2_buf_type type)
 645{
 646	struct emmaprp_ctx *ctx = priv;
 647
 648	return v4l2_m2m_streamon(file, ctx->m2m_ctx, type);
 649}
 650
 651static int vidioc_streamoff(struct file *file, void *priv,
 652			    enum v4l2_buf_type type)
 653{
 654	struct emmaprp_ctx *ctx = priv;
 655
 656	return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type);
 657}
 658
 659static const struct v4l2_ioctl_ops emmaprp_ioctl_ops = {
 660	.vidioc_querycap	= vidioc_querycap,
 661
 662	.vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
 663	.vidioc_g_fmt_vid_cap	= vidioc_g_fmt_vid_cap,
 664	.vidioc_try_fmt_vid_cap	= vidioc_try_fmt_vid_cap,
 665	.vidioc_s_fmt_vid_cap	= vidioc_s_fmt_vid_cap,
 666
 667	.vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out,
 668	.vidioc_g_fmt_vid_out	= vidioc_g_fmt_vid_out,
 669	.vidioc_try_fmt_vid_out	= vidioc_try_fmt_vid_out,
 670	.vidioc_s_fmt_vid_out	= vidioc_s_fmt_vid_out,
 671
 672	.vidioc_reqbufs		= vidioc_reqbufs,
 673	.vidioc_querybuf	= vidioc_querybuf,
 674
 675	.vidioc_qbuf		= vidioc_qbuf,
 676	.vidioc_dqbuf		= vidioc_dqbuf,
 677
 678	.vidioc_streamon	= vidioc_streamon,
 679	.vidioc_streamoff	= vidioc_streamoff,
 680};
 681
 682
 683/*
 684 * Queue operations
 685 */
 686static int emmaprp_queue_setup(struct vb2_queue *vq,
 687				const struct v4l2_format *fmt,
 688				unsigned int *nbuffers, unsigned int *nplanes,
 689				unsigned int sizes[], void *alloc_ctxs[])
 690{
 691	struct emmaprp_ctx *ctx = vb2_get_drv_priv(vq);
 692	struct emmaprp_q_data *q_data;
 693	unsigned int size, count = *nbuffers;
 694
 695	q_data = get_q_data(ctx, vq->type);
 696
 697	if (q_data->fmt->fourcc == V4L2_PIX_FMT_YUV420)
 698		size = q_data->width * q_data->height * 3 / 2;
 699	else
 700		size = q_data->width * q_data->height * 2;
 701
 702	while (size * count > MEM2MEM_VID_MEM_LIMIT)
 703		(count)--;
 704
 705	*nplanes = 1;
 706	*nbuffers = count;
 707	sizes[0] = size;
 708
 709	alloc_ctxs[0] = ctx->dev->alloc_ctx;
 710
 711	dprintk(ctx->dev, "get %d buffer(s) of size %d each.\n", count, size);
 712
 713	return 0;
 714}
 715
 716static int emmaprp_buf_prepare(struct vb2_buffer *vb)
 717{
 718	struct emmaprp_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
 719	struct emmaprp_q_data *q_data;
 720
 721	dprintk(ctx->dev, "type: %d\n", vb->vb2_queue->type);
 722
 723	q_data = get_q_data(ctx, vb->vb2_queue->type);
 724
 725	if (vb2_plane_size(vb, 0) < q_data->sizeimage) {
 726		dprintk(ctx->dev, "%s data will not fit into plane"
 727				  "(%lu < %lu)\n", __func__,
 728				  vb2_plane_size(vb, 0),
 729				  (long)q_data->sizeimage);
 730		return -EINVAL;
 731	}
 732
 733	vb2_set_plane_payload(vb, 0, q_data->sizeimage);
 734
 735	return 0;
 736}
 737
 738static void emmaprp_buf_queue(struct vb2_buffer *vb)
 739{
 740	struct emmaprp_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
 741	v4l2_m2m_buf_queue(ctx->m2m_ctx, vb);
 742}
 743
 744static struct vb2_ops emmaprp_qops = {
 745	.queue_setup	 = emmaprp_queue_setup,
 746	.buf_prepare	 = emmaprp_buf_prepare,
 747	.buf_queue	 = emmaprp_buf_queue,
 748};
 749
 750static int queue_init(void *priv, struct vb2_queue *src_vq,
 751		      struct vb2_queue *dst_vq)
 752{
 753	struct emmaprp_ctx *ctx = priv;
 754	int ret;
 755
 756	memset(src_vq, 0, sizeof(*src_vq));
 757	src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
 758	src_vq->io_modes = VB2_MMAP | VB2_USERPTR;
 759	src_vq->drv_priv = ctx;
 760	src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
 761	src_vq->ops = &emmaprp_qops;
 762	src_vq->mem_ops = &vb2_dma_contig_memops;
 763
 764	ret = vb2_queue_init(src_vq);
 765	if (ret)
 766		return ret;
 767
 768	memset(dst_vq, 0, sizeof(*dst_vq));
 769	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 770	dst_vq->io_modes = VB2_MMAP | VB2_USERPTR;
 771	dst_vq->drv_priv = ctx;
 772	dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
 773	dst_vq->ops = &emmaprp_qops;
 774	dst_vq->mem_ops = &vb2_dma_contig_memops;
 775
 776	return vb2_queue_init(dst_vq);
 777}
 778
 779/*
 780 * File operations
 781 */
 782static int emmaprp_open(struct file *file)
 783{
 784	struct emmaprp_dev *pcdev = video_drvdata(file);
 785	struct emmaprp_ctx *ctx;
 786
 787	ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
 788	if (!ctx)
 789		return -ENOMEM;
 790
 791	file->private_data = ctx;
 792	ctx->dev = pcdev;
 793
 794	ctx->m2m_ctx = v4l2_m2m_ctx_init(pcdev->m2m_dev, ctx, &queue_init);
 795
 796	if (IS_ERR(ctx->m2m_ctx)) {
 797		int ret = PTR_ERR(ctx->m2m_ctx);
 798
 799		kfree(ctx);
 800		return ret;
 801	}
 802
 803	clk_enable(pcdev->clk_emma);
 804	ctx->q_data[V4L2_M2M_SRC].fmt = &formats[1];
 805	ctx->q_data[V4L2_M2M_DST].fmt = &formats[0];
 806
 807	dprintk(pcdev, "Created instance %p, m2m_ctx: %p\n", ctx, ctx->m2m_ctx);
 808
 809	return 0;
 810}
 811
 812static int emmaprp_release(struct file *file)
 813{
 814	struct emmaprp_dev *pcdev = video_drvdata(file);
 815	struct emmaprp_ctx *ctx = file->private_data;
 816
 817	dprintk(pcdev, "Releasing instance %p\n", ctx);
 818
 819	clk_disable(pcdev->clk_emma);
 820	v4l2_m2m_ctx_release(ctx->m2m_ctx);
 821	kfree(ctx);
 822
 823	return 0;
 824}
 825
 826static unsigned int emmaprp_poll(struct file *file,
 827				 struct poll_table_struct *wait)
 828{
 829	struct emmaprp_ctx *ctx = file->private_data;
 830
 831	return v4l2_m2m_poll(file, ctx->m2m_ctx, wait);
 832}
 833
 834static int emmaprp_mmap(struct file *file, struct vm_area_struct *vma)
 835{
 836	struct emmaprp_ctx *ctx = file->private_data;
 837
 838	return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma);
 839}
 840
 841static const struct v4l2_file_operations emmaprp_fops = {
 842	.owner		= THIS_MODULE,
 843	.open		= emmaprp_open,
 844	.release	= emmaprp_release,
 845	.poll		= emmaprp_poll,
 846	.unlocked_ioctl	= video_ioctl2,
 847	.mmap		= emmaprp_mmap,
 848};
 849
 850static struct video_device emmaprp_videodev = {
 851	.name		= MEM2MEM_NAME,
 852	.fops		= &emmaprp_fops,
 853	.ioctl_ops	= &emmaprp_ioctl_ops,
 854	.minor		= -1,
 855	.release	= video_device_release,
 856};
 857
 858static struct v4l2_m2m_ops m2m_ops = {
 859	.device_run	= emmaprp_device_run,
 860	.job_abort	= emmaprp_job_abort,
 861	.lock		= emmaprp_lock,
 862	.unlock		= emmaprp_unlock,
 863};
 864
 865static int emmaprp_probe(struct platform_device *pdev)
 866{
 867	struct emmaprp_dev *pcdev;
 868	struct video_device *vfd;
 869	struct resource *res_emma;
 870	int irq_emma;
 871	int ret;
 872
 873	pcdev = kzalloc(sizeof *pcdev, GFP_KERNEL);
 874	if (!pcdev)
 875		return -ENOMEM;
 876
 877	spin_lock_init(&pcdev->irqlock);
 878
 879	pcdev->clk_emma = clk_get(&pdev->dev, NULL);
 880	if (IS_ERR(pcdev->clk_emma)) {
 881		ret = PTR_ERR(pcdev->clk_emma);
 882		goto free_dev;
 883	}
 884
 885	irq_emma = platform_get_irq(pdev, 0);
 886	res_emma = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 887	if (irq_emma < 0 || res_emma == NULL) {
 888		dev_err(&pdev->dev, "Missing platform resources data\n");
 889		ret = -ENODEV;
 890		goto free_clk;
 891	}
 892
 893	ret = v4l2_device_register(&pdev->dev, &pcdev->v4l2_dev);
 894	if (ret)
 895		goto free_clk;
 896
 897	mutex_init(&pcdev->dev_mutex);
 898
 899	vfd = video_device_alloc();
 900	if (!vfd) {
 901		v4l2_err(&pcdev->v4l2_dev, "Failed to allocate video device\n");
 902		ret = -ENOMEM;
 903		goto unreg_dev;
 904	}
 905
 906	*vfd = emmaprp_videodev;
 907	/* Locking in file operations other than ioctl should be done
 908	   by the driver, not the V4L2 core.
 909	   This driver needs auditing so that this flag can be removed. */
 910	set_bit(V4L2_FL_LOCK_ALL_FOPS, &vfd->flags);
 911	vfd->lock = &pcdev->dev_mutex;
 912
 913	video_set_drvdata(vfd, pcdev);
 914	snprintf(vfd->name, sizeof(vfd->name), "%s", emmaprp_videodev.name);
 915	pcdev->vfd = vfd;
 916	v4l2_info(&pcdev->v4l2_dev, EMMAPRP_MODULE_NAME
 917			" Device registered as /dev/video%d\n", vfd->num);
 918
 919	platform_set_drvdata(pdev, pcdev);
 920
 921	if (devm_request_mem_region(&pdev->dev, res_emma->start,
 922	    resource_size(res_emma), MEM2MEM_NAME) == NULL)
 923		goto rel_vdev;
 924
 925	pcdev->base_emma = devm_ioremap(&pdev->dev, res_emma->start,
 926					resource_size(res_emma));
 927	if (!pcdev->base_emma)
 928		goto rel_vdev;
 929
 930	pcdev->irq_emma = irq_emma;
 931	pcdev->res_emma = res_emma;
 932
 933	if (devm_request_irq(&pdev->dev, pcdev->irq_emma, emmaprp_irq,
 934			     0, MEM2MEM_NAME, pcdev) < 0)
 935		goto rel_vdev;
 936
 937	pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
 938	if (IS_ERR(pcdev->alloc_ctx)) {
 939		v4l2_err(&pcdev->v4l2_dev, "Failed to alloc vb2 context\n");
 940		ret = PTR_ERR(pcdev->alloc_ctx);
 941		goto rel_vdev;
 942	}
 943
 944	pcdev->m2m_dev = v4l2_m2m_init(&m2m_ops);
 945	if (IS_ERR(pcdev->m2m_dev)) {
 946		v4l2_err(&pcdev->v4l2_dev, "Failed to init mem2mem device\n");
 947		ret = PTR_ERR(pcdev->m2m_dev);
 948		goto rel_ctx;
 949	}
 950
 951	ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
 952	if (ret) {
 953		v4l2_err(&pcdev->v4l2_dev, "Failed to register video device\n");
 954		goto rel_m2m;
 955	}
 956
 957	return 0;
 958
 959
 960rel_m2m:
 961	v4l2_m2m_release(pcdev->m2m_dev);
 962rel_ctx:
 963	vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx);
 964rel_vdev:
 965	video_device_release(vfd);
 966unreg_dev:
 967	v4l2_device_unregister(&pcdev->v4l2_dev);
 968free_clk:
 969	clk_put(pcdev->clk_emma);
 970free_dev:
 971	kfree(pcdev);
 972
 973	return ret;
 974}
 975
 976static int emmaprp_remove(struct platform_device *pdev)
 977{
 978	struct emmaprp_dev *pcdev = platform_get_drvdata(pdev);
 979
 980	v4l2_info(&pcdev->v4l2_dev, "Removing " EMMAPRP_MODULE_NAME);
 981
 982	video_unregister_device(pcdev->vfd);
 983	v4l2_m2m_release(pcdev->m2m_dev);
 984	vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx);
 985	v4l2_device_unregister(&pcdev->v4l2_dev);
 986	clk_put(pcdev->clk_emma);
 987	kfree(pcdev);
 988
 989	return 0;
 990}
 991
 992static struct platform_driver emmaprp_pdrv = {
 993	.probe		= emmaprp_probe,
 994	.remove		= emmaprp_remove,
 995	.driver		= {
 996		.name	= MEM2MEM_NAME,
 997		.owner	= THIS_MODULE,
 998	},
 999};
1000
1001static void __exit emmaprp_exit(void)
1002{
1003	platform_driver_unregister(&emmaprp_pdrv);
1004}
1005
1006static int __init emmaprp_init(void)
1007{
1008	return platform_driver_register(&emmaprp_pdrv);
1009}
1010
1011module_init(emmaprp_init);
1012module_exit(emmaprp_exit);