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