18091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin/*
28091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin * Support eMMa-PrP through mem2mem framework.
38091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin *
48091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin * eMMa-PrP is a piece of HW that allows fetching buffers
58091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin * from one memory location and do several operations on
68091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin * them such as scaling or format conversion giving, as a result
78091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin * a new processed buffer in another memory location.
88091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin *
98091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin * Based on mem2mem_testdev.c by Pawel Osciak.
108091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin *
118091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin * Copyright (c) 2011 Vista Silicon S.L.
128091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin * Javier Martin <javier.martin@vista-silicon.com>
138091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin *
148091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin * This program is free software; you can redistribute it and/or modify
158091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin * it under the terms of the GNU General Public License as published by the
168091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin * Free Software Foundation; either version 2 of the
178091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin * License, or (at your option) any later version
188091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin */
198091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#include <linux/module.h>
208091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#include <linux/clk.h>
218091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#include <linux/slab.h>
228091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#include <linux/interrupt.h>
238091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#include <linux/io.h>
248091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
258091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#include <linux/platform_device.h>
268091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#include <media/v4l2-mem2mem.h>
278091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#include <media/v4l2-device.h>
288091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#include <media/v4l2-ioctl.h>
298091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#include <media/videobuf2-dma-contig.h>
308091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#include <asm/sizes.h>
318091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
328091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define EMMAPRP_MODULE_NAME "mem2mem-emmaprp"
338091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
348091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier MartinMODULE_DESCRIPTION("Mem-to-mem device which supports eMMa-PrP present in mx2 SoCs");
358091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier MartinMODULE_AUTHOR("Javier Martin <javier.martin@vista-silicon.com");
368091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier MartinMODULE_LICENSE("GPL");
378091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier MartinMODULE_VERSION("0.0.1");
388091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
398091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstatic bool debug;
408091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinmodule_param(debug, bool, 0644);
418091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
428091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define MIN_W 32
438091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define MIN_H 32
448091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define MAX_W 2040
458091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define MAX_H 2046
468091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
478091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define S_ALIGN		1 /* multiple of 2 */
488091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define W_ALIGN_YUV420	3 /* multiple of 8 */
498091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define W_ALIGN_OTHERS	2 /* multiple of 4 */
508091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define H_ALIGN		1 /* multiple of 2 */
518091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
528091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin/* Flags that indicate a format can be used for capture/output */
538091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define MEM2MEM_CAPTURE	(1 << 0)
548091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define MEM2MEM_OUTPUT	(1 << 1)
558091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
568091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define MEM2MEM_NAME		"m2m-emmaprp"
578091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
588091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin/* In bytes, per queue */
598091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define MEM2MEM_VID_MEM_LIMIT	SZ_16M
608091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
618091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define dprintk(dev, fmt, arg...) \
628091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	v4l2_dbg(1, debug, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg)
638091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
648091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin/* EMMA PrP */
658091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CNTL                        0x00
668091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_INTR_CNTL                   0x04
678091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_INTRSTATUS                  0x08
688091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_SOURCE_Y_PTR                0x0c
698091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_SOURCE_CB_PTR               0x10
708091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_SOURCE_CR_PTR               0x14
718091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_DEST_RGB1_PTR               0x18
728091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_DEST_RGB2_PTR               0x1c
738091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_DEST_Y_PTR                  0x20
748091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_DEST_CB_PTR                 0x24
758091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_DEST_CR_PTR                 0x28
768091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_SRC_FRAME_SIZE              0x2c
778091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_DEST_CH1_LINE_STRIDE        0x30
788091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_SRC_PIXEL_FORMAT_CNTL       0x34
798091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CH1_PIXEL_FORMAT_CNTL       0x38
808091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CH1_OUT_IMAGE_SIZE          0x3c
818091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CH2_OUT_IMAGE_SIZE          0x40
828091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_SRC_LINE_STRIDE             0x44
838091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CSC_COEF_012                0x48
848091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CSC_COEF_345                0x4c
858091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CSC_COEF_678                0x50
868091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CH1_RZ_HORI_COEF1           0x54
878091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CH1_RZ_HORI_COEF2           0x58
888091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CH1_RZ_HORI_VALID           0x5c
898091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CH1_RZ_VERT_COEF1           0x60
908091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CH1_RZ_VERT_COEF2           0x64
918091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CH1_RZ_VERT_VALID           0x68
928091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CH2_RZ_HORI_COEF1           0x6c
938091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CH2_RZ_HORI_COEF2           0x70
948091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CH2_RZ_HORI_VALID           0x74
958091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CH2_RZ_VERT_COEF1           0x78
968091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CH2_RZ_VERT_COEF2           0x7c
978091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CH2_RZ_VERT_VALID           0x80
988091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
998091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CNTL_CH1EN          (1 << 0)
1008091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CNTL_CH2EN          (1 << 1)
1018091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CNTL_CSIEN          (1 << 2)
1028091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CNTL_DATA_IN_YUV420 (0 << 3)
1038091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CNTL_DATA_IN_YUV422 (1 << 3)
1048091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CNTL_DATA_IN_RGB16  (2 << 3)
1058091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CNTL_DATA_IN_RGB32  (3 << 3)
1068091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CNTL_CH1_OUT_RGB8   (0 << 5)
1078091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CNTL_CH1_OUT_RGB16  (1 << 5)
1088091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CNTL_CH1_OUT_RGB32  (2 << 5)
1098091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CNTL_CH1_OUT_YUV422 (3 << 5)
1108091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CNTL_CH2_OUT_YUV420 (0 << 7)
1118091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CNTL_CH2_OUT_YUV422 (1 << 7)
1128091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CNTL_CH2_OUT_YUV444 (2 << 7)
1138091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CNTL_CH1_LEN        (1 << 9)
1148091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CNTL_CH2_LEN        (1 << 10)
1158091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CNTL_SKIP_FRAME     (1 << 11)
1168091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CNTL_SWRST          (1 << 12)
1178091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CNTL_CLKEN          (1 << 13)
1188091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CNTL_WEN            (1 << 14)
1198091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CNTL_CH1BYP         (1 << 15)
1208091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CNTL_IN_TSKIP(x)    ((x) << 16)
1218091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CNTL_CH1_TSKIP(x)   ((x) << 19)
1228091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CNTL_CH2_TSKIP(x)   ((x) << 22)
1238091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CNTL_INPUT_FIFO_LEVEL(x)    ((x) << 25)
1248091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CNTL_RZ_FIFO_LEVEL(x)       ((x) << 27)
1258091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CNTL_CH2B1EN        (1 << 29)
1268091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CNTL_CH2B2EN        (1 << 30)
1278091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_CNTL_CH2FEN         (1 << 31)
1288091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
1298091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_SIZE_HEIGHT(x)	(x)
1308091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_SIZE_WIDTH(x)	((x) << 16)
1318091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
1328091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin/* IRQ Enable and status register */
1338091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_INTR_RDERR          (1 << 0)
1348091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_INTR_CH1WERR        (1 << 1)
1358091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_INTR_CH2WERR        (1 << 2)
1368091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_INTR_CH1FC          (1 << 3)
1378091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_INTR_CH2FC          (1 << 5)
1388091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_INTR_LBOVF          (1 << 7)
1398091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_INTR_CH2OVF         (1 << 8)
1408091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
1418091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_INTR_ST_RDERR	(1 << 0)
1428091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_INTR_ST_CH1WERR	(1 << 1)
1438091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_INTR_ST_CH2WERR	(1 << 2)
1448091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_INTR_ST_CH2B2CI	(1 << 3)
1458091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_INTR_ST_CH2B1CI	(1 << 4)
1468091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_INTR_ST_CH1B2CI	(1 << 5)
1478091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_INTR_ST_CH1B1CI	(1 << 6)
1488091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_INTR_ST_LBOVF	(1 << 7)
1498091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define PRP_INTR_ST_CH2OVF	(1 << 8)
1508091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
1518091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstruct emmaprp_fmt {
1528091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	char	*name;
1538091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	u32	fourcc;
1548091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	/* Types the format can be used for */
1558091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	u32	types;
1568091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin};
1578091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
1588091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstatic struct emmaprp_fmt formats[] = {
1598091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	{
1608091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		.name	= "YUV 4:2:0 Planar",
1618091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		.fourcc	= V4L2_PIX_FMT_YUV420,
1628091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		.types	= MEM2MEM_CAPTURE,
1638091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	},
1648091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	{
1658091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		.name	= "4:2:2, packed, YUYV",
1668091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		.fourcc	= V4L2_PIX_FMT_YUYV,
1678091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		.types	= MEM2MEM_OUTPUT,
1688091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	},
1698091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin};
1708091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
1718091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin/* Per-queue, driver-specific private data */
1728091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstruct emmaprp_q_data {
1738091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	unsigned int		width;
1748091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	unsigned int		height;
1758091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	unsigned int		sizeimage;
1768091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct emmaprp_fmt	*fmt;
1778091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin};
1788091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
1798091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinenum {
1808091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	V4L2_M2M_SRC = 0,
1818091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	V4L2_M2M_DST = 1,
1828091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin};
1838091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
1848091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin#define NUM_FORMATS ARRAY_SIZE(formats)
1858091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
1868091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstatic struct emmaprp_fmt *find_format(struct v4l2_format *f)
1878091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin{
1888091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct emmaprp_fmt *fmt;
1898091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	unsigned int k;
1908091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
1918091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	for (k = 0; k < NUM_FORMATS; k++) {
1928091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		fmt = &formats[k];
1938091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		if (fmt->fourcc == f->fmt.pix.pixelformat)
1948091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin			break;
1958091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	}
1968091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
1978091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	if (k == NUM_FORMATS)
1988091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		return NULL;
1998091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
2008091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	return &formats[k];
2018091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin}
2028091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
2038091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstruct emmaprp_dev {
2048091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct v4l2_device	v4l2_dev;
2058091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct video_device	*vfd;
2068091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
2078091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct mutex		dev_mutex;
2088091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	spinlock_t		irqlock;
2098091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
2108091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	int			irq_emma;
2118091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	void __iomem		*base_emma;
2128091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct clk		*clk_emma;
2138091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct resource		*res_emma;
2148091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
2158091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct v4l2_m2m_dev	*m2m_dev;
2168091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct vb2_alloc_ctx	*alloc_ctx;
2178091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin};
2188091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
2198091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstruct emmaprp_ctx {
2208091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct emmaprp_dev	*dev;
2218091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	/* Abort requested by m2m */
2228091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	int			aborting;
2238091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct emmaprp_q_data	q_data[2];
2248091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct v4l2_m2m_ctx	*m2m_ctx;
2258091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin};
2268091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
2278091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstatic struct emmaprp_q_data *get_q_data(struct emmaprp_ctx *ctx,
2288091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin					 enum v4l2_buf_type type)
2298091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin{
2308091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	switch (type) {
2318091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
2328091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		return &(ctx->q_data[V4L2_M2M_SRC]);
2338091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
2348091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		return &(ctx->q_data[V4L2_M2M_DST]);
2358091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	default:
2368091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		BUG();
2378091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	}
2388091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	return NULL;
2398091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin}
2408091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
2418091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin/*
2428091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin * mem2mem callbacks
2438091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin */
2448091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstatic void emmaprp_job_abort(void *priv)
2458091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin{
2468091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct emmaprp_ctx *ctx = priv;
2478091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct emmaprp_dev *pcdev = ctx->dev;
2488091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
2498091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	ctx->aborting = 1;
2508091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
2518091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	dprintk(pcdev, "Aborting task\n");
2528091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
2538091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	v4l2_m2m_job_finish(pcdev->m2m_dev, ctx->m2m_ctx);
2548091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin}
2558091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
2568091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstatic void emmaprp_lock(void *priv)
2578091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin{
2588091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct emmaprp_ctx *ctx = priv;
2598091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct emmaprp_dev *pcdev = ctx->dev;
2608091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	mutex_lock(&pcdev->dev_mutex);
2618091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin}
2628091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
2638091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstatic void emmaprp_unlock(void *priv)
2648091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin{
2658091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct emmaprp_ctx *ctx = priv;
2668091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct emmaprp_dev *pcdev = ctx->dev;
2678091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	mutex_unlock(&pcdev->dev_mutex);
2688091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin}
2698091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
2708091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstatic inline void emmaprp_dump_regs(struct emmaprp_dev *pcdev)
2718091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin{
2728091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	dprintk(pcdev,
2738091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		"eMMa-PrP Registers:\n"
2748091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		"  SOURCE_Y_PTR = 0x%08X\n"
2758091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		"  SRC_FRAME_SIZE = 0x%08X\n"
2768091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		"  DEST_Y_PTR = 0x%08X\n"
2778091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		"  DEST_CR_PTR = 0x%08X\n"
2788091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		"  DEST_CB_PTR = 0x%08X\n"
2798091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		"  CH2_OUT_IMAGE_SIZE = 0x%08X\n"
2808091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		"  CNTL = 0x%08X\n",
2818091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		readl(pcdev->base_emma + PRP_SOURCE_Y_PTR),
2828091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		readl(pcdev->base_emma + PRP_SRC_FRAME_SIZE),
2838091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		readl(pcdev->base_emma + PRP_DEST_Y_PTR),
2848091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		readl(pcdev->base_emma + PRP_DEST_CR_PTR),
2858091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		readl(pcdev->base_emma + PRP_DEST_CB_PTR),
2868091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		readl(pcdev->base_emma + PRP_CH2_OUT_IMAGE_SIZE),
2878091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		readl(pcdev->base_emma + PRP_CNTL));
2888091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin}
2898091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
2908091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstatic void emmaprp_device_run(void *priv)
2918091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin{
2928091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct emmaprp_ctx *ctx = priv;
2938091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct emmaprp_q_data *s_q_data, *d_q_data;
2948091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct vb2_buffer *src_buf, *dst_buf;
2958091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct emmaprp_dev *pcdev = ctx->dev;
2968091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	unsigned int s_width, s_height;
2978091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	unsigned int d_width, d_height;
2988091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	unsigned int d_size;
2998091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	dma_addr_t p_in, p_out;
3008091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	u32 tmp;
3018091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
3028091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
3038091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
3048091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
3058091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	s_q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
3068091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	s_width	= s_q_data->width;
3078091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	s_height = s_q_data->height;
3088091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
3098091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	d_q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
3108091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	d_width = d_q_data->width;
3118091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	d_height = d_q_data->height;
3128091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	d_size = d_width * d_height;
3138091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
3148091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	p_in = vb2_dma_contig_plane_dma_addr(src_buf, 0);
3158091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	p_out = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
3168091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	if (!p_in || !p_out) {
3178091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		v4l2_err(&pcdev->v4l2_dev,
3188091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin			 "Acquiring kernel pointers to buffers failed\n");
3198091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		return;
3208091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	}
3218091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
3228091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	/* Input frame parameters */
3238091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	writel(p_in, pcdev->base_emma + PRP_SOURCE_Y_PTR);
3248091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	writel(PRP_SIZE_WIDTH(s_width) | PRP_SIZE_HEIGHT(s_height),
3258091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	       pcdev->base_emma + PRP_SRC_FRAME_SIZE);
3268091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
3278091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	/* Output frame parameters */
3288091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	writel(p_out, pcdev->base_emma + PRP_DEST_Y_PTR);
3298091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	writel(p_out + d_size, pcdev->base_emma + PRP_DEST_CB_PTR);
3308091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	writel(p_out + d_size + (d_size >> 2),
3318091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	       pcdev->base_emma + PRP_DEST_CR_PTR);
3328091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	writel(PRP_SIZE_WIDTH(d_width) | PRP_SIZE_HEIGHT(d_height),
3338091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	       pcdev->base_emma + PRP_CH2_OUT_IMAGE_SIZE);
3348091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
3358091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	/* IRQ configuration */
3368091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	tmp = readl(pcdev->base_emma + PRP_INTR_CNTL);
3378091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	writel(tmp | PRP_INTR_RDERR |
3388091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		PRP_INTR_CH2WERR |
3398091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		PRP_INTR_CH2FC,
3408091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		pcdev->base_emma + PRP_INTR_CNTL);
3418091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
3428091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	emmaprp_dump_regs(pcdev);
3438091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
3448091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	/* Enable transfer */
3458091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	tmp = readl(pcdev->base_emma + PRP_CNTL);
3468091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	writel(tmp | PRP_CNTL_CH2_OUT_YUV420 |
3478091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		PRP_CNTL_DATA_IN_YUV422 |
3488091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		PRP_CNTL_CH2EN,
3498091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		pcdev->base_emma + PRP_CNTL);
3508091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin}
3518091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
3528091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstatic irqreturn_t emmaprp_irq(int irq_emma, void *data)
3538091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin{
3548091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct emmaprp_dev *pcdev = data;
3558091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct emmaprp_ctx *curr_ctx;
3568091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct vb2_buffer *src_vb, *dst_vb;
3578091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	unsigned long flags;
3588091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	u32 irqst;
3598091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
3608091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	/* Check irq flags and clear irq */
3618091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	irqst = readl(pcdev->base_emma + PRP_INTRSTATUS);
3628091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	writel(irqst, pcdev->base_emma + PRP_INTRSTATUS);
3638091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	dprintk(pcdev, "irqst = 0x%08x\n", irqst);
3648091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
3658091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	curr_ctx = v4l2_m2m_get_curr_priv(pcdev->m2m_dev);
3668091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	if (curr_ctx == NULL) {
3678091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		pr_err("Instance released before the end of transaction\n");
3688091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		return IRQ_HANDLED;
3698091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	}
3708091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
3718091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	if (!curr_ctx->aborting) {
3728091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		if ((irqst & PRP_INTR_ST_RDERR) ||
3738091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		(irqst & PRP_INTR_ST_CH2WERR)) {
3748091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin			pr_err("PrP bus error ocurred, this transfer is probably corrupted\n");
3758091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin			writel(PRP_CNTL_SWRST, pcdev->base_emma + PRP_CNTL);
3768091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		} else if (irqst & PRP_INTR_ST_CH2B1CI) { /* buffer ready */
3778091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin			src_vb = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx);
3788091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin			dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->m2m_ctx);
3798091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
3808091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin			spin_lock_irqsave(&pcdev->irqlock, flags);
3818091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin			v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE);
3828091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin			v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE);
3838091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin			spin_unlock_irqrestore(&pcdev->irqlock, flags);
3848091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		}
3858091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	}
3868091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
3878091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	v4l2_m2m_job_finish(pcdev->m2m_dev, curr_ctx->m2m_ctx);
3888091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	return IRQ_HANDLED;
3898091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin}
3908091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
3918091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin/*
3928091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin * video ioctls
3938091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin */
3948091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstatic int vidioc_querycap(struct file *file, void *priv,
3958091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin			   struct v4l2_capability *cap)
3968091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin{
3978091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	strncpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver) - 1);
3988091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	strncpy(cap->card, MEM2MEM_NAME, sizeof(cap->card) - 1);
3998091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT
4008091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin			  | V4L2_CAP_STREAMING;
4018091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
4028091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	return 0;
4038091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin}
4048091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
4058091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstatic int enum_fmt(struct v4l2_fmtdesc *f, u32 type)
4068091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin{
4078091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	int i, num;
4088091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct emmaprp_fmt *fmt;
4098091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
4108091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	num = 0;
4118091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
4128091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	for (i = 0; i < NUM_FORMATS; ++i) {
4138091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		if (formats[i].types & type) {
4148091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin			/* index-th format of type type found ? */
4158091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin			if (num == f->index)
4168091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin				break;
4178091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin			/* Correct type but haven't reached our index yet,
4188091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin			 * just increment per-type index */
4198091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin			++num;
4208091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		}
4218091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	}
4228091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
4238091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	if (i < NUM_FORMATS) {
4248091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		/* Format found */
4258091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		fmt = &formats[i];
4268091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		strlcpy(f->description, fmt->name, sizeof(f->description) - 1);
4278091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		f->pixelformat = fmt->fourcc;
4288091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		return 0;
4298091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	}
4308091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
4318091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	/* Format not found */
4328091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	return -EINVAL;
4338091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin}
4348091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
4358091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstatic int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
4368091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin				   struct v4l2_fmtdesc *f)
4378091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin{
4388091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	return enum_fmt(f, MEM2MEM_CAPTURE);
4398091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin}
4408091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
4418091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstatic int vidioc_enum_fmt_vid_out(struct file *file, void *priv,
4428091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin				   struct v4l2_fmtdesc *f)
4438091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin{
4448091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	return enum_fmt(f, MEM2MEM_OUTPUT);
4458091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin}
4468091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
4478091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstatic int vidioc_g_fmt(struct emmaprp_ctx *ctx, struct v4l2_format *f)
4488091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin{
4498091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct vb2_queue *vq;
4508091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct emmaprp_q_data *q_data;
4518091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
4528091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
4538091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	if (!vq)
4548091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		return -EINVAL;
4558091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
4568091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	q_data = get_q_data(ctx, f->type);
4578091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
4588091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	f->fmt.pix.width	= q_data->width;
4598091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	f->fmt.pix.height	= q_data->height;
4608091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	f->fmt.pix.field	= V4L2_FIELD_NONE;
4618091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	f->fmt.pix.pixelformat	= q_data->fmt->fourcc;
4628091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420)
4638091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		f->fmt.pix.bytesperline = q_data->width * 3 / 2;
4648091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	else /* YUYV */
4658091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		f->fmt.pix.bytesperline = q_data->width * 2;
4668091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	f->fmt.pix.sizeimage	= q_data->sizeimage;
4678091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
4688091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	return 0;
4698091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin}
4708091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
4718091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstatic int vidioc_g_fmt_vid_out(struct file *file, void *priv,
4728091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin				struct v4l2_format *f)
4738091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin{
4748091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	return vidioc_g_fmt(priv, f);
4758091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin}
4768091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
4778091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstatic int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
4788091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin				struct v4l2_format *f)
4798091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin{
4808091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	return vidioc_g_fmt(priv, f);
4818091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin}
4828091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
4838091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstatic int vidioc_try_fmt(struct v4l2_format *f)
4848091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin{
4858091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	enum v4l2_field field;
4868091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
4878091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
4888091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	if (!find_format(f))
4898091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		return -EINVAL;
4908091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
4918091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	field = f->fmt.pix.field;
4928091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	if (field == V4L2_FIELD_ANY)
4938091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		field = V4L2_FIELD_NONE;
4948091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	else if (V4L2_FIELD_NONE != field)
4958091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		return -EINVAL;
4968091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
4978091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	/* V4L2 specification suggests the driver corrects the format struct
4988091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	 * if any of the dimensions is unsupported */
4998091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	f->fmt.pix.field = field;
5008091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
5018091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420) {
5028091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		v4l_bound_align_image(&f->fmt.pix.width, MIN_W, MAX_W,
5038091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin				      W_ALIGN_YUV420, &f->fmt.pix.height,
5048091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin				      MIN_H, MAX_H, H_ALIGN, S_ALIGN);
5058091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		f->fmt.pix.bytesperline = f->fmt.pix.width * 3 / 2;
5068091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	} else {
5078091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		v4l_bound_align_image(&f->fmt.pix.width, MIN_W, MAX_W,
5088091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin				      W_ALIGN_OTHERS, &f->fmt.pix.height,
5098091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin				      MIN_H, MAX_H, H_ALIGN, S_ALIGN);
5108091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
5118091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	}
5128091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
5138091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
5148091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	return 0;
5158091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin}
5168091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
5178091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstatic int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
5188091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin				  struct v4l2_format *f)
5198091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin{
5208091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct emmaprp_fmt *fmt;
5218091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct emmaprp_ctx *ctx = priv;
5228091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
5238091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	fmt = find_format(f);
5248091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	if (!fmt || !(fmt->types & MEM2MEM_CAPTURE)) {
5258091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		v4l2_err(&ctx->dev->v4l2_dev,
5268091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin			 "Fourcc format (0x%08x) invalid.\n",
5278091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin			 f->fmt.pix.pixelformat);
5288091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		return -EINVAL;
5298091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	}
5308091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
5318091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	return vidioc_try_fmt(f);
5328091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin}
5338091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
5348091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstatic int vidioc_try_fmt_vid_out(struct file *file, void *priv,
5358091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin				  struct v4l2_format *f)
5368091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin{
5378091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct emmaprp_fmt *fmt;
5388091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct emmaprp_ctx *ctx = priv;
5398091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
5408091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	fmt = find_format(f);
5418091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	if (!fmt || !(fmt->types & MEM2MEM_OUTPUT)) {
5428091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		v4l2_err(&ctx->dev->v4l2_dev,
5438091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin			 "Fourcc format (0x%08x) invalid.\n",
5448091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin			 f->fmt.pix.pixelformat);
5458091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		return -EINVAL;
5468091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	}
5478091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
5488091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	return vidioc_try_fmt(f);
5498091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin}
5508091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
5518091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstatic int vidioc_s_fmt(struct emmaprp_ctx *ctx, struct v4l2_format *f)
5528091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin{
5538091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct emmaprp_q_data *q_data;
5548091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct vb2_queue *vq;
5558091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	int ret;
5568091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
5578091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
5588091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	if (!vq)
5598091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		return -EINVAL;
5608091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
5618091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	q_data = get_q_data(ctx, f->type);
5628091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	if (!q_data)
5638091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		return -EINVAL;
5648091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
5658091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	if (vb2_is_busy(vq)) {
5668091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		v4l2_err(&ctx->dev->v4l2_dev, "%s queue busy\n", __func__);
5678091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		return -EBUSY;
5688091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	}
5698091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
5708091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	ret = vidioc_try_fmt(f);
5718091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	if (ret)
5728091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		return ret;
5738091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
5748091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	q_data->fmt		= find_format(f);
5758091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	q_data->width		= f->fmt.pix.width;
5768091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	q_data->height		= f->fmt.pix.height;
5778091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	if (q_data->fmt->fourcc == V4L2_PIX_FMT_YUV420)
5788091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		q_data->sizeimage = q_data->width * q_data->height * 3 / 2;
5798091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	else /* YUYV */
5808091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		q_data->sizeimage = q_data->width * q_data->height * 2;
5818091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
5828091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	dprintk(ctx->dev,
5838091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		"Setting format for type %d, wxh: %dx%d, fmt: %d\n",
5848091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		f->type, q_data->width, q_data->height, q_data->fmt->fourcc);
5858091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
5868091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	return 0;
5878091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin}
5888091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
5898091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstatic int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
5908091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin				struct v4l2_format *f)
5918091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin{
5928091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	int ret;
5938091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
5948091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	ret = vidioc_try_fmt_vid_cap(file, priv, f);
5958091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	if (ret)
5968091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		return ret;
5978091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
5988091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	return vidioc_s_fmt(priv, f);
5998091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin}
6008091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
6018091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstatic int vidioc_s_fmt_vid_out(struct file *file, void *priv,
6028091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin				struct v4l2_format *f)
6038091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin{
6048091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	int ret;
6058091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
6068091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	ret = vidioc_try_fmt_vid_out(file, priv, f);
6078091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	if (ret)
6088091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		return ret;
6098091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
6108091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	return vidioc_s_fmt(priv, f);
6118091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin}
6128091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
6138091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstatic int vidioc_reqbufs(struct file *file, void *priv,
6148091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin			  struct v4l2_requestbuffers *reqbufs)
6158091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin{
6168091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct emmaprp_ctx *ctx = priv;
6178091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
6188091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs);
6198091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin}
6208091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
6218091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstatic int vidioc_querybuf(struct file *file, void *priv,
6228091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin			   struct v4l2_buffer *buf)
6238091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin{
6248091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct emmaprp_ctx *ctx = priv;
6258091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
6268091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf);
6278091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin}
6288091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
6298091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstatic int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
6308091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin{
6318091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct emmaprp_ctx *ctx = priv;
6328091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
6338091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf);
6348091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin}
6358091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
6368091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstatic int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
6378091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin{
6388091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct emmaprp_ctx *ctx = priv;
6398091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
6408091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
6418091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin}
6428091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
6438091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstatic int vidioc_streamon(struct file *file, void *priv,
6448091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin			   enum v4l2_buf_type type)
6458091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin{
6468091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct emmaprp_ctx *ctx = priv;
6478091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
6488091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	return v4l2_m2m_streamon(file, ctx->m2m_ctx, type);
6498091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin}
6508091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
6518091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstatic int vidioc_streamoff(struct file *file, void *priv,
6528091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin			    enum v4l2_buf_type type)
6538091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin{
6548091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct emmaprp_ctx *ctx = priv;
6558091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
6568091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type);
6578091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin}
6588091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
6598091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstatic const struct v4l2_ioctl_ops emmaprp_ioctl_ops = {
6608091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	.vidioc_querycap	= vidioc_querycap,
6618091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
6628091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	.vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
6638091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	.vidioc_g_fmt_vid_cap	= vidioc_g_fmt_vid_cap,
6648091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	.vidioc_try_fmt_vid_cap	= vidioc_try_fmt_vid_cap,
6658091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	.vidioc_s_fmt_vid_cap	= vidioc_s_fmt_vid_cap,
6668091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
6678091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	.vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out,
6688091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	.vidioc_g_fmt_vid_out	= vidioc_g_fmt_vid_out,
6698091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	.vidioc_try_fmt_vid_out	= vidioc_try_fmt_vid_out,
6708091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	.vidioc_s_fmt_vid_out	= vidioc_s_fmt_vid_out,
6718091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
6728091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	.vidioc_reqbufs		= vidioc_reqbufs,
6738091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	.vidioc_querybuf	= vidioc_querybuf,
6748091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
6758091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	.vidioc_qbuf		= vidioc_qbuf,
6768091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	.vidioc_dqbuf		= vidioc_dqbuf,
6778091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
6788091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	.vidioc_streamon	= vidioc_streamon,
6798091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	.vidioc_streamoff	= vidioc_streamoff,
6808091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin};
6818091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
6828091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
6838091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin/*
6848091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin * Queue operations
6858091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin */
6868091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstatic int emmaprp_queue_setup(struct vb2_queue *vq,
6878091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin				const struct v4l2_format *fmt,
6888091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin				unsigned int *nbuffers, unsigned int *nplanes,
6898091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin				unsigned int sizes[], void *alloc_ctxs[])
6908091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin{
6918091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct emmaprp_ctx *ctx = vb2_get_drv_priv(vq);
6928091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct emmaprp_q_data *q_data;
6938091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	unsigned int size, count = *nbuffers;
6948091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
6958091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	q_data = get_q_data(ctx, vq->type);
6968091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
6978091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	if (q_data->fmt->fourcc == V4L2_PIX_FMT_YUV420)
6988091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		size = q_data->width * q_data->height * 3 / 2;
6998091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	else
7008091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		size = q_data->width * q_data->height * 2;
7018091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
7028091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	while (size * count > MEM2MEM_VID_MEM_LIMIT)
7038091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		(count)--;
7048091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
7058091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	*nplanes = 1;
7068091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	*nbuffers = count;
7078091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	sizes[0] = size;
7088091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
7098091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	alloc_ctxs[0] = ctx->dev->alloc_ctx;
7108091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
7118091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	dprintk(ctx->dev, "get %d buffer(s) of size %d each.\n", count, size);
7128091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
7138091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	return 0;
7148091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin}
7158091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
7168091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstatic int emmaprp_buf_prepare(struct vb2_buffer *vb)
7178091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin{
7188091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct emmaprp_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
7198091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct emmaprp_q_data *q_data;
7208091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
7218091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	dprintk(ctx->dev, "type: %d\n", vb->vb2_queue->type);
7228091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
7238091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	q_data = get_q_data(ctx, vb->vb2_queue->type);
7248091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
7258091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	if (vb2_plane_size(vb, 0) < q_data->sizeimage) {
7268091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		dprintk(ctx->dev, "%s data will not fit into plane"
7278091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin				  "(%lu < %lu)\n", __func__,
7288091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin				  vb2_plane_size(vb, 0),
7298091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin				  (long)q_data->sizeimage);
7308091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		return -EINVAL;
7318091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	}
7328091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
7338091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	vb2_set_plane_payload(vb, 0, q_data->sizeimage);
7348091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
7358091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	return 0;
7368091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin}
7378091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
7388091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstatic void emmaprp_buf_queue(struct vb2_buffer *vb)
7398091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin{
7408091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct emmaprp_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
7418091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	v4l2_m2m_buf_queue(ctx->m2m_ctx, vb);
7428091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin}
7438091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
7448091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstatic struct vb2_ops emmaprp_qops = {
7458091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	.queue_setup	 = emmaprp_queue_setup,
7468091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	.buf_prepare	 = emmaprp_buf_prepare,
7478091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	.buf_queue	 = emmaprp_buf_queue,
7488091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin};
7498091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
7508091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstatic int queue_init(void *priv, struct vb2_queue *src_vq,
7518091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		      struct vb2_queue *dst_vq)
7528091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin{
7538091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct emmaprp_ctx *ctx = priv;
7548091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	int ret;
7558091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
7568091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	memset(src_vq, 0, sizeof(*src_vq));
7578091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
7588091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	src_vq->io_modes = VB2_MMAP;
7598091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	src_vq->drv_priv = ctx;
7608091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
7618091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	src_vq->ops = &emmaprp_qops;
7628091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	src_vq->mem_ops = &vb2_dma_contig_memops;
7638091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
7648091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	ret = vb2_queue_init(src_vq);
7658091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	if (ret)
7668091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		return ret;
7678091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
7688091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	memset(dst_vq, 0, sizeof(*dst_vq));
7698091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
7708091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	dst_vq->io_modes = VB2_MMAP;
7718091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	dst_vq->drv_priv = ctx;
7728091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
7738091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	dst_vq->ops = &emmaprp_qops;
7748091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	dst_vq->mem_ops = &vb2_dma_contig_memops;
7758091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
7768091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	return vb2_queue_init(dst_vq);
7778091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin}
7788091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
7798091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin/*
7808091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin * File operations
7818091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin */
7828091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstatic int emmaprp_open(struct file *file)
7838091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin{
7848091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct emmaprp_dev *pcdev = video_drvdata(file);
7858091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct emmaprp_ctx *ctx;
7868091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
7878091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
7888091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	if (!ctx)
7898091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		return -ENOMEM;
7908091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
7918091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	file->private_data = ctx;
7928091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	ctx->dev = pcdev;
7938091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
7948091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	ctx->m2m_ctx = v4l2_m2m_ctx_init(pcdev->m2m_dev, ctx, &queue_init);
7958091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
7968091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	if (IS_ERR(ctx->m2m_ctx)) {
7978091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		int ret = PTR_ERR(ctx->m2m_ctx);
7988091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
7998091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		kfree(ctx);
8008091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		return ret;
8018091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	}
8028091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
8038091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	clk_enable(pcdev->clk_emma);
8048091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	ctx->q_data[V4L2_M2M_SRC].fmt = &formats[1];
8058091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	ctx->q_data[V4L2_M2M_DST].fmt = &formats[0];
8068091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
8078091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	dprintk(pcdev, "Created instance %p, m2m_ctx: %p\n", ctx, ctx->m2m_ctx);
8088091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
8098091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	return 0;
8108091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin}
8118091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
8128091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstatic int emmaprp_release(struct file *file)
8138091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin{
8148091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct emmaprp_dev *pcdev = video_drvdata(file);
8158091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct emmaprp_ctx *ctx = file->private_data;
8168091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
8178091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	dprintk(pcdev, "Releasing instance %p\n", ctx);
8188091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
8198091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	clk_disable(pcdev->clk_emma);
8208091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	v4l2_m2m_ctx_release(ctx->m2m_ctx);
8218091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	kfree(ctx);
8228091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
8238091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	return 0;
8248091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin}
8258091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
8268091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstatic unsigned int emmaprp_poll(struct file *file,
8278091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin				 struct poll_table_struct *wait)
8288091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin{
8298091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct emmaprp_ctx *ctx = file->private_data;
8308091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
8318091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	return v4l2_m2m_poll(file, ctx->m2m_ctx, wait);
8328091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin}
8338091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
8348091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstatic int emmaprp_mmap(struct file *file, struct vm_area_struct *vma)
8358091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin{
8368091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct emmaprp_ctx *ctx = file->private_data;
8378091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
8388091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma);
8398091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin}
8408091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
8418091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstatic const struct v4l2_file_operations emmaprp_fops = {
8428091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	.owner		= THIS_MODULE,
8438091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	.open		= emmaprp_open,
8448091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	.release	= emmaprp_release,
8458091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	.poll		= emmaprp_poll,
8468091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	.unlocked_ioctl	= video_ioctl2,
8478091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	.mmap		= emmaprp_mmap,
8488091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin};
8498091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
8508091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstatic struct video_device emmaprp_videodev = {
8518091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	.name		= MEM2MEM_NAME,
8528091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	.fops		= &emmaprp_fops,
8538091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	.ioctl_ops	= &emmaprp_ioctl_ops,
8548091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	.minor		= -1,
8558091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	.release	= video_device_release,
8568091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin};
8578091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
8588091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstatic struct v4l2_m2m_ops m2m_ops = {
8598091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	.device_run	= emmaprp_device_run,
8608091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	.job_abort	= emmaprp_job_abort,
8618091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	.lock		= emmaprp_lock,
8628091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	.unlock		= emmaprp_unlock,
8638091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin};
8648091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
8658091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstatic int emmaprp_probe(struct platform_device *pdev)
8668091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin{
8678091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct emmaprp_dev *pcdev;
8688091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct video_device *vfd;
8698091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct resource *res_emma;
8708091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	int irq_emma;
8718091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	int ret;
8728091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
8738091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	pcdev = kzalloc(sizeof *pcdev, GFP_KERNEL);
8748091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	if (!pcdev)
8758091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		return -ENOMEM;
8768091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
8778091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	spin_lock_init(&pcdev->irqlock);
8788091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
8798091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	pcdev->clk_emma = clk_get(&pdev->dev, NULL);
8808091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	if (IS_ERR(pcdev->clk_emma)) {
8818091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		ret = PTR_ERR(pcdev->clk_emma);
8828091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		goto free_dev;
8838091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	}
8848091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
8858091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	irq_emma = platform_get_irq(pdev, 0);
8868091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	res_emma = platform_get_resource(pdev, IORESOURCE_MEM, 0);
8878091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	if (irq_emma < 0 || res_emma == NULL) {
8888091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		dev_err(&pdev->dev, "Missing platform resources data\n");
8898091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		ret = -ENODEV;
8908091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		goto free_clk;
8918091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	}
8928091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
8938091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	ret = v4l2_device_register(&pdev->dev, &pcdev->v4l2_dev);
8948091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	if (ret)
8958091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		goto free_clk;
8968091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
8978091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	mutex_init(&pcdev->dev_mutex);
8988091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
8998091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	vfd = video_device_alloc();
9008091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	if (!vfd) {
9018091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		v4l2_err(&pcdev->v4l2_dev, "Failed to allocate video device\n");
9028091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		ret = -ENOMEM;
9038091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		goto unreg_dev;
9048091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	}
9058091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
9068091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	*vfd = emmaprp_videodev;
9078091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	vfd->lock = &pcdev->dev_mutex;
9088091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
9098091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	video_set_drvdata(vfd, pcdev);
9108091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	snprintf(vfd->name, sizeof(vfd->name), "%s", emmaprp_videodev.name);
9118091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	pcdev->vfd = vfd;
9128091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	v4l2_info(&pcdev->v4l2_dev, EMMAPRP_MODULE_NAME
9138091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin			" Device registered as /dev/video%d\n", vfd->num);
9148091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
9158091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	platform_set_drvdata(pdev, pcdev);
9168091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
9178091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	if (devm_request_mem_region(&pdev->dev, res_emma->start,
9188091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	    resource_size(res_emma), MEM2MEM_NAME) == NULL)
9198091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		goto rel_vdev;
9208091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
9218091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	pcdev->base_emma = devm_ioremap(&pdev->dev, res_emma->start,
9228091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin					resource_size(res_emma));
9238091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	if (!pcdev->base_emma)
9248091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		goto rel_vdev;
9258091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
9268091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	pcdev->irq_emma = irq_emma;
9278091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	pcdev->res_emma = res_emma;
9288091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
9298091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	if (devm_request_irq(&pdev->dev, pcdev->irq_emma, emmaprp_irq,
9308091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin			     0, MEM2MEM_NAME, pcdev) < 0)
9318091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		goto rel_vdev;
9328091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
9338091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
9348091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	if (IS_ERR(pcdev->alloc_ctx)) {
9358091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		v4l2_err(&pcdev->v4l2_dev, "Failed to alloc vb2 context\n");
9368091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		ret = PTR_ERR(pcdev->alloc_ctx);
9378091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		goto rel_vdev;
9388091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	}
9398091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
9408091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	pcdev->m2m_dev = v4l2_m2m_init(&m2m_ops);
9418091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	if (IS_ERR(pcdev->m2m_dev)) {
9428091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		v4l2_err(&pcdev->v4l2_dev, "Failed to init mem2mem device\n");
9438091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		ret = PTR_ERR(pcdev->m2m_dev);
9448091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		goto rel_ctx;
9458091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	}
9468091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
9478091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
9488091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	if (ret) {
9498091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		v4l2_err(&pcdev->v4l2_dev, "Failed to register video device\n");
9508091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		goto rel_m2m;
9518091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	}
9528091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
9538091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	return 0;
9548091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
9558091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
9568091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinrel_m2m:
9578091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	v4l2_m2m_release(pcdev->m2m_dev);
9588091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinrel_ctx:
9598091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx);
9608091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinrel_vdev:
9618091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	video_device_release(vfd);
9628091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinunreg_dev:
9638091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	v4l2_device_unregister(&pcdev->v4l2_dev);
9648091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinfree_clk:
9658091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	clk_put(pcdev->clk_emma);
9668091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinfree_dev:
9678091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	kfree(pcdev);
9688091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
9698091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	return ret;
9708091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin}
9718091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
9728091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstatic int emmaprp_remove(struct platform_device *pdev)
9738091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin{
9748091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	struct emmaprp_dev *pcdev = platform_get_drvdata(pdev);
9758091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
9768091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	v4l2_info(&pcdev->v4l2_dev, "Removing " EMMAPRP_MODULE_NAME);
9778091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
9788091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	video_unregister_device(pcdev->vfd);
9798091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	v4l2_m2m_release(pcdev->m2m_dev);
9808091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx);
9818091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	v4l2_device_unregister(&pcdev->v4l2_dev);
9828091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	clk_put(pcdev->clk_emma);
9838091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	kfree(pcdev);
9848091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
9858091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	return 0;
9868091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin}
9878091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
9888091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstatic struct platform_driver emmaprp_pdrv = {
9898091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	.probe		= emmaprp_probe,
9908091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	.remove		= emmaprp_remove,
9918091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	.driver		= {
9928091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		.name	= MEM2MEM_NAME,
9938091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin		.owner	= THIS_MODULE,
9948091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	},
9958091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin};
9968091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
9978091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstatic void __exit emmaprp_exit(void)
9988091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin{
9998091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	platform_driver_unregister(&emmaprp_pdrv);
10008091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin}
10018091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
10028091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinstatic int __init emmaprp_init(void)
10038091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin{
10048091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin	return platform_driver_register(&emmaprp_pdrv);
10058091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin}
10068091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martin
10078091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinmodule_init(emmaprp_init);
10088091cb7d9ce671628bb094d5e6bd5395bc3db4f4Javier Martinmodule_exit(emmaprp_exit);
1009