mx2_camera.c revision 5384a12b23160e11ff949a94172051476d308b66
12066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach/*
22066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach * V4L2 Driver for i.MX27/i.MX25 camera host
32066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach *
42066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach * Copyright (C) 2008, Sascha Hauer, Pengutronix
52066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach * Copyright (C) 2010, Baruch Siach, Orex Computed Radiography
62066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach *
72066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach * This program is free software; you can redistribute it and/or modify
82066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach * it under the terms of the GNU General Public License as published by
92066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach * the Free Software Foundation; either version 2 of the License, or
102066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach * (at your option) any later version.
112066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach */
122066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
132066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#include <linux/init.h>
142066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#include <linux/module.h>
152066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#include <linux/io.h>
162066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#include <linux/delay.h>
172066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#include <linux/slab.h>
182066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#include <linux/dma-mapping.h>
192066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#include <linux/errno.h>
202066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#include <linux/fs.h>
212066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#include <linux/interrupt.h>
222066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#include <linux/kernel.h>
232066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#include <linux/mm.h>
242066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#include <linux/moduleparam.h>
252066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#include <linux/time.h>
262066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#include <linux/version.h>
272066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#include <linux/device.h>
282066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#include <linux/platform_device.h>
292066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#include <linux/mutex.h>
302066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#include <linux/clk.h>
312066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
322066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#include <media/v4l2-common.h>
332066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#include <media/v4l2-dev.h>
342066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#include <media/videobuf-dma-contig.h>
352066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#include <media/soc_camera.h>
362066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#include <media/soc_mediabus.h>
372066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
382066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#include <linux/videodev2.h>
392066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
402066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#include <mach/mx2_cam.h>
412066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#ifdef CONFIG_MACH_MX27
422066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#include <mach/dma-mx1-mx2.h>
432066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#endif
442066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#include <mach/hardware.h>
452066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
462066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#include <asm/dma.h>
472066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
482066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define MX2_CAM_DRV_NAME "mx2-camera"
492066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define MX2_CAM_VERSION_CODE KERNEL_VERSION(0, 0, 5)
502066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define MX2_CAM_DRIVER_DESCRIPTION "i.MX2x_Camera"
512066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
522066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach/* reset values */
532066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSICR1_RESET_VAL	0x40000800
542066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSICR2_RESET_VAL	0x0
552066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSICR3_RESET_VAL	0x0
562066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
572066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach/* csi control reg 1 */
582066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSICR1_SWAP16_EN	(1 << 31)
592066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSICR1_EXT_VSYNC	(1 << 30)
602066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSICR1_EOF_INTEN	(1 << 29)
612066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSICR1_PRP_IF_EN	(1 << 28)
622066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSICR1_CCIR_MODE	(1 << 27)
632066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSICR1_COF_INTEN	(1 << 26)
642066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSICR1_SF_OR_INTEN	(1 << 25)
652066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSICR1_RF_OR_INTEN	(1 << 24)
662066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSICR1_STATFF_LEVEL	(3 << 22)
672066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSICR1_STATFF_INTEN	(1 << 21)
682066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSICR1_RXFF_LEVEL(l)	(((l) & 3) << 19)	/* MX27 */
692066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSICR1_FB2_DMA_INTEN	(1 << 20)		/* MX25 */
702066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSICR1_FB1_DMA_INTEN	(1 << 19)		/* MX25 */
712066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSICR1_RXFF_INTEN	(1 << 18)
722066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSICR1_SOF_POL		(1 << 17)
732066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSICR1_SOF_INTEN	(1 << 16)
742066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSICR1_MCLKDIV(d)	(((d) & 0xF) << 12)
752066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSICR1_HSYNC_POL	(1 << 11)
762066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSICR1_CCIR_EN		(1 << 10)
772066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSICR1_MCLKEN		(1 << 9)
782066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSICR1_FCC		(1 << 8)
792066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSICR1_PACK_DIR		(1 << 7)
802066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSICR1_CLR_STATFIFO	(1 << 6)
812066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSICR1_CLR_RXFIFO	(1 << 5)
822066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSICR1_GCLK_MODE	(1 << 4)
832066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSICR1_INV_DATA		(1 << 3)
842066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSICR1_INV_PCLK		(1 << 2)
852066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSICR1_REDGE		(1 << 1)
862066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
872066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define SHIFT_STATFF_LEVEL	22
882066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define SHIFT_RXFF_LEVEL	19
892066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define SHIFT_MCLKDIV		12
902066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
912066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach/* control reg 3 */
922066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSICR3_FRMCNT		(0xFFFF << 16)
932066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSICR3_FRMCNT_RST	(1 << 15)
942066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSICR3_DMA_REFLASH_RFF	(1 << 14)
952066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSICR3_DMA_REFLASH_SFF	(1 << 13)
962066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSICR3_DMA_REQ_EN_RFF	(1 << 12)
972066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSICR3_DMA_REQ_EN_SFF	(1 << 11)
982066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSICR3_RXFF_LEVEL(l)	(((l) & 7) << 4)	/* MX25 */
992066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSICR3_CSI_SUP		(1 << 3)
1002066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSICR3_ZERO_PACK_EN	(1 << 2)
1012066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSICR3_ECC_INT_EN	(1 << 1)
1022066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSICR3_ECC_AUTO_EN	(1 << 0)
1032066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
1042066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define SHIFT_FRMCNT		16
1052066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
1062066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach/* csi status reg */
1072066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSISR_SFF_OR_INT	(1 << 25)
1082066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSISR_RFF_OR_INT	(1 << 24)
1092066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSISR_STATFF_INT	(1 << 21)
1102066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSISR_DMA_TSF_FB2_INT	(1 << 20)	/* MX25 */
1112066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSISR_DMA_TSF_FB1_INT	(1 << 19)	/* MX25 */
1122066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSISR_RXFF_INT		(1 << 18)
1132066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSISR_EOF_INT		(1 << 17)
1142066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSISR_SOF_INT		(1 << 16)
1152066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSISR_F2_INT		(1 << 15)
1162066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSISR_F1_INT		(1 << 14)
1172066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSISR_COF_INT		(1 << 13)
1182066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSISR_ECC_INT		(1 << 1)
1192066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSISR_DRDY		(1 << 0)
1202066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
1212066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSICR1			0x00
1222066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSICR2			0x04
1232066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSISR			(cpu_is_mx27() ? 0x08 : 0x18)
1242066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSISTATFIFO		0x0c
1252066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSIRFIFO		0x10
1262066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSIRXCNT		0x14
1272066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSICR3			(cpu_is_mx27() ? 0x1C : 0x08)
1282066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSIDMASA_STATFIFO	0x20
1292066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSIDMATA_STATFIFO	0x24
1302066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSIDMASA_FB1		0x28
1312066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSIDMASA_FB2		0x2c
1322066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSIFBUF_PARA		0x30
1332066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define CSIIMAG_PARA		0x34
1342066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
1352066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach/* EMMA PrP */
1362066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CNTL			0x00
1372066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_INTR_CNTL			0x04
1382066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_INTRSTATUS			0x08
1392066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_SOURCE_Y_PTR		0x0c
1402066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_SOURCE_CB_PTR		0x10
1412066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_SOURCE_CR_PTR		0x14
1422066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_DEST_RGB1_PTR		0x18
1432066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_DEST_RGB2_PTR		0x1c
1442066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_DEST_Y_PTR			0x20
1452066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_DEST_CB_PTR			0x24
1462066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_DEST_CR_PTR			0x28
1472066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_SRC_FRAME_SIZE		0x2c
1482066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_DEST_CH1_LINE_STRIDE	0x30
1492066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_SRC_PIXEL_FORMAT_CNTL	0x34
1502066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CH1_PIXEL_FORMAT_CNTL	0x38
1512066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CH1_OUT_IMAGE_SIZE		0x3c
1522066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CH2_OUT_IMAGE_SIZE		0x40
1532066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_SRC_LINE_STRIDE		0x44
1542066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CSC_COEF_012		0x48
1552066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CSC_COEF_345		0x4c
1562066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CSC_COEF_678		0x50
1572066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CH1_RZ_HORI_COEF1		0x54
1582066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CH1_RZ_HORI_COEF2		0x58
1592066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CH1_RZ_HORI_VALID		0x5c
1602066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CH1_RZ_VERT_COEF1		0x60
1612066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CH1_RZ_VERT_COEF2		0x64
1622066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CH1_RZ_VERT_VALID		0x68
1632066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CH2_RZ_HORI_COEF1		0x6c
1642066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CH2_RZ_HORI_COEF2		0x70
1652066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CH2_RZ_HORI_VALID		0x74
1662066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CH2_RZ_VERT_COEF1		0x78
1672066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CH2_RZ_VERT_COEF2		0x7c
1682066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CH2_RZ_VERT_VALID		0x80
1692066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
1702066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CNTL_CH1EN		(1 << 0)
1712066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CNTL_CH2EN		(1 << 1)
1722066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CNTL_CSIEN		(1 << 2)
1732066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CNTL_DATA_IN_YUV420	(0 << 3)
1742066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CNTL_DATA_IN_YUV422	(1 << 3)
1752066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CNTL_DATA_IN_RGB16	(2 << 3)
1762066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CNTL_DATA_IN_RGB32	(3 << 3)
1772066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CNTL_CH1_OUT_RGB8	(0 << 5)
1782066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CNTL_CH1_OUT_RGB16	(1 << 5)
1792066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CNTL_CH1_OUT_RGB32	(2 << 5)
1802066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CNTL_CH1_OUT_YUV422	(3 << 5)
1812066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CNTL_CH2_OUT_YUV420	(0 << 7)
1822066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CNTL_CH2_OUT_YUV422 (1 << 7)
1832066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CNTL_CH2_OUT_YUV444	(2 << 7)
1842066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CNTL_CH1_LEN	(1 << 9)
1852066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CNTL_CH2_LEN	(1 << 10)
1862066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CNTL_SKIP_FRAME	(1 << 11)
1872066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CNTL_SWRST		(1 << 12)
1882066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CNTL_CLKEN		(1 << 13)
1892066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CNTL_WEN		(1 << 14)
1902066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CNTL_CH1BYP		(1 << 15)
1912066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CNTL_IN_TSKIP(x)	((x) << 16)
1922066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CNTL_CH1_TSKIP(x)	((x) << 19)
1932066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CNTL_CH2_TSKIP(x)	((x) << 22)
1942066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CNTL_INPUT_FIFO_LEVEL(x)	((x) << 25)
1952066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CNTL_RZ_FIFO_LEVEL(x)	((x) << 27)
1962066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CNTL_CH2B1EN	(1 << 29)
1972066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CNTL_CH2B2EN	(1 << 30)
1982066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_CNTL_CH2FEN		(1 << 31)
1992066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
2002066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach/* IRQ Enable and status register */
2012066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_INTR_RDERR		(1 << 0)
2022066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_INTR_CH1WERR	(1 << 1)
2032066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_INTR_CH2WERR	(1 << 2)
2042066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_INTR_CH1FC		(1 << 3)
2052066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_INTR_CH2FC		(1 << 5)
2062066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_INTR_LBOVF		(1 << 7)
2072066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define PRP_INTR_CH2OVF		(1 << 8)
2082066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
2092066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define mx27_camera_emma(pcdev)	(cpu_is_mx27() && pcdev->use_emma)
2102066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
2112066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define MAX_VIDEO_MEM	16
2122066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
2132066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstruct mx2_camera_dev {
2142066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct device		*dev;
2152066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct soc_camera_host	soc_host;
2162066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct soc_camera_device *icd;
2172066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct clk		*clk_csi, *clk_emma;
2182066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
2192066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	unsigned int		irq_csi, irq_emma;
2202066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	void __iomem		*base_csi, *base_emma;
2212066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	unsigned long		base_dma;
2222066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
2232066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct mx2_camera_platform_data *pdata;
2242066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct resource		*res_csi, *res_emma;
2252066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	unsigned long		platform_flags;
2262066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
2272066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct list_head	capture;
2282066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct list_head	active_bufs;
2292066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
2302066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	spinlock_t		lock;
2312066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
2322066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	int			dma;
2332066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct mx2_buffer	*active;
2342066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct mx2_buffer	*fb1_active;
2352066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct mx2_buffer	*fb2_active;
2362066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
2372066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	int			use_emma;
2382066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
2392066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	u32			csicr1;
2402066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
24179d3c2c2395a89a70d25f0c77c11afc87efab89bBaruch Siach	void			*discard_buffer;
2422066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	dma_addr_t		discard_buffer_dma;
2432066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	size_t			discard_size;
2442066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach};
2452066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
2462066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach/* buffer for one video frame */
2472066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstruct mx2_buffer {
2482066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	/* common v4l buffer stuff -- must be first */
2492066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct videobuf_buffer		vb;
2502066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
2512066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	enum v4l2_mbus_pixelcode	code;
2522066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
2532066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	int bufnum;
2542066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach};
2552066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
2562066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic void mx2_camera_deactivate(struct mx2_camera_dev *pcdev)
2572066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{
2582066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	unsigned long flags;
2592066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
2602066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	clk_disable(pcdev->clk_csi);
2612066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	writel(0, pcdev->base_csi + CSICR1);
2622066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (mx27_camera_emma(pcdev)) {
2632066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		writel(0, pcdev->base_emma + PRP_CNTL);
2642066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	} else if (cpu_is_mx25()) {
2652066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		spin_lock_irqsave(&pcdev->lock, flags);
2662066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		pcdev->fb1_active = NULL;
2672066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		pcdev->fb2_active = NULL;
2682066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		writel(0, pcdev->base_csi + CSIDMASA_FB1);
2692066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		writel(0, pcdev->base_csi + CSIDMASA_FB2);
2702066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		spin_unlock_irqrestore(&pcdev->lock, flags);
2712066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	}
2722066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach}
2732066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
2742066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach/*
2752066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach * The following two functions absolutely depend on the fact, that
2762066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach * there can be only one camera on mx2 camera sensor interface
2772066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach */
2782066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic int mx2_camera_add_device(struct soc_camera_device *icd)
2792066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{
2802066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
2812066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct mx2_camera_dev *pcdev = ici->priv;
2822066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	int ret;
2832066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	u32 csicr1;
2842066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
2852066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (pcdev->icd)
2862066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		return -EBUSY;
2872066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
2882066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	ret = clk_enable(pcdev->clk_csi);
2892066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (ret < 0)
2902066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		return ret;
2912066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
2922066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	csicr1 = CSICR1_MCLKEN;
2932066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
2942066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (mx27_camera_emma(pcdev)) {
2952066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		csicr1 |= CSICR1_PRP_IF_EN | CSICR1_FCC |
2962066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			CSICR1_RXFF_LEVEL(0);
2972066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	} else if (cpu_is_mx27())
2982066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		csicr1 |= CSICR1_SOF_INTEN | CSICR1_RXFF_LEVEL(2);
2992066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
3002066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	pcdev->csicr1 = csicr1;
3012066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	writel(pcdev->csicr1, pcdev->base_csi + CSICR1);
3022066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
3032066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	pcdev->icd = icd;
3042066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
3052066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	dev_info(icd->dev.parent, "Camera driver attached to camera %d\n",
3062066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		 icd->devnum);
3072066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
3082066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	return 0;
3092066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach}
3102066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
3112066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic void mx2_camera_remove_device(struct soc_camera_device *icd)
3122066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{
3132066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
3142066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct mx2_camera_dev *pcdev = ici->priv;
3152066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
3162066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	BUG_ON(icd != pcdev->icd);
3172066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
3182066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	dev_info(icd->dev.parent, "Camera driver detached from camera %d\n",
3192066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		 icd->devnum);
3202066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
3212066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	mx2_camera_deactivate(pcdev);
3222066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
3232066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (pcdev->discard_buffer) {
3242066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		dma_free_coherent(ici->v4l2_dev.dev, pcdev->discard_size,
3252066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach				pcdev->discard_buffer,
3262066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach				pcdev->discard_buffer_dma);
3272066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		pcdev->discard_buffer = NULL;
3282066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	}
3292066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
3302066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	pcdev->icd = NULL;
3312066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach}
3322066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
3332066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#ifdef CONFIG_MACH_MX27
3342066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic void mx27_camera_dma_enable(struct mx2_camera_dev *pcdev)
3352066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{
3362066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	u32 tmp;
3372066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
3382066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	imx_dma_enable(pcdev->dma);
3392066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
3402066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	tmp = readl(pcdev->base_csi + CSICR1);
3412066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	tmp |= CSICR1_RF_OR_INTEN;
3422066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	writel(tmp, pcdev->base_csi + CSICR1);
3432066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach}
3442066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
3452066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic irqreturn_t mx27_camera_irq(int irq_csi, void *data)
3462066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{
3472066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct mx2_camera_dev *pcdev = data;
3482066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	u32 status = readl(pcdev->base_csi + CSISR);
3492066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
3502066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (status & CSISR_SOF_INT && pcdev->active) {
3512066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		u32 tmp;
3522066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
3532066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		tmp = readl(pcdev->base_csi + CSICR1);
3542066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		writel(tmp | CSICR1_CLR_RXFIFO, pcdev->base_csi + CSICR1);
3552066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		mx27_camera_dma_enable(pcdev);
3562066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	}
3572066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
3582066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	writel(CSISR_SOF_INT | CSISR_RFF_OR_INT, pcdev->base_csi + CSISR);
3592066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
3602066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	return IRQ_HANDLED;
3612066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach}
3622066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#else
3632066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic irqreturn_t mx27_camera_irq(int irq_csi, void *data)
3642066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{
3652066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	return IRQ_NONE;
3662066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach}
3672066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#endif /* CONFIG_MACH_MX27 */
3682066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
3692066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic void mx25_camera_frame_done(struct mx2_camera_dev *pcdev, int fb,
3702066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		int state)
3712066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{
3722066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct videobuf_buffer *vb;
3732066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct mx2_buffer *buf;
3742066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct mx2_buffer **fb_active = fb == 1 ? &pcdev->fb1_active :
3752066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		&pcdev->fb2_active;
3762066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	u32 fb_reg = fb == 1 ? CSIDMASA_FB1 : CSIDMASA_FB2;
3772066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	unsigned long flags;
3782066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
3792066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	spin_lock_irqsave(&pcdev->lock, flags);
3802066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
3815384a12b23160e11ff949a94172051476d308b66Baruch Siach	if (*fb_active == NULL)
3825384a12b23160e11ff949a94172051476d308b66Baruch Siach		goto out;
3835384a12b23160e11ff949a94172051476d308b66Baruch Siach
3842066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	vb = &(*fb_active)->vb;
3852066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
3862066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		vb, vb->baddr, vb->bsize);
3872066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
3882066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	vb->state = state;
3892066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	do_gettimeofday(&vb->ts);
3902066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	vb->field_count++;
3912066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
3922066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	wake_up(&vb->done);
3932066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
3942066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (list_empty(&pcdev->capture)) {
3952066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		buf = NULL;
3962066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		writel(0, pcdev->base_csi + fb_reg);
3972066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	} else {
3982066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		buf = list_entry(pcdev->capture.next, struct mx2_buffer,
3992066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach				vb.queue);
4002066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		vb = &buf->vb;
4012066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		list_del(&vb->queue);
4022066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		vb->state = VIDEOBUF_ACTIVE;
4032066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		writel(videobuf_to_dma_contig(vb), pcdev->base_csi + fb_reg);
4042066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	}
4052066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
4062066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	*fb_active = buf;
4072066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
4085384a12b23160e11ff949a94172051476d308b66Baruch Siachout:
4092066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	spin_unlock_irqrestore(&pcdev->lock, flags);
4102066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach}
4112066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
4122066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic irqreturn_t mx25_camera_irq(int irq_csi, void *data)
4132066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{
4142066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct mx2_camera_dev *pcdev = data;
4152066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	u32 status = readl(pcdev->base_csi + CSISR);
4162066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
4172066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (status & CSISR_DMA_TSF_FB1_INT)
4182066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		mx25_camera_frame_done(pcdev, 1, VIDEOBUF_DONE);
4192066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	else if (status & CSISR_DMA_TSF_FB2_INT)
4202066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		mx25_camera_frame_done(pcdev, 2, VIDEOBUF_DONE);
4212066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
4222066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	/* FIXME: handle CSISR_RFF_OR_INT */
4232066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
4242066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	writel(status, pcdev->base_csi + CSISR);
4252066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
4262066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	return IRQ_HANDLED;
4272066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach}
4282066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
4292066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach/*
4302066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach *  Videobuf operations
4312066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach */
4322066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic int mx2_videobuf_setup(struct videobuf_queue *vq, unsigned int *count,
4332066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			      unsigned int *size)
4342066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{
4352066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct soc_camera_device *icd = vq->priv_data;
4362066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
4372066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			icd->current_fmt->host_fmt);
4382066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
4392066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	dev_dbg(&icd->dev, "count=%d, size=%d\n", *count, *size);
4402066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
4412066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (bytes_per_line < 0)
4422066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		return bytes_per_line;
4432066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
4442066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	*size = bytes_per_line * icd->user_height;
4452066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
4462066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (0 == *count)
4472066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		*count = 32;
4482066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (*size * *count > MAX_VIDEO_MEM * 1024 * 1024)
4492066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		*count = (MAX_VIDEO_MEM * 1024 * 1024) / *size;
4502066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
4512066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	return 0;
4522066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach}
4532066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
4542066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic void free_buffer(struct videobuf_queue *vq, struct mx2_buffer *buf)
4552066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{
4562066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct soc_camera_device *icd = vq->priv_data;
4572066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct videobuf_buffer *vb = &buf->vb;
4582066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
4592066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
4602066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		vb, vb->baddr, vb->bsize);
4612066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
4622066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	/*
4632066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	 * This waits until this buffer is out of danger, i.e., until it is no
4642066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	 * longer in STATE_QUEUED or STATE_ACTIVE
4652066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	 */
4662066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	videobuf_waiton(vb, 0, 0);
4672066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
4682066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	videobuf_dma_contig_free(vq, vb);
4692066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	dev_dbg(&icd->dev, "%s freed\n", __func__);
4702066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
4712066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	vb->state = VIDEOBUF_NEEDS_INIT;
4722066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach}
4732066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
4742066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic int mx2_videobuf_prepare(struct videobuf_queue *vq,
4752066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		struct videobuf_buffer *vb, enum v4l2_field field)
4762066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{
4772066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct soc_camera_device *icd = vq->priv_data;
4782066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct mx2_buffer *buf = container_of(vb, struct mx2_buffer, vb);
4792066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
4802066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			icd->current_fmt->host_fmt);
4812066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	int ret = 0;
4822066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
4832066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
4842066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		vb, vb->baddr, vb->bsize);
4852066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
4862066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (bytes_per_line < 0)
4872066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		return bytes_per_line;
4882066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
4892066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#ifdef DEBUG
4902066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	/*
4912066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	 * This can be useful if you want to see if we actually fill
4922066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	 * the buffer with something
4932066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	 */
4942066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	memset((void *)vb->baddr, 0xaa, vb->bsize);
4952066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#endif
4962066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
4972066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (buf->code	!= icd->current_fmt->code ||
4982066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	    vb->width	!= icd->user_width ||
4992066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	    vb->height	!= icd->user_height ||
5002066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	    vb->field	!= field) {
5012066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		buf->code	= icd->current_fmt->code;
5022066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		vb->width	= icd->user_width;
5032066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		vb->height	= icd->user_height;
5042066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		vb->field	= field;
5052066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		vb->state	= VIDEOBUF_NEEDS_INIT;
5062066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	}
5072066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
5082066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	vb->size = bytes_per_line * vb->height;
5092066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (vb->baddr && vb->bsize < vb->size) {
5102066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		ret = -EINVAL;
5112066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		goto out;
5122066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	}
5132066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
5142066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (vb->state == VIDEOBUF_NEEDS_INIT) {
5152066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		ret = videobuf_iolock(vq, vb, NULL);
5162066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		if (ret)
5172066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			goto fail;
5182066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
5192066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		vb->state = VIDEOBUF_PREPARED;
5202066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	}
5212066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
5222066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	return 0;
5232066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
5242066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachfail:
5252066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	free_buffer(vq, buf);
5262066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachout:
5272066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	return ret;
5282066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach}
5292066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
5302066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic void mx2_videobuf_queue(struct videobuf_queue *vq,
5312066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			       struct videobuf_buffer *vb)
5322066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{
5332066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct soc_camera_device *icd = vq->priv_data;
5342066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct soc_camera_host *ici =
5352066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		to_soc_camera_host(icd->dev.parent);
5362066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct mx2_camera_dev *pcdev = ici->priv;
5372066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct mx2_buffer *buf = container_of(vb, struct mx2_buffer, vb);
5382066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	unsigned long flags;
5392066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
5402066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
5412066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		vb, vb->baddr, vb->bsize);
5422066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
5432066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	spin_lock_irqsave(&pcdev->lock, flags);
5442066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
5452066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	vb->state = VIDEOBUF_QUEUED;
5462066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	list_add_tail(&vb->queue, &pcdev->capture);
5472066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
5482066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (mx27_camera_emma(pcdev)) {
5492066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		goto out;
5502066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#ifdef CONFIG_MACH_MX27
5512066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	} else if (cpu_is_mx27()) {
5522066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		int ret;
5532066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
5542066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		if (pcdev->active == NULL) {
5552066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			ret = imx_dma_setup_single(pcdev->dma,
5562066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach					videobuf_to_dma_contig(vb), vb->size,
5572066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach					(u32)pcdev->base_dma + 0x10,
5582066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach					DMA_MODE_READ);
5592066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			if (ret) {
5602066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach				vb->state = VIDEOBUF_ERROR;
5612066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach				wake_up(&vb->done);
5622066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach				goto out;
5632066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			}
5642066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
5652066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			vb->state = VIDEOBUF_ACTIVE;
5662066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			pcdev->active = buf;
5672066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		}
5682066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#endif
5692066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	} else { /* cpu_is_mx25() */
5702066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		u32 csicr3, dma_inten = 0;
5712066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
5722066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		if (pcdev->fb1_active == NULL) {
5732066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			writel(videobuf_to_dma_contig(vb),
5742066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach					pcdev->base_csi + CSIDMASA_FB1);
5752066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			pcdev->fb1_active = buf;
5762066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			dma_inten = CSICR1_FB1_DMA_INTEN;
5772066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		} else if (pcdev->fb2_active == NULL) {
5782066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			writel(videobuf_to_dma_contig(vb),
5792066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach					pcdev->base_csi + CSIDMASA_FB2);
5802066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			pcdev->fb2_active = buf;
5812066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			dma_inten = CSICR1_FB2_DMA_INTEN;
5822066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		}
5832066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
5842066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		if (dma_inten) {
5852066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			list_del(&vb->queue);
5862066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			vb->state = VIDEOBUF_ACTIVE;
5872066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
5882066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			csicr3 = readl(pcdev->base_csi + CSICR3);
5892066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
5902066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			/* Reflash DMA */
5912066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			writel(csicr3 | CSICR3_DMA_REFLASH_RFF,
5922066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach					pcdev->base_csi + CSICR3);
5932066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
5942066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			/* clear & enable interrupts */
5952066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			writel(dma_inten, pcdev->base_csi + CSISR);
5962066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			pcdev->csicr1 |= dma_inten;
5972066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			writel(pcdev->csicr1, pcdev->base_csi + CSICR1);
5982066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
5992066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			/* enable DMA */
6002066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			csicr3 |= CSICR3_DMA_REQ_EN_RFF | CSICR3_RXFF_LEVEL(1);
6012066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			writel(csicr3, pcdev->base_csi + CSICR3);
6022066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		}
6032066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	}
6042066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
6052066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachout:
6062066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	spin_unlock_irqrestore(&pcdev->lock, flags);
6072066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach}
6082066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
6092066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic void mx2_videobuf_release(struct videobuf_queue *vq,
6102066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach				 struct videobuf_buffer *vb)
6112066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{
6122066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct soc_camera_device *icd = vq->priv_data;
6132066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
6142066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct mx2_camera_dev *pcdev = ici->priv;
6152066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct mx2_buffer *buf = container_of(vb, struct mx2_buffer, vb);
6162066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	unsigned long flags;
6172066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
6182066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#ifdef DEBUG
6192066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	dev_dbg(&icd->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
6202066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		vb, vb->baddr, vb->bsize);
6212066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
6222066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	switch (vb->state) {
6232066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	case VIDEOBUF_ACTIVE:
6242066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		dev_info(&icd->dev, "%s (active)\n", __func__);
6252066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		break;
6262066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	case VIDEOBUF_QUEUED:
6272066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		dev_info(&icd->dev, "%s (queued)\n", __func__);
6282066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		break;
6292066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	case VIDEOBUF_PREPARED:
6302066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		dev_info(&icd->dev, "%s (prepared)\n", __func__);
6312066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		break;
6322066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	default:
6332066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		dev_info(&icd->dev, "%s (unknown) %d\n", __func__,
6342066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach				vb->state);
6352066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		break;
6362066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	}
6372066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#endif
6382066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
6392066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	/*
6402066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	 * Terminate only queued but inactive buffers. Active buffers are
6412066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	 * released when they become inactive after videobuf_waiton().
6422066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	 *
6432066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	 * FIXME: implement forced termination of active buffers, so that the
6442066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	 * user won't get stuck in an uninterruptible state. This requires a
6452066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	 * specific handling for each of the three DMA types that this driver
6462066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	 * supports.
6472066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	 */
6482066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	spin_lock_irqsave(&pcdev->lock, flags);
6492066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (vb->state == VIDEOBUF_QUEUED) {
6502066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		list_del(&vb->queue);
6512066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		vb->state = VIDEOBUF_ERROR;
6522066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	}
6532066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	spin_unlock_irqrestore(&pcdev->lock, flags);
6542066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
6552066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	free_buffer(vq, buf);
6562066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach}
6572066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
6582066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic struct videobuf_queue_ops mx2_videobuf_ops = {
6592066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	.buf_setup      = mx2_videobuf_setup,
6602066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	.buf_prepare    = mx2_videobuf_prepare,
6612066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	.buf_queue      = mx2_videobuf_queue,
6622066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	.buf_release    = mx2_videobuf_release,
6632066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach};
6642066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
6652066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic void mx2_camera_init_videobuf(struct videobuf_queue *q,
6662066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			      struct soc_camera_device *icd)
6672066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{
6682066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
6692066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct mx2_camera_dev *pcdev = ici->priv;
6702066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
6712066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	videobuf_queue_dma_contig_init(q, &mx2_videobuf_ops, pcdev->dev,
6722066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			&pcdev->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE,
6732066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			V4L2_FIELD_NONE, sizeof(struct mx2_buffer), icd);
6742066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach}
6752066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
6762066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define MX2_BUS_FLAGS	(SOCAM_DATAWIDTH_8 | \
6772066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			SOCAM_MASTER | \
6782066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			SOCAM_VSYNC_ACTIVE_HIGH | \
6792066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			SOCAM_VSYNC_ACTIVE_LOW | \
6802066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			SOCAM_HSYNC_ACTIVE_HIGH | \
6812066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			SOCAM_HSYNC_ACTIVE_LOW | \
6822066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			SOCAM_PCLK_SAMPLE_RISING | \
6832066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			SOCAM_PCLK_SAMPLE_FALLING | \
6842066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			SOCAM_DATA_ACTIVE_HIGH | \
6852066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			SOCAM_DATA_ACTIVE_LOW)
6862066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
6872066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic int mx27_camera_emma_prp_reset(struct mx2_camera_dev *pcdev)
6882066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{
6892066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	u32 cntl;
6902066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	int count = 0;
6912066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
6922066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	cntl = readl(pcdev->base_emma + PRP_CNTL);
6932066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	writel(PRP_CNTL_SWRST, pcdev->base_emma + PRP_CNTL);
6942066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	while (count++ < 100) {
6952066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		if (!(readl(pcdev->base_emma + PRP_CNTL) & PRP_CNTL_SWRST))
6962066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			return 0;
6972066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		barrier();
6982066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		udelay(1);
6992066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	}
7002066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
7012066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	return -ETIMEDOUT;
7022066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach}
7032066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
7042066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic void mx27_camera_emma_buf_init(struct soc_camera_device *icd,
7052066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		int bytesperline)
7062066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{
7072066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct soc_camera_host *ici =
7082066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		to_soc_camera_host(icd->dev.parent);
7092066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct mx2_camera_dev *pcdev = ici->priv;
7102066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
7112066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	writel(pcdev->discard_buffer_dma,
7122066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			pcdev->base_emma + PRP_DEST_RGB1_PTR);
7132066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	writel(pcdev->discard_buffer_dma,
7142066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			pcdev->base_emma + PRP_DEST_RGB2_PTR);
7152066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
7162066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	/*
7172066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	 * We only use the EMMA engine to get rid of the broken
7182066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	 * DMA Engine. No color space consversion at the moment.
7192066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	 * We adjust incoming and outgoing pixelformat to rgb16
7202066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	 * and adjust the bytesperline accordingly.
7212066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	 */
7222066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	writel(PRP_CNTL_CH1EN |
7232066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			PRP_CNTL_CSIEN |
7242066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			PRP_CNTL_DATA_IN_RGB16 |
7252066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			PRP_CNTL_CH1_OUT_RGB16 |
7262066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			PRP_CNTL_CH1_LEN |
7272066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			PRP_CNTL_CH1BYP |
7282066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			PRP_CNTL_CH1_TSKIP(0) |
7292066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			PRP_CNTL_IN_TSKIP(0),
7302066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			pcdev->base_emma + PRP_CNTL);
7312066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
7322066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	writel(((bytesperline >> 1) << 16) | icd->user_height,
7332066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			pcdev->base_emma + PRP_SRC_FRAME_SIZE);
7342066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	writel(((bytesperline >> 1) << 16) | icd->user_height,
7352066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			pcdev->base_emma + PRP_CH1_OUT_IMAGE_SIZE);
7362066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	writel(bytesperline,
7372066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			pcdev->base_emma + PRP_DEST_CH1_LINE_STRIDE);
7382066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	writel(0x2ca00565, /* RGB565 */
7392066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			pcdev->base_emma + PRP_SRC_PIXEL_FORMAT_CNTL);
7402066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	writel(0x2ca00565, /* RGB565 */
7412066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			pcdev->base_emma + PRP_CH1_PIXEL_FORMAT_CNTL);
7422066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
7432066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	/* Enable interrupts */
7442066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	writel(PRP_INTR_RDERR |
7452066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			PRP_INTR_CH1WERR |
7462066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			PRP_INTR_CH2WERR |
7472066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			PRP_INTR_CH1FC |
7482066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			PRP_INTR_CH2FC |
7492066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			PRP_INTR_LBOVF |
7502066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			PRP_INTR_CH2OVF,
7512066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			pcdev->base_emma + PRP_INTR_CNTL);
7522066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach}
7532066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
7542066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic int mx2_camera_set_bus_param(struct soc_camera_device *icd,
7552066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		__u32 pixfmt)
7562066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{
7572066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct soc_camera_host *ici =
7582066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		to_soc_camera_host(icd->dev.parent);
7592066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct mx2_camera_dev *pcdev = ici->priv;
7602066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	unsigned long camera_flags, common_flags;
7612066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	int ret = 0;
7622066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	int bytesperline;
7632066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	u32 csicr1 = pcdev->csicr1;
7642066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
7652066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	camera_flags = icd->ops->query_bus_param(icd);
7662066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
7672066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	common_flags = soc_camera_bus_param_compatible(camera_flags,
7682066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach				MX2_BUS_FLAGS);
7692066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (!common_flags)
7702066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		return -EINVAL;
7712066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
7722066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if ((common_flags & SOCAM_HSYNC_ACTIVE_HIGH) &&
7732066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	    (common_flags & SOCAM_HSYNC_ACTIVE_LOW)) {
7742066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		if (pcdev->platform_flags & MX2_CAMERA_HSYNC_HIGH)
7752066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			common_flags &= ~SOCAM_HSYNC_ACTIVE_LOW;
7762066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		else
7772066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			common_flags &= ~SOCAM_HSYNC_ACTIVE_HIGH;
7782066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	}
7792066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
7802066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if ((common_flags & SOCAM_PCLK_SAMPLE_RISING) &&
7812066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	    (common_flags & SOCAM_PCLK_SAMPLE_FALLING)) {
7822066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		if (pcdev->platform_flags & MX2_CAMERA_PCLK_SAMPLE_RISING)
7832066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			common_flags &= ~SOCAM_PCLK_SAMPLE_FALLING;
7842066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		else
7852066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			common_flags &= ~SOCAM_PCLK_SAMPLE_RISING;
7862066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	}
7872066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
7882066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	ret = icd->ops->set_bus_param(icd, common_flags);
7892066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (ret < 0)
7902066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		return ret;
7912066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
792d86097e19cef2f13a29fc37db0dad17b99b6d5f8Michael Grzeschik	if (common_flags & SOCAM_PCLK_SAMPLE_RISING)
793d86097e19cef2f13a29fc37db0dad17b99b6d5f8Michael Grzeschik		csicr1 |= CSICR1_REDGE;
7942066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (common_flags & SOCAM_PCLK_SAMPLE_FALLING)
7952066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		csicr1 |= CSICR1_INV_PCLK;
7962066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (common_flags & SOCAM_VSYNC_ACTIVE_HIGH)
7972066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		csicr1 |= CSICR1_SOF_POL;
7982066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (common_flags & SOCAM_HSYNC_ACTIVE_HIGH)
7992066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		csicr1 |= CSICR1_HSYNC_POL;
8002066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (pcdev->platform_flags & MX2_CAMERA_SWAP16)
8012066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		csicr1 |= CSICR1_SWAP16_EN;
8022066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (pcdev->platform_flags & MX2_CAMERA_EXT_VSYNC)
8032066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		csicr1 |= CSICR1_EXT_VSYNC;
8042066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (pcdev->platform_flags & MX2_CAMERA_CCIR)
8052066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		csicr1 |= CSICR1_CCIR_EN;
8062066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (pcdev->platform_flags & MX2_CAMERA_CCIR_INTERLACE)
8072066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		csicr1 |= CSICR1_CCIR_MODE;
8082066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (pcdev->platform_flags & MX2_CAMERA_GATED_CLOCK)
8092066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		csicr1 |= CSICR1_GCLK_MODE;
8102066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (pcdev->platform_flags & MX2_CAMERA_INV_DATA)
8112066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		csicr1 |= CSICR1_INV_DATA;
8122066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (pcdev->platform_flags & MX2_CAMERA_PACK_DIR_MSB)
8132066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		csicr1 |= CSICR1_PACK_DIR;
8142066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
8152066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	pcdev->csicr1 = csicr1;
8162066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
8172066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	bytesperline = soc_mbus_bytes_per_line(icd->user_width,
8182066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			icd->current_fmt->host_fmt);
8192066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (bytesperline < 0)
8202066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		return bytesperline;
8212066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
8222066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (mx27_camera_emma(pcdev)) {
8232066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		ret = mx27_camera_emma_prp_reset(pcdev);
8242066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		if (ret)
8252066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			return ret;
8262066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
8272066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		if (pcdev->discard_buffer)
8282066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			dma_free_coherent(ici->v4l2_dev.dev,
8292066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach				pcdev->discard_size, pcdev->discard_buffer,
8302066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach				pcdev->discard_buffer_dma);
8312066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
8322066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		/*
8332066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		 * I didn't manage to properly enable/disable the prp
8342066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		 * on a per frame basis during running transfers,
8352066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		 * thus we allocate a buffer here and use it to
8362066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		 * discard frames when no buffer is available.
8372066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		 * Feel free to work on this ;)
8382066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		 */
8392066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		pcdev->discard_size = icd->user_height * bytesperline;
8402066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		pcdev->discard_buffer = dma_alloc_coherent(ici->v4l2_dev.dev,
8412066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach				pcdev->discard_size, &pcdev->discard_buffer_dma,
8422066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach				GFP_KERNEL);
8432066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		if (!pcdev->discard_buffer)
8442066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			return -ENOMEM;
8452066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
8462066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		mx27_camera_emma_buf_init(icd, bytesperline);
8472066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	} else if (cpu_is_mx25()) {
8482066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		writel((bytesperline * icd->user_height) >> 2,
8492066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach				pcdev->base_csi + CSIRXCNT);
8502066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		writel((bytesperline << 16) | icd->user_height,
8512066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach				pcdev->base_csi + CSIIMAG_PARA);
8522066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	}
8532066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
8542066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	writel(pcdev->csicr1, pcdev->base_csi + CSICR1);
8552066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
8562066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	return 0;
8572066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach}
8582066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
8592066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic int mx2_camera_set_crop(struct soc_camera_device *icd,
8602066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach				struct v4l2_crop *a)
8612066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{
8622066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct v4l2_rect *rect = &a->c;
8632066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
8642066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct v4l2_mbus_framefmt mf;
8652066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	int ret;
8662066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
8672066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	soc_camera_limit_side(&rect->left, &rect->width, 0, 2, 4096);
8682066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	soc_camera_limit_side(&rect->top, &rect->height, 0, 2, 4096);
8692066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
8702066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	ret = v4l2_subdev_call(sd, video, s_crop, a);
8712066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (ret < 0)
8722066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		return ret;
8732066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
8742066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	/* The capture device might have changed its output  */
8752066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf);
8762066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (ret < 0)
8772066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		return ret;
8782066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
8792066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	dev_dbg(icd->dev.parent, "Sensor cropped %dx%d\n",
8802066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		mf.width, mf.height);
8812066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
8822066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	icd->user_width		= mf.width;
8832066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	icd->user_height	= mf.height;
8842066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
8852066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	return ret;
8862066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach}
8872066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
8882066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic int mx2_camera_set_fmt(struct soc_camera_device *icd,
8892066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			       struct v4l2_format *f)
8902066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{
8912066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
8922066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct mx2_camera_dev *pcdev = ici->priv;
8932066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
8942066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	const struct soc_camera_format_xlate *xlate;
8952066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct v4l2_pix_format *pix = &f->fmt.pix;
8962066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct v4l2_mbus_framefmt mf;
8972066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	int ret;
8982066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
8992066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
9002066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (!xlate) {
9012066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		dev_warn(icd->dev.parent, "Format %x not found\n",
9022066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach				pix->pixelformat);
9032066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		return -EINVAL;
9042066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	}
9052066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
9062066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	/* eMMA can only do RGB565 */
9072066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (mx27_camera_emma(pcdev) && pix->pixelformat != V4L2_PIX_FMT_RGB565)
9082066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		return -EINVAL;
9092066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
9102066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	mf.width	= pix->width;
9112066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	mf.height	= pix->height;
9122066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	mf.field	= pix->field;
9132066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	mf.colorspace	= pix->colorspace;
9142066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	mf.code		= xlate->code;
9152066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
9162066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
9172066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (ret < 0 && ret != -ENOIOCTLCMD)
9182066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		return ret;
9192066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
9202066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (mf.code != xlate->code)
9212066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		return -EINVAL;
9222066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
9232066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	pix->width		= mf.width;
9242066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	pix->height		= mf.height;
9252066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	pix->field		= mf.field;
9262066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	pix->colorspace		= mf.colorspace;
9272066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	icd->current_fmt	= xlate;
9282066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
9292066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	return 0;
9302066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach}
9312066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
9322066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic int mx2_camera_try_fmt(struct soc_camera_device *icd,
9332066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach				  struct v4l2_format *f)
9342066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{
9352066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
9362066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct mx2_camera_dev *pcdev = ici->priv;
9372066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
9382066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	const struct soc_camera_format_xlate *xlate;
9392066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct v4l2_pix_format *pix = &f->fmt.pix;
9402066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct v4l2_mbus_framefmt mf;
9412066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	__u32 pixfmt = pix->pixelformat;
9422066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	unsigned int width_limit;
9432066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	int ret;
9442066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
9452066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
9462066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (pixfmt && !xlate) {
9472066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		dev_warn(icd->dev.parent, "Format %x not found\n", pixfmt);
9482066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		return -EINVAL;
9492066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	}
9502066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
9512066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	/* FIXME: implement MX27 limits */
9522066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
9532066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	/* eMMA can only do RGB565 */
9542066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (mx27_camera_emma(pcdev) && pixfmt != V4L2_PIX_FMT_RGB565)
9552066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		return -EINVAL;
9562066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
9572066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	/* limit to MX25 hardware capabilities */
9582066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (cpu_is_mx25()) {
9592066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		if (xlate->host_fmt->bits_per_sample <= 8)
9602066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			width_limit = 0xffff * 4;
9612066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		else
9622066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			width_limit = 0xffff * 2;
9632066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		/* CSIIMAG_PARA limit */
9642066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		if (pix->width > width_limit)
9652066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			pix->width = width_limit;
9662066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		if (pix->height > 0xffff)
9672066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			pix->height = 0xffff;
9682066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
9692066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		pix->bytesperline = soc_mbus_bytes_per_line(pix->width,
9702066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach				xlate->host_fmt);
9712066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		if (pix->bytesperline < 0)
9722066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			return pix->bytesperline;
9732066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		pix->sizeimage = pix->height * pix->bytesperline;
9742066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		if (pix->sizeimage > (4 * 0x3ffff)) { /* CSIRXCNT limit */
9752066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			dev_warn(icd->dev.parent,
9762066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach					"Image size (%u) above limit\n",
9772066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach					pix->sizeimage);
9782066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			return -EINVAL;
9792066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		}
9802066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	}
9812066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
9822066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	/* limit to sensor capabilities */
9832066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	mf.width	= pix->width;
9842066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	mf.height	= pix->height;
9852066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	mf.field	= pix->field;
9862066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	mf.colorspace	= pix->colorspace;
9872066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	mf.code		= xlate->code;
9882066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
9892066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf);
9902066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (ret < 0)
9912066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		return ret;
9922066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
9932066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (mf.field == V4L2_FIELD_ANY)
9942066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		mf.field = V4L2_FIELD_NONE;
9952066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (mf.field != V4L2_FIELD_NONE) {
9962066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		dev_err(icd->dev.parent, "Field type %d unsupported.\n",
9972066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach				mf.field);
9982066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		return -EINVAL;
9992066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	}
10002066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
10012066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	pix->width	= mf.width;
10022066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	pix->height	= mf.height;
10032066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	pix->field	= mf.field;
10042066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	pix->colorspace	= mf.colorspace;
10052066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
10062066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	return 0;
10072066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach}
10082066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
10092066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic int mx2_camera_querycap(struct soc_camera_host *ici,
10102066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			       struct v4l2_capability *cap)
10112066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{
10122066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	/* cap->name is set by the friendly caller:-> */
10132066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	strlcpy(cap->card, MX2_CAM_DRIVER_DESCRIPTION, sizeof(cap->card));
10142066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	cap->version = MX2_CAM_VERSION_CODE;
10152066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
10162066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
10172066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	return 0;
10182066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach}
10192066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
10202066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic int mx2_camera_reqbufs(struct soc_camera_file *icf,
10212066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			      struct v4l2_requestbuffers *p)
10222066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{
10232066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	int i;
10242066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
10252066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	for (i = 0; i < p->count; i++) {
10262066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		struct mx2_buffer *buf = container_of(icf->vb_vidq.bufs[i],
10272066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach						      struct mx2_buffer, vb);
10282066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		INIT_LIST_HEAD(&buf->vb.queue);
10292066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	}
10302066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
10312066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	return 0;
10322066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach}
10332066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
10342066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#ifdef CONFIG_MACH_MX27
10352066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic void mx27_camera_frame_done(struct mx2_camera_dev *pcdev, int state)
10362066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{
10372066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct videobuf_buffer *vb;
10382066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct mx2_buffer *buf;
10392066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	unsigned long flags;
10402066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	int ret;
10412066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
10422066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	spin_lock_irqsave(&pcdev->lock, flags);
10432066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
10442066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (!pcdev->active) {
10452066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		dev_err(pcdev->dev, "%s called with no active buffer!\n",
10462066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach				__func__);
10472066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		goto out;
10482066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	}
10492066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
10502066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	vb = &pcdev->active->vb;
10512066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	buf = container_of(vb, struct mx2_buffer, vb);
10522066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	WARN_ON(list_empty(&vb->queue));
10532066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
10542066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		vb, vb->baddr, vb->bsize);
10552066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
10562066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	/* _init is used to debug races, see comment in pxa_camera_reqbufs() */
10572066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	list_del_init(&vb->queue);
10582066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	vb->state = state;
10592066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	do_gettimeofday(&vb->ts);
10602066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	vb->field_count++;
10612066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
10622066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	wake_up(&vb->done);
10632066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
10642066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (list_empty(&pcdev->capture)) {
10652066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		pcdev->active = NULL;
10662066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		goto out;
10672066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	}
10682066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
10692066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	pcdev->active = list_entry(pcdev->capture.next,
10702066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			struct mx2_buffer, vb.queue);
10712066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
10722066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	vb = &pcdev->active->vb;
10732066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	vb->state = VIDEOBUF_ACTIVE;
10742066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
10752066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	ret = imx_dma_setup_single(pcdev->dma, videobuf_to_dma_contig(vb),
10762066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			vb->size, (u32)pcdev->base_dma + 0x10, DMA_MODE_READ);
10772066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
10782066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (ret) {
10792066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		vb->state = VIDEOBUF_ERROR;
10802066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		pcdev->active = NULL;
10812066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		wake_up(&vb->done);
10822066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	}
10832066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
10842066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachout:
10852066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	spin_unlock_irqrestore(&pcdev->lock, flags);
10862066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach}
10872066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
10882066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic void mx27_camera_dma_err_callback(int channel, void *data, int err)
10892066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{
10902066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct mx2_camera_dev *pcdev = data;
10912066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
10922066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	mx27_camera_frame_done(pcdev, VIDEOBUF_ERROR);
10932066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach}
10942066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
10952066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic void mx27_camera_dma_callback(int channel, void *data)
10962066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{
10972066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct mx2_camera_dev *pcdev = data;
10982066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
10992066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	mx27_camera_frame_done(pcdev, VIDEOBUF_DONE);
11002066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach}
11012066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
11022066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define DMA_REQ_CSI_RX          31 /* FIXME: Add this to a resource */
11032066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
11042066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic int __devinit mx27_camera_dma_init(struct platform_device *pdev,
11052066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		struct mx2_camera_dev *pcdev)
11062066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{
11072066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	int err;
11082066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
11092066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	pcdev->dma = imx_dma_request_by_prio("CSI RX DMA", DMA_PRIO_HIGH);
11102066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (pcdev->dma < 0) {
11112066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		dev_err(&pdev->dev, "%s failed to request DMA channel\n",
11122066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach				__func__);
11132066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		return pcdev->dma;
11142066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	}
11152066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
11162066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	err = imx_dma_setup_handlers(pcdev->dma, mx27_camera_dma_callback,
11172066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach					mx27_camera_dma_err_callback, pcdev);
11182066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (err) {
11192066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		dev_err(&pdev->dev, "%s failed to set DMA callback\n",
11202066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach				__func__);
11212066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		goto err_out;
11222066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	}
11232066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
11242066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	err = imx_dma_config_channel(pcdev->dma,
11252066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_FIFO,
11262066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR,
11272066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			DMA_REQ_CSI_RX, 1);
11282066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (err) {
11292066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		dev_err(&pdev->dev, "%s failed to config DMA channel\n",
11302066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach				__func__);
11312066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		goto err_out;
11322066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	}
11332066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
11342066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	imx_dma_config_burstlen(pcdev->dma, 64);
11352066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
11362066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	return 0;
11372066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
11382066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siacherr_out:
11392066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	imx_dma_free(pcdev->dma);
11402066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
11412066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	return err;
11422066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach}
11432066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#endif /* CONFIG_MACH_MX27 */
11442066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
11452066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic unsigned int mx2_camera_poll(struct file *file, poll_table *pt)
11462066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{
11472066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct soc_camera_file *icf = file->private_data;
11482066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
11492066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	return videobuf_poll_stream(file, &icf->vb_vidq, pt);
11502066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach}
11512066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
11522066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic struct soc_camera_host_ops mx2_soc_camera_host_ops = {
11532066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	.owner		= THIS_MODULE,
11542066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	.add		= mx2_camera_add_device,
11552066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	.remove		= mx2_camera_remove_device,
11562066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	.set_fmt	= mx2_camera_set_fmt,
11572066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	.set_crop	= mx2_camera_set_crop,
11582066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	.try_fmt	= mx2_camera_try_fmt,
11592066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	.init_videobuf	= mx2_camera_init_videobuf,
11602066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	.reqbufs	= mx2_camera_reqbufs,
11612066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	.poll		= mx2_camera_poll,
11622066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	.querycap	= mx2_camera_querycap,
11632066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	.set_bus_param	= mx2_camera_set_bus_param,
11642066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach};
11652066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
11662066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev,
11672066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		int bufnum, int state)
11682066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{
11692066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct mx2_buffer *buf;
11702066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct videobuf_buffer *vb;
11712066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	unsigned long phys;
11722066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
11732066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (!list_empty(&pcdev->active_bufs)) {
11742066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		buf = list_entry(pcdev->active_bufs.next,
11752066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			struct mx2_buffer, vb.queue);
11762066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
11772066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		BUG_ON(buf->bufnum != bufnum);
11782066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
11792066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		vb = &buf->vb;
11802066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#ifdef DEBUG
11812066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		phys = videobuf_to_dma_contig(vb);
11822066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		if (readl(pcdev->base_emma + PRP_DEST_RGB1_PTR + 4 * bufnum)
11832066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach				!= phys) {
11842066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			dev_err(pcdev->dev, "%p != %p\n", phys,
11852066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach					readl(pcdev->base_emma +
11862066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach						PRP_DEST_RGB1_PTR +
11872066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach						4 * bufnum));
11882066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		}
11892066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#endif
11902066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb,
11912066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach				vb->baddr, vb->bsize);
11922066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
11932066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		list_del(&vb->queue);
11942066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		vb->state = state;
11952066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		do_gettimeofday(&vb->ts);
11962066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		vb->field_count++;
11972066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
11982066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		wake_up(&vb->done);
11992066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	}
12002066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
12012066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (list_empty(&pcdev->capture)) {
12022066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		writel(pcdev->discard_buffer_dma, pcdev->base_emma +
12032066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach				PRP_DEST_RGB1_PTR + 4 * bufnum);
12042066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		return;
12052066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	}
12062066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
12072066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	buf = list_entry(pcdev->capture.next,
12082066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			struct mx2_buffer, vb.queue);
12092066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
1210cd9ebdbc0541b4e8ee145c81642d68332f79b932Michael Grzeschik	buf->bufnum = !bufnum;
12112066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
12122066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	list_move_tail(pcdev->capture.next, &pcdev->active_bufs);
12132066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
12142066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	vb = &buf->vb;
12152066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	vb->state = VIDEOBUF_ACTIVE;
12162066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
12172066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	phys = videobuf_to_dma_contig(vb);
12182066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	writel(phys, pcdev->base_emma + PRP_DEST_RGB1_PTR + 4 * bufnum);
12192066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach}
12202066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
12212066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic irqreturn_t mx27_camera_emma_irq(int irq_emma, void *data)
12222066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{
12232066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct mx2_camera_dev *pcdev = data;
12242066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	unsigned int status = readl(pcdev->base_emma + PRP_INTRSTATUS);
12252066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct mx2_buffer *buf;
12262066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
12272066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (status & (1 << 7)) { /* overflow */
12282066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		u32 cntl;
12292066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		/*
12302066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		 * We only disable channel 1 here since this is the only
12312066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		 * enabled channel
12322066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		 *
12332066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		 * FIXME: the correct DMA overflow handling should be resetting
12342066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		 * the buffer, returning an error frame, and continuing with
12352066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		 * the next one.
12362066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		 */
12372066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		cntl = readl(pcdev->base_emma + PRP_CNTL);
12382066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		writel(cntl & ~PRP_CNTL_CH1EN, pcdev->base_emma + PRP_CNTL);
12392066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		writel(cntl, pcdev->base_emma + PRP_CNTL);
12402066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	}
12412066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if ((status & (3 << 5)) == (3 << 5)
12422066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			&& !list_empty(&pcdev->active_bufs)) {
12432066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		/*
12442066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		 * Both buffers have triggered, process the one we're expecting
12452066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		 * to first
12462066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		 */
12472066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		buf = list_entry(pcdev->active_bufs.next,
12482066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			struct mx2_buffer, vb.queue);
12492066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		mx27_camera_frame_done_emma(pcdev, buf->bufnum, VIDEOBUF_DONE);
12502066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		status &= ~(1 << (6 - buf->bufnum)); /* mark processed */
12512066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	}
12522066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (status & (1 << 6))
12532066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		mx27_camera_frame_done_emma(pcdev, 0, VIDEOBUF_DONE);
12542066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (status & (1 << 5))
12552066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		mx27_camera_frame_done_emma(pcdev, 1, VIDEOBUF_DONE);
12562066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
12572066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	writel(status, pcdev->base_emma + PRP_INTRSTATUS);
12582066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
12592066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	return IRQ_HANDLED;
12602066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach}
12612066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
12622066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic int __devinit mx27_camera_emma_init(struct mx2_camera_dev *pcdev)
12632066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{
12642066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct resource *res_emma = pcdev->res_emma;
12652066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	int err = 0;
12662066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
12672066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (!request_mem_region(res_emma->start, resource_size(res_emma),
12682066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach				MX2_CAM_DRV_NAME)) {
12692066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		err = -EBUSY;
12702066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		goto out;
12712066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	}
12722066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
12732066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	pcdev->base_emma = ioremap(res_emma->start, resource_size(res_emma));
12742066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (!pcdev->base_emma) {
12752066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		err = -ENOMEM;
12762066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		goto exit_release;
12772066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	}
12782066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
12792066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	err = request_irq(pcdev->irq_emma, mx27_camera_emma_irq, 0,
12802066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			MX2_CAM_DRV_NAME, pcdev);
12812066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (err) {
12822066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		dev_err(pcdev->dev, "Camera EMMA interrupt register failed \n");
12832066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		goto exit_iounmap;
12842066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	}
12852066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
12862066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	pcdev->clk_emma = clk_get(NULL, "emma");
12872066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (IS_ERR(pcdev->clk_emma)) {
12882066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		err = PTR_ERR(pcdev->clk_emma);
12892066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		goto exit_free_irq;
12902066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	}
12912066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
12922066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	clk_enable(pcdev->clk_emma);
12932066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
12942066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	err = mx27_camera_emma_prp_reset(pcdev);
12952066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (err)
12962066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		goto exit_clk_emma_put;
12972066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
12982066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	return err;
12992066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
13002066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachexit_clk_emma_put:
13012066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	clk_disable(pcdev->clk_emma);
13022066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	clk_put(pcdev->clk_emma);
13032066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachexit_free_irq:
13042066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	free_irq(pcdev->irq_emma, pcdev);
13052066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachexit_iounmap:
13062066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	iounmap(pcdev->base_emma);
13072066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachexit_release:
13082066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	release_mem_region(res_emma->start, resource_size(res_emma));
13092066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachout:
13102066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	return err;
13112066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach}
13122066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
13132066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic int __devinit mx2_camera_probe(struct platform_device *pdev)
13142066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{
13152066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct mx2_camera_dev *pcdev;
13162066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct resource *res_csi, *res_emma;
13172066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	void __iomem *base_csi;
13182066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	int irq_csi, irq_emma;
13192066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	irq_handler_t mx2_cam_irq_handler = cpu_is_mx25() ? mx25_camera_irq
13202066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		: mx27_camera_irq;
13212066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	int err = 0;
13222066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
13232066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	dev_dbg(&pdev->dev, "initialising\n");
13242066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
13252066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	res_csi = platform_get_resource(pdev, IORESOURCE_MEM, 0);
13262066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	irq_csi = platform_get_irq(pdev, 0);
13272066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (res_csi == NULL || irq_csi < 0) {
13282066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		dev_err(&pdev->dev, "Missing platform resources data\n");
13292066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		err = -ENODEV;
13302066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		goto exit;
13312066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	}
13322066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
13332066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	pcdev = kzalloc(sizeof(*pcdev), GFP_KERNEL);
13342066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (!pcdev) {
13352066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		dev_err(&pdev->dev, "Could not allocate pcdev\n");
13362066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		err = -ENOMEM;
13372066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		goto exit;
13382066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	}
13392066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
13402066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	pcdev->clk_csi = clk_get(&pdev->dev, NULL);
13412066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (IS_ERR(pcdev->clk_csi)) {
13422066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		err = PTR_ERR(pcdev->clk_csi);
13432066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		goto exit_kfree;
13442066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	}
13452066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
13462066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	dev_dbg(&pdev->dev, "Camera clock frequency: %ld\n",
13472066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			clk_get_rate(pcdev->clk_csi));
13482066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
13492066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	/* Initialize DMA */
13502066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#ifdef CONFIG_MACH_MX27
13512066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (cpu_is_mx27()) {
13522066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		err = mx27_camera_dma_init(pdev, pcdev);
13532066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		if (err)
13542066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			goto exit_clk_put;
13552066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	}
13562066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#endif /* CONFIG_MACH_MX27 */
13572066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
13582066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	pcdev->res_csi = res_csi;
13592066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	pcdev->pdata = pdev->dev.platform_data;
13602066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (pcdev->pdata) {
13612066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		long rate;
13622066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
13632066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		pcdev->platform_flags = pcdev->pdata->flags;
13642066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
13652066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		rate = clk_round_rate(pcdev->clk_csi, pcdev->pdata->clk * 2);
13662066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		if (rate <= 0) {
13672066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			err = -ENODEV;
13682066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			goto exit_dma_free;
13692066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		}
13702066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		err = clk_set_rate(pcdev->clk_csi, rate);
13712066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		if (err < 0)
13722066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			goto exit_dma_free;
13732066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	}
13742066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
13752066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	INIT_LIST_HEAD(&pcdev->capture);
13762066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	INIT_LIST_HEAD(&pcdev->active_bufs);
13772066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	spin_lock_init(&pcdev->lock);
13782066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
13792066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	/*
13802066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	 * Request the regions.
13812066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	 */
13822066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (!request_mem_region(res_csi->start, resource_size(res_csi),
13832066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach				MX2_CAM_DRV_NAME)) {
13842066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		err = -EBUSY;
13852066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		goto exit_dma_free;
13862066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	}
13872066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
13882066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	base_csi = ioremap(res_csi->start, resource_size(res_csi));
13892066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (!base_csi) {
13902066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		err = -ENOMEM;
13912066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		goto exit_release;
13922066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	}
13932066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	pcdev->irq_csi = irq_csi;
13942066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	pcdev->base_csi = base_csi;
13952066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	pcdev->base_dma = res_csi->start;
13962066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	pcdev->dev = &pdev->dev;
13972066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
13982066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	err = request_irq(pcdev->irq_csi, mx2_cam_irq_handler, 0,
13992066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			MX2_CAM_DRV_NAME, pcdev);
14002066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (err) {
14012066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		dev_err(pcdev->dev, "Camera interrupt register failed \n");
14022066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		goto exit_iounmap;
14032066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	}
14042066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
14052066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (cpu_is_mx27()) {
14062066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		/* EMMA support */
14072066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		res_emma = platform_get_resource(pdev, IORESOURCE_MEM, 1);
14082066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		irq_emma = platform_get_irq(pdev, 1);
14092066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
14102066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		if (res_emma && irq_emma >= 0) {
14112066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			dev_info(&pdev->dev, "Using EMMA\n");
14122066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			pcdev->use_emma = 1;
14132066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			pcdev->res_emma = res_emma;
14142066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			pcdev->irq_emma = irq_emma;
14152066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			if (mx27_camera_emma_init(pcdev))
14162066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach				goto exit_free_irq;
14172066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		}
14182066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	}
14192066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
14202066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	pcdev->soc_host.drv_name	= MX2_CAM_DRV_NAME,
14212066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	pcdev->soc_host.ops		= &mx2_soc_camera_host_ops,
14222066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	pcdev->soc_host.priv		= pcdev;
14232066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	pcdev->soc_host.v4l2_dev.dev	= &pdev->dev;
14242066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	pcdev->soc_host.nr		= pdev->id;
14252066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	err = soc_camera_host_register(&pcdev->soc_host);
14262066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (err)
14272066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		goto exit_free_emma;
14282066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
14292066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	return 0;
14302066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
14312066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachexit_free_emma:
14322066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (mx27_camera_emma(pcdev)) {
14332066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		free_irq(pcdev->irq_emma, pcdev);
14342066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		clk_disable(pcdev->clk_emma);
14352066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		clk_put(pcdev->clk_emma);
14362066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		iounmap(pcdev->base_emma);
14372066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		release_mem_region(res_emma->start, resource_size(res_emma));
14382066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	}
14392066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachexit_free_irq:
14402066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	free_irq(pcdev->irq_csi, pcdev);
14412066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachexit_iounmap:
14422066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	iounmap(base_csi);
14432066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachexit_release:
14442066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	release_mem_region(res_csi->start, resource_size(res_csi));
14452066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachexit_dma_free:
14462066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#ifdef CONFIG_MACH_MX27
14472066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (cpu_is_mx27())
14482066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		imx_dma_free(pcdev->dma);
14492066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachexit_clk_put:
14502066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	clk_put(pcdev->clk_csi);
14512066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#endif /* CONFIG_MACH_MX27 */
14522066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachexit_kfree:
14532066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	kfree(pcdev);
14542066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachexit:
14552066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	return err;
14562066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach}
14572066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
14582066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic int __devexit mx2_camera_remove(struct platform_device *pdev)
14592066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{
14602066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev);
14612066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct mx2_camera_dev *pcdev = container_of(soc_host,
14622066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach			struct mx2_camera_dev, soc_host);
14632066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	struct resource *res;
14642066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
14652066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	clk_put(pcdev->clk_csi);
14662066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#ifdef CONFIG_MACH_MX27
14672066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (cpu_is_mx27())
14682066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		imx_dma_free(pcdev->dma);
14692066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#endif /* CONFIG_MACH_MX27 */
14702066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	free_irq(pcdev->irq_csi, pcdev);
14712066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (mx27_camera_emma(pcdev))
14722066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		free_irq(pcdev->irq_emma, pcdev);
14732066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
14742066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	soc_camera_host_unregister(&pcdev->soc_host);
14752066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
14762066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	iounmap(pcdev->base_csi);
14772066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
14782066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	if (mx27_camera_emma(pcdev)) {
14792066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		clk_disable(pcdev->clk_emma);
14802066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		clk_put(pcdev->clk_emma);
14812066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		iounmap(pcdev->base_emma);
14822066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		res = pcdev->res_emma;
14832066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		release_mem_region(res->start, resource_size(res));
14842066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	}
14852066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
14862066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	res = pcdev->res_csi;
14872066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	release_mem_region(res->start, resource_size(res));
14882066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
14892066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	kfree(pcdev);
14902066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
14912066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	dev_info(&pdev->dev, "MX2 Camera driver unloaded\n");
14922066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
14932066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	return 0;
14942066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach}
14952066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
14962066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic struct platform_driver mx2_camera_driver = {
14972066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	.driver 	= {
14982066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach		.name	= MX2_CAM_DRV_NAME,
14992066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	},
15002066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	.remove		= __devexit_p(mx2_camera_remove),
15012066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach};
15022066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
15032066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
15042066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic int __init mx2_camera_init(void)
15052066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{
15062066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	return platform_driver_probe(&mx2_camera_driver, &mx2_camera_probe);
15072066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach}
15082066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
15092066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic void __exit mx2_camera_exit(void)
15102066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{
15112066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach	return platform_driver_unregister(&mx2_camera_driver);
15122066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach}
15132066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
15142066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachmodule_init(mx2_camera_init);
15152066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachmodule_exit(mx2_camera_exit);
15162066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach
15172066930de6296ef7470de11eaa9b8bc9129721e8Baruch SiachMODULE_DESCRIPTION("i.MX27/i.MX25 SoC Camera Host driver");
15182066930de6296ef7470de11eaa9b8bc9129721e8Baruch SiachMODULE_AUTHOR("Sascha Hauer <sha@pengutronix.de>");
15192066930de6296ef7470de11eaa9b8bc9129721e8Baruch SiachMODULE_LICENSE("GPL");
1520