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/device.h> 272066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#include <linux/platform_device.h> 282066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#include <linux/mutex.h> 292066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#include <linux/clk.h> 302066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 312066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#include <media/v4l2-common.h> 322066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#include <media/v4l2-dev.h> 336b101926f98b54549128db4d34f4a73b5f03feccSascha Hauer#include <media/videobuf-core.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" 4964dc3c1a906467d90c24913b0b38dd13d9378f4fMauro Carvalho Chehab#define MX2_CAM_VERSION "0.0.6" 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 213f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martinstruct mx2_prp_cfg { 214f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin int channel; 215f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin u32 in_fmt; 216f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin u32 out_fmt; 217f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin u32 src_pixel; 218f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin u32 ch1_pixel; 219f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin u32 irq_flags; 220f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin}; 221f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin 222f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin/* prp configuration for a client-host fmt pair */ 223f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martinstruct mx2_fmt_cfg { 224f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin enum v4l2_mbus_pixelcode in_fmt; 225f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin u32 out_fmt; 226f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin struct mx2_prp_cfg cfg; 227f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin}; 228f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin 2292066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstruct mx2_camera_dev { 2302066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct device *dev; 2312066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct soc_camera_host soc_host; 2322066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct soc_camera_device *icd; 2332066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct clk *clk_csi, *clk_emma; 2342066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 2352066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach unsigned int irq_csi, irq_emma; 2362066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach void __iomem *base_csi, *base_emma; 2372066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach unsigned long base_dma; 2382066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 2392066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct mx2_camera_platform_data *pdata; 2402066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct resource *res_csi, *res_emma; 2412066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach unsigned long platform_flags; 2422066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 2432066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct list_head capture; 2442066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct list_head active_bufs; 2452066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 2462066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach spinlock_t lock; 2472066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 2482066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach int dma; 2492066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct mx2_buffer *active; 2502066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct mx2_buffer *fb1_active; 2512066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct mx2_buffer *fb2_active; 2522066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 2532066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach int use_emma; 2542066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 2552066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach u32 csicr1; 2562066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 25779d3c2c2395a89a70d25f0c77c11afc87efab89bBaruch Siach void *discard_buffer; 2582066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach dma_addr_t discard_buffer_dma; 2592066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach size_t discard_size; 260f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin struct mx2_fmt_cfg *emma_prp; 261ccd1a499c1675fef5d2a138617507add63cb81dbJavier Martin u32 frame_count; 2622066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach}; 2632066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 2642066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach/* buffer for one video frame */ 2652066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstruct mx2_buffer { 2662066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach /* common v4l buffer stuff -- must be first */ 2672066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct videobuf_buffer vb; 2682066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 2692066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach enum v4l2_mbus_pixelcode code; 2702066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 2712066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach int bufnum; 2722066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach}; 2732066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 274f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martinstatic struct mx2_fmt_cfg mx27_emma_prp_table[] = { 275f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin /* 276f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin * This is a generic configuration which is valid for most 277f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin * prp input-output format combinations. 278f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin * We set the incomming and outgoing pixelformat to a 279f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin * 16 Bit wide format and adjust the bytesperline 280f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin * accordingly. With this configuration the inputdata 281f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin * will not be changed by the emma and could be any type 282f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin * of 16 Bit Pixelformat. 283f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin */ 284f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin { 285f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin .in_fmt = 0, 286f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin .out_fmt = 0, 287f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin .cfg = { 288f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin .channel = 1, 289f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin .in_fmt = PRP_CNTL_DATA_IN_RGB16, 290f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin .out_fmt = PRP_CNTL_CH1_OUT_RGB16, 291f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin .src_pixel = 0x2ca00565, /* RGB565 */ 292f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin .ch1_pixel = 0x2ca00565, /* RGB565 */ 293f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin .irq_flags = PRP_INTR_RDERR | PRP_INTR_CH1WERR | 294f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin PRP_INTR_CH1FC | PRP_INTR_LBOVF, 295f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin } 296f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin }, 297f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin { 298f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin .in_fmt = V4L2_MBUS_FMT_YUYV8_2X8, 299f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin .out_fmt = V4L2_PIX_FMT_YUV420, 300f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin .cfg = { 301f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin .channel = 2, 302f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin .in_fmt = PRP_CNTL_DATA_IN_YUV422, 303f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin .out_fmt = PRP_CNTL_CH2_OUT_YUV420, 304f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin .src_pixel = 0x22000888, /* YUV422 (YUYV) */ 305f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin .irq_flags = PRP_INTR_RDERR | PRP_INTR_CH2WERR | 306f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin PRP_INTR_CH2FC | PRP_INTR_LBOVF | 307f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin PRP_INTR_CH2OVF, 308f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin } 309f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin }, 310f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin}; 311f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin 312f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martinstatic struct mx2_fmt_cfg *mx27_emma_prp_get_format( 313f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin enum v4l2_mbus_pixelcode in_fmt, 314f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin u32 out_fmt) 315f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin{ 316f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin int i; 317f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin 318f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin for (i = 1; i < ARRAY_SIZE(mx27_emma_prp_table); i++) 319f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin if ((mx27_emma_prp_table[i].in_fmt == in_fmt) && 320f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin (mx27_emma_prp_table[i].out_fmt == out_fmt)) { 321f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin return &mx27_emma_prp_table[i]; 322f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin } 323f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin /* If no match return the most generic configuration */ 324f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin return &mx27_emma_prp_table[0]; 325f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin}; 326f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin 3272066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic void mx2_camera_deactivate(struct mx2_camera_dev *pcdev) 3282066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{ 3292066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach unsigned long flags; 3302066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 3312066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach clk_disable(pcdev->clk_csi); 3322066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach writel(0, pcdev->base_csi + CSICR1); 3332066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (mx27_camera_emma(pcdev)) { 3342066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach writel(0, pcdev->base_emma + PRP_CNTL); 3352066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } else if (cpu_is_mx25()) { 3362066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach spin_lock_irqsave(&pcdev->lock, flags); 3372066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->fb1_active = NULL; 3382066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->fb2_active = NULL; 3392066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach writel(0, pcdev->base_csi + CSIDMASA_FB1); 3402066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach writel(0, pcdev->base_csi + CSIDMASA_FB2); 3412066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach spin_unlock_irqrestore(&pcdev->lock, flags); 3422066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 3432066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach} 3442066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 3452066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach/* 3462066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach * The following two functions absolutely depend on the fact, that 3472066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach * there can be only one camera on mx2 camera sensor interface 3482066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach */ 3492066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic int mx2_camera_add_device(struct soc_camera_device *icd) 3502066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{ 3517dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski struct soc_camera_host *ici = to_soc_camera_host(icd->parent); 3522066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct mx2_camera_dev *pcdev = ici->priv; 3532066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach int ret; 3542066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach u32 csicr1; 3552066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 3562066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (pcdev->icd) 3572066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach return -EBUSY; 3582066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 3592066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach ret = clk_enable(pcdev->clk_csi); 3602066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (ret < 0) 3612066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach return ret; 3622066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 3632066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach csicr1 = CSICR1_MCLKEN; 3642066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 3652066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (mx27_camera_emma(pcdev)) { 3662066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach csicr1 |= CSICR1_PRP_IF_EN | CSICR1_FCC | 3672066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach CSICR1_RXFF_LEVEL(0); 3682066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } else if (cpu_is_mx27()) 3692066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach csicr1 |= CSICR1_SOF_INTEN | CSICR1_RXFF_LEVEL(2); 3702066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 3712066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->csicr1 = csicr1; 3722066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach writel(pcdev->csicr1, pcdev->base_csi + CSICR1); 3732066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 3742066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->icd = icd; 375ccd1a499c1675fef5d2a138617507add63cb81dbJavier Martin pcdev->frame_count = 0; 3762066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 3777dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski dev_info(icd->parent, "Camera driver attached to camera %d\n", 3782066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach icd->devnum); 3792066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 3802066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach return 0; 3812066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach} 3822066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 3832066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic void mx2_camera_remove_device(struct soc_camera_device *icd) 3842066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{ 3857dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski struct soc_camera_host *ici = to_soc_camera_host(icd->parent); 3862066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct mx2_camera_dev *pcdev = ici->priv; 3872066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 3882066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach BUG_ON(icd != pcdev->icd); 3892066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 3907dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski dev_info(icd->parent, "Camera driver detached from camera %d\n", 3912066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach icd->devnum); 3922066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 3932066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach mx2_camera_deactivate(pcdev); 3942066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 3952066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (pcdev->discard_buffer) { 3962066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach dma_free_coherent(ici->v4l2_dev.dev, pcdev->discard_size, 3972066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->discard_buffer, 3982066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->discard_buffer_dma); 3992066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->discard_buffer = NULL; 4002066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 4012066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 4022066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->icd = NULL; 4032066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach} 4042066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 4052066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#ifdef CONFIG_MACH_MX27 4062066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic void mx27_camera_dma_enable(struct mx2_camera_dev *pcdev) 4072066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{ 4082066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach u32 tmp; 4092066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 4102066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach imx_dma_enable(pcdev->dma); 4112066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 4122066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach tmp = readl(pcdev->base_csi + CSICR1); 4132066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach tmp |= CSICR1_RF_OR_INTEN; 4142066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach writel(tmp, pcdev->base_csi + CSICR1); 4152066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach} 4162066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 4172066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic irqreturn_t mx27_camera_irq(int irq_csi, void *data) 4182066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{ 4192066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct mx2_camera_dev *pcdev = data; 4202066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach u32 status = readl(pcdev->base_csi + CSISR); 4212066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 4222066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (status & CSISR_SOF_INT && pcdev->active) { 4232066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach u32 tmp; 4242066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 4252066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach tmp = readl(pcdev->base_csi + CSICR1); 4262066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach writel(tmp | CSICR1_CLR_RXFIFO, pcdev->base_csi + CSICR1); 4272066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach mx27_camera_dma_enable(pcdev); 4282066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 4292066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 4302066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach writel(CSISR_SOF_INT | CSISR_RFF_OR_INT, pcdev->base_csi + CSISR); 4312066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 4322066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach return IRQ_HANDLED; 4332066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach} 4342066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#else 4352066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic irqreturn_t mx27_camera_irq(int irq_csi, void *data) 4362066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{ 4372066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach return IRQ_NONE; 4382066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach} 4392066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#endif /* CONFIG_MACH_MX27 */ 4402066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 4412066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic void mx25_camera_frame_done(struct mx2_camera_dev *pcdev, int fb, 4422066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach int state) 4432066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{ 4442066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct videobuf_buffer *vb; 4452066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct mx2_buffer *buf; 4462066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct mx2_buffer **fb_active = fb == 1 ? &pcdev->fb1_active : 4472066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach &pcdev->fb2_active; 4482066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach u32 fb_reg = fb == 1 ? CSIDMASA_FB1 : CSIDMASA_FB2; 4492066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach unsigned long flags; 4502066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 4512066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach spin_lock_irqsave(&pcdev->lock, flags); 4522066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 4535384a12b23160e11ff949a94172051476d308b66Baruch Siach if (*fb_active == NULL) 4545384a12b23160e11ff949a94172051476d308b66Baruch Siach goto out; 4555384a12b23160e11ff949a94172051476d308b66Baruch Siach 4562066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach vb = &(*fb_active)->vb; 4572066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, 4582066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach vb, vb->baddr, vb->bsize); 4592066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 4602066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach vb->state = state; 4612066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach do_gettimeofday(&vb->ts); 4622066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach vb->field_count++; 4632066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 4642066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach wake_up(&vb->done); 4652066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 4662066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (list_empty(&pcdev->capture)) { 4672066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach buf = NULL; 4682066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach writel(0, pcdev->base_csi + fb_reg); 4692066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } else { 4702066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach buf = list_entry(pcdev->capture.next, struct mx2_buffer, 4712066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach vb.queue); 4722066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach vb = &buf->vb; 4732066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach list_del(&vb->queue); 4742066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach vb->state = VIDEOBUF_ACTIVE; 4752066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach writel(videobuf_to_dma_contig(vb), pcdev->base_csi + fb_reg); 4762066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 4772066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 4782066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach *fb_active = buf; 4792066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 4805384a12b23160e11ff949a94172051476d308b66Baruch Siachout: 4812066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach spin_unlock_irqrestore(&pcdev->lock, flags); 4822066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach} 4832066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 4842066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic irqreturn_t mx25_camera_irq(int irq_csi, void *data) 4852066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{ 4862066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct mx2_camera_dev *pcdev = data; 4872066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach u32 status = readl(pcdev->base_csi + CSISR); 4882066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 4892066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (status & CSISR_DMA_TSF_FB1_INT) 4902066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach mx25_camera_frame_done(pcdev, 1, VIDEOBUF_DONE); 4912066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach else if (status & CSISR_DMA_TSF_FB2_INT) 4922066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach mx25_camera_frame_done(pcdev, 2, VIDEOBUF_DONE); 4932066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 4942066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach /* FIXME: handle CSISR_RFF_OR_INT */ 4952066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 4962066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach writel(status, pcdev->base_csi + CSISR); 4972066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 4982066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach return IRQ_HANDLED; 4992066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach} 5002066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 5012066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach/* 5022066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach * Videobuf operations 5032066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach */ 5042066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic int mx2_videobuf_setup(struct videobuf_queue *vq, unsigned int *count, 5052066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach unsigned int *size) 5062066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{ 5072066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct soc_camera_device *icd = vq->priv_data; 5082066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, 5092066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach icd->current_fmt->host_fmt); 5102066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 5117dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski dev_dbg(icd->parent, "count=%d, size=%d\n", *count, *size); 5122066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 5132066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (bytes_per_line < 0) 5142066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach return bytes_per_line; 5152066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 5162066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach *size = bytes_per_line * icd->user_height; 5172066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 5182066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (0 == *count) 5192066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach *count = 32; 5202066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (*size * *count > MAX_VIDEO_MEM * 1024 * 1024) 5212066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach *count = (MAX_VIDEO_MEM * 1024 * 1024) / *size; 5222066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 5232066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach return 0; 5242066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach} 5252066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 5262066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic void free_buffer(struct videobuf_queue *vq, struct mx2_buffer *buf) 5272066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{ 5282066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct soc_camera_device *icd = vq->priv_data; 5292066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct videobuf_buffer *vb = &buf->vb; 5302066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 5317dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, 5322066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach vb, vb->baddr, vb->bsize); 5332066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 5342066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach /* 5352066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach * This waits until this buffer is out of danger, i.e., until it is no 53688bfd0bd7f8343c3c2ff65fe4d3fc3aff6ecca7cBaruch Siach * longer in state VIDEOBUF_QUEUED or VIDEOBUF_ACTIVE 5372066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach */ 5380e0809a58869e3e422985f868ad5e0da1fc0ba85Hans Verkuil videobuf_waiton(vq, vb, 0, 0); 5392066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 5402066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach videobuf_dma_contig_free(vq, vb); 5417dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski dev_dbg(icd->parent, "%s freed\n", __func__); 5422066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 5432066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach vb->state = VIDEOBUF_NEEDS_INIT; 5442066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach} 5452066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 5462066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic int mx2_videobuf_prepare(struct videobuf_queue *vq, 5472066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct videobuf_buffer *vb, enum v4l2_field field) 5482066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{ 5492066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct soc_camera_device *icd = vq->priv_data; 5502066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct mx2_buffer *buf = container_of(vb, struct mx2_buffer, vb); 5512066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width, 5522066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach icd->current_fmt->host_fmt); 5532066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach int ret = 0; 5542066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 5557dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, 5562066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach vb, vb->baddr, vb->bsize); 5572066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 5582066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (bytes_per_line < 0) 5592066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach return bytes_per_line; 5602066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 5612066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#ifdef DEBUG 5622066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach /* 5632066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach * This can be useful if you want to see if we actually fill 5642066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach * the buffer with something 5652066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach */ 5662066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach memset((void *)vb->baddr, 0xaa, vb->bsize); 5672066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#endif 5682066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 5692066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (buf->code != icd->current_fmt->code || 5702066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach vb->width != icd->user_width || 5712066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach vb->height != icd->user_height || 5722066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach vb->field != field) { 5732066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach buf->code = icd->current_fmt->code; 5742066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach vb->width = icd->user_width; 5752066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach vb->height = icd->user_height; 5762066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach vb->field = field; 5772066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach vb->state = VIDEOBUF_NEEDS_INIT; 5782066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 5792066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 5802066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach vb->size = bytes_per_line * vb->height; 5812066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (vb->baddr && vb->bsize < vb->size) { 5822066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach ret = -EINVAL; 5832066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach goto out; 5842066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 5852066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 5862066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (vb->state == VIDEOBUF_NEEDS_INIT) { 5872066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach ret = videobuf_iolock(vq, vb, NULL); 5882066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (ret) 5892066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach goto fail; 5902066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 5912066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach vb->state = VIDEOBUF_PREPARED; 5922066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 5932066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 5942066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach return 0; 5952066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 5962066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachfail: 5972066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach free_buffer(vq, buf); 5982066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachout: 5992066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach return ret; 6002066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach} 6012066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 6022066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic void mx2_videobuf_queue(struct videobuf_queue *vq, 6032066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct videobuf_buffer *vb) 6042066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{ 6052066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct soc_camera_device *icd = vq->priv_data; 6062066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct soc_camera_host *ici = 6077dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski to_soc_camera_host(icd->parent); 6082066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct mx2_camera_dev *pcdev = ici->priv; 6092066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct mx2_buffer *buf = container_of(vb, struct mx2_buffer, vb); 6102066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach unsigned long flags; 6112066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 6127dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, 6132066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach vb, vb->baddr, vb->bsize); 6142066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 6152066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach spin_lock_irqsave(&pcdev->lock, flags); 6162066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 6172066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach vb->state = VIDEOBUF_QUEUED; 6182066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach list_add_tail(&vb->queue, &pcdev->capture); 6192066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 6202066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (mx27_camera_emma(pcdev)) { 6212066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach goto out; 6222066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#ifdef CONFIG_MACH_MX27 6232066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } else if (cpu_is_mx27()) { 6242066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach int ret; 6252066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 6262066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (pcdev->active == NULL) { 6272066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach ret = imx_dma_setup_single(pcdev->dma, 6282066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach videobuf_to_dma_contig(vb), vb->size, 6292066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach (u32)pcdev->base_dma + 0x10, 6302066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach DMA_MODE_READ); 6312066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (ret) { 6322066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach vb->state = VIDEOBUF_ERROR; 6332066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach wake_up(&vb->done); 6342066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach goto out; 6352066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 6362066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 6372066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach vb->state = VIDEOBUF_ACTIVE; 6382066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->active = buf; 6392066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 6402066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#endif 6412066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } else { /* cpu_is_mx25() */ 6422066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach u32 csicr3, dma_inten = 0; 6432066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 6442066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (pcdev->fb1_active == NULL) { 6452066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach writel(videobuf_to_dma_contig(vb), 6462066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->base_csi + CSIDMASA_FB1); 6472066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->fb1_active = buf; 6482066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach dma_inten = CSICR1_FB1_DMA_INTEN; 6492066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } else if (pcdev->fb2_active == NULL) { 6502066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach writel(videobuf_to_dma_contig(vb), 6512066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->base_csi + CSIDMASA_FB2); 6522066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->fb2_active = buf; 6532066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach dma_inten = CSICR1_FB2_DMA_INTEN; 6542066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 6552066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 6562066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (dma_inten) { 6572066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach list_del(&vb->queue); 6582066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach vb->state = VIDEOBUF_ACTIVE; 6592066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 6602066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach csicr3 = readl(pcdev->base_csi + CSICR3); 6612066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 6622066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach /* Reflash DMA */ 6632066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach writel(csicr3 | CSICR3_DMA_REFLASH_RFF, 6642066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->base_csi + CSICR3); 6652066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 6662066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach /* clear & enable interrupts */ 6672066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach writel(dma_inten, pcdev->base_csi + CSISR); 6682066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->csicr1 |= dma_inten; 6692066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach writel(pcdev->csicr1, pcdev->base_csi + CSICR1); 6702066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 6712066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach /* enable DMA */ 6722066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach csicr3 |= CSICR3_DMA_REQ_EN_RFF | CSICR3_RXFF_LEVEL(1); 6732066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach writel(csicr3, pcdev->base_csi + CSICR3); 6742066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 6752066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 6762066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 6772066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachout: 6782066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach spin_unlock_irqrestore(&pcdev->lock, flags); 6792066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach} 6802066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 6812066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic void mx2_videobuf_release(struct videobuf_queue *vq, 6822066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct videobuf_buffer *vb) 6832066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{ 6842066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct soc_camera_device *icd = vq->priv_data; 6857dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski struct soc_camera_host *ici = to_soc_camera_host(icd->parent); 6862066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct mx2_camera_dev *pcdev = ici->priv; 6872066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct mx2_buffer *buf = container_of(vb, struct mx2_buffer, vb); 6882066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach unsigned long flags; 6892066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 6902066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#ifdef DEBUG 6917dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__, 6922066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach vb, vb->baddr, vb->bsize); 6932066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 6942066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach switch (vb->state) { 6952066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach case VIDEOBUF_ACTIVE: 6967dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski dev_info(icd->parent, "%s (active)\n", __func__); 6972066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach break; 6982066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach case VIDEOBUF_QUEUED: 6997dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski dev_info(icd->parent, "%s (queued)\n", __func__); 7002066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach break; 7012066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach case VIDEOBUF_PREPARED: 7027dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski dev_info(icd->parent, "%s (prepared)\n", __func__); 7032066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach break; 7042066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach default: 7057dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski dev_info(icd->parent, "%s (unknown) %d\n", __func__, 7062066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach vb->state); 7072066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach break; 7082066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 7092066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#endif 7102066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 7112066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach /* 7122066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach * Terminate only queued but inactive buffers. Active buffers are 7132066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach * released when they become inactive after videobuf_waiton(). 7142066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach * 7157c6b73197062180d51e9871982b083a651838992Baruch Siach * FIXME: implement forced termination of active buffers for mx27 and 7167c6b73197062180d51e9871982b083a651838992Baruch Siach * mx27 eMMA, so that the user won't get stuck in an uninterruptible 7177c6b73197062180d51e9871982b083a651838992Baruch Siach * state. This requires a specific handling for each of the these DMA 7187c6b73197062180d51e9871982b083a651838992Baruch Siach * types. 7192066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach */ 7202066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach spin_lock_irqsave(&pcdev->lock, flags); 7212066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (vb->state == VIDEOBUF_QUEUED) { 7222066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach list_del(&vb->queue); 7232066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach vb->state = VIDEOBUF_ERROR; 7247c6b73197062180d51e9871982b083a651838992Baruch Siach } else if (cpu_is_mx25() && vb->state == VIDEOBUF_ACTIVE) { 7257c6b73197062180d51e9871982b083a651838992Baruch Siach if (pcdev->fb1_active == buf) { 7267c6b73197062180d51e9871982b083a651838992Baruch Siach pcdev->csicr1 &= ~CSICR1_FB1_DMA_INTEN; 7277c6b73197062180d51e9871982b083a651838992Baruch Siach writel(0, pcdev->base_csi + CSIDMASA_FB1); 7287c6b73197062180d51e9871982b083a651838992Baruch Siach pcdev->fb1_active = NULL; 7297c6b73197062180d51e9871982b083a651838992Baruch Siach } else if (pcdev->fb2_active == buf) { 7307c6b73197062180d51e9871982b083a651838992Baruch Siach pcdev->csicr1 &= ~CSICR1_FB2_DMA_INTEN; 7317c6b73197062180d51e9871982b083a651838992Baruch Siach writel(0, pcdev->base_csi + CSIDMASA_FB2); 7327c6b73197062180d51e9871982b083a651838992Baruch Siach pcdev->fb2_active = NULL; 7337c6b73197062180d51e9871982b083a651838992Baruch Siach } 7347c6b73197062180d51e9871982b083a651838992Baruch Siach writel(pcdev->csicr1, pcdev->base_csi + CSICR1); 7357c6b73197062180d51e9871982b083a651838992Baruch Siach vb->state = VIDEOBUF_ERROR; 7362066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 7372066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach spin_unlock_irqrestore(&pcdev->lock, flags); 7382066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 7392066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach free_buffer(vq, buf); 7402066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach} 7412066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 7422066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic struct videobuf_queue_ops mx2_videobuf_ops = { 7432066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach .buf_setup = mx2_videobuf_setup, 7442066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach .buf_prepare = mx2_videobuf_prepare, 7452066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach .buf_queue = mx2_videobuf_queue, 7462066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach .buf_release = mx2_videobuf_release, 7472066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach}; 7482066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 7492066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic void mx2_camera_init_videobuf(struct videobuf_queue *q, 7502066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct soc_camera_device *icd) 7512066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{ 7527dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski struct soc_camera_host *ici = to_soc_camera_host(icd->parent); 7532066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct mx2_camera_dev *pcdev = ici->priv; 7542066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 7552066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach videobuf_queue_dma_contig_init(q, &mx2_videobuf_ops, pcdev->dev, 7562066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach &pcdev->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE, 757b6a633c18ba83c0c8e96759a31d356bfb77e2b5fGuennadi Liakhovetski V4L2_FIELD_NONE, sizeof(struct mx2_buffer), 758b6a633c18ba83c0c8e96759a31d356bfb77e2b5fGuennadi Liakhovetski icd, &icd->video_lock); 7592066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach} 7602066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 761db592a24656ec1028728eb4eccc450b925bea268Guennadi Liakhovetski#define MX2_BUS_FLAGS (V4L2_MBUS_MASTER | \ 762db592a24656ec1028728eb4eccc450b925bea268Guennadi Liakhovetski V4L2_MBUS_VSYNC_ACTIVE_HIGH | \ 763db592a24656ec1028728eb4eccc450b925bea268Guennadi Liakhovetski V4L2_MBUS_VSYNC_ACTIVE_LOW | \ 764db592a24656ec1028728eb4eccc450b925bea268Guennadi Liakhovetski V4L2_MBUS_HSYNC_ACTIVE_HIGH | \ 765db592a24656ec1028728eb4eccc450b925bea268Guennadi Liakhovetski V4L2_MBUS_HSYNC_ACTIVE_LOW | \ 766db592a24656ec1028728eb4eccc450b925bea268Guennadi Liakhovetski V4L2_MBUS_PCLK_SAMPLE_RISING | \ 767db592a24656ec1028728eb4eccc450b925bea268Guennadi Liakhovetski V4L2_MBUS_PCLK_SAMPLE_FALLING | \ 768db592a24656ec1028728eb4eccc450b925bea268Guennadi Liakhovetski V4L2_MBUS_DATA_ACTIVE_HIGH | \ 769db592a24656ec1028728eb4eccc450b925bea268Guennadi Liakhovetski V4L2_MBUS_DATA_ACTIVE_LOW) 7702066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 7712066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic int mx27_camera_emma_prp_reset(struct mx2_camera_dev *pcdev) 7722066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{ 7732066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach u32 cntl; 7742066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach int count = 0; 7752066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 7762066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach cntl = readl(pcdev->base_emma + PRP_CNTL); 7772066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach writel(PRP_CNTL_SWRST, pcdev->base_emma + PRP_CNTL); 7782066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach while (count++ < 100) { 7792066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (!(readl(pcdev->base_emma + PRP_CNTL) & PRP_CNTL_SWRST)) 7802066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach return 0; 7812066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach barrier(); 7822066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach udelay(1); 7832066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 7842066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 7852066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach return -ETIMEDOUT; 7862066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach} 7872066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 7882066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic void mx27_camera_emma_buf_init(struct soc_camera_device *icd, 7892066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach int bytesperline) 7902066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{ 7912066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct soc_camera_host *ici = 7927dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski to_soc_camera_host(icd->parent); 7932066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct mx2_camera_dev *pcdev = ici->priv; 794f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin struct mx2_fmt_cfg *prp = pcdev->emma_prp; 795f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin u32 imgsize = pcdev->icd->user_height * pcdev->icd->user_width; 796f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin 797f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin if (prp->cfg.channel == 1) { 798f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin writel(pcdev->discard_buffer_dma, 799f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin pcdev->base_emma + PRP_DEST_RGB1_PTR); 800f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin writel(pcdev->discard_buffer_dma, 801f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin pcdev->base_emma + PRP_DEST_RGB2_PTR); 802f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin 803f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin writel(PRP_CNTL_CH1EN | 804f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin PRP_CNTL_CSIEN | 805f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin prp->cfg.in_fmt | 806f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin prp->cfg.out_fmt | 807f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin PRP_CNTL_CH1_LEN | 808f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin PRP_CNTL_CH1BYP | 809f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin PRP_CNTL_CH1_TSKIP(0) | 810f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin PRP_CNTL_IN_TSKIP(0), 811f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin pcdev->base_emma + PRP_CNTL); 812f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin 813f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin writel((icd->user_width << 16) | icd->user_height, 814f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin pcdev->base_emma + PRP_SRC_FRAME_SIZE); 815f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin writel((icd->user_width << 16) | icd->user_height, 816f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin pcdev->base_emma + PRP_CH1_OUT_IMAGE_SIZE); 817f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin writel(bytesperline, 818f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin pcdev->base_emma + PRP_DEST_CH1_LINE_STRIDE); 819f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin writel(prp->cfg.src_pixel, 820f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin pcdev->base_emma + PRP_SRC_PIXEL_FORMAT_CNTL); 821f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin writel(prp->cfg.ch1_pixel, 822f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin pcdev->base_emma + PRP_CH1_PIXEL_FORMAT_CNTL); 823f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin } else { /* channel 2 */ 824f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin writel(pcdev->discard_buffer_dma, 825f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin pcdev->base_emma + PRP_DEST_Y_PTR); 826f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin writel(pcdev->discard_buffer_dma, 827f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin pcdev->base_emma + PRP_SOURCE_Y_PTR); 828f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin 829f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin if (prp->cfg.out_fmt == PRP_CNTL_CH2_OUT_YUV420) { 830f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin writel(pcdev->discard_buffer_dma + imgsize, 831f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin pcdev->base_emma + PRP_DEST_CB_PTR); 832f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin writel(pcdev->discard_buffer_dma + ((5 * imgsize) / 4), 833f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin pcdev->base_emma + PRP_DEST_CR_PTR); 834f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin writel(pcdev->discard_buffer_dma + imgsize, 835f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin pcdev->base_emma + PRP_SOURCE_CB_PTR); 836f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin writel(pcdev->discard_buffer_dma + ((5 * imgsize) / 4), 837f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin pcdev->base_emma + PRP_SOURCE_CR_PTR); 838f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin } 8392066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 840f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin writel(PRP_CNTL_CH2EN | 8412066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach PRP_CNTL_CSIEN | 842f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin prp->cfg.in_fmt | 843f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin prp->cfg.out_fmt | 844f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin PRP_CNTL_CH2_LEN | 845f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin PRP_CNTL_CH2_TSKIP(0) | 8462066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach PRP_CNTL_IN_TSKIP(0), 8472066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->base_emma + PRP_CNTL); 8482066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 849f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin writel((icd->user_width << 16) | icd->user_height, 8502066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->base_emma + PRP_SRC_FRAME_SIZE); 851f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin 852f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin writel((icd->user_width << 16) | icd->user_height, 853f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin pcdev->base_emma + PRP_CH2_OUT_IMAGE_SIZE); 854f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin 855f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin writel(prp->cfg.src_pixel, 8562066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->base_emma + PRP_SRC_PIXEL_FORMAT_CNTL); 857f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin 858f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin } 8592066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 8602066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach /* Enable interrupts */ 861f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin writel(prp->cfg.irq_flags, pcdev->base_emma + PRP_INTR_CNTL); 8622066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach} 8632066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 8648843d119eaf1a7a87a2cf8c3eadbd1937b16bc27Guennadi Liakhovetskistatic int mx2_camera_set_bus_param(struct soc_camera_device *icd) 8652066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{ 866db592a24656ec1028728eb4eccc450b925bea268Guennadi Liakhovetski struct v4l2_subdev *sd = soc_camera_to_subdev(icd); 867db592a24656ec1028728eb4eccc450b925bea268Guennadi Liakhovetski struct soc_camera_host *ici = to_soc_camera_host(icd->parent); 8682066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct mx2_camera_dev *pcdev = ici->priv; 869db592a24656ec1028728eb4eccc450b925bea268Guennadi Liakhovetski struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,}; 870db592a24656ec1028728eb4eccc450b925bea268Guennadi Liakhovetski unsigned long common_flags; 871db592a24656ec1028728eb4eccc450b925bea268Guennadi Liakhovetski int ret; 8722066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach int bytesperline; 8732066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach u32 csicr1 = pcdev->csicr1; 8742066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 875db592a24656ec1028728eb4eccc450b925bea268Guennadi Liakhovetski ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg); 876db592a24656ec1028728eb4eccc450b925bea268Guennadi Liakhovetski if (!ret) { 877db592a24656ec1028728eb4eccc450b925bea268Guennadi Liakhovetski common_flags = soc_mbus_config_compatible(&cfg, MX2_BUS_FLAGS); 878db592a24656ec1028728eb4eccc450b925bea268Guennadi Liakhovetski if (!common_flags) { 879db592a24656ec1028728eb4eccc450b925bea268Guennadi Liakhovetski dev_warn(icd->parent, 880db592a24656ec1028728eb4eccc450b925bea268Guennadi Liakhovetski "Flags incompatible: camera 0x%x, host 0x%x\n", 881db592a24656ec1028728eb4eccc450b925bea268Guennadi Liakhovetski cfg.flags, MX2_BUS_FLAGS); 882db592a24656ec1028728eb4eccc450b925bea268Guennadi Liakhovetski return -EINVAL; 883db592a24656ec1028728eb4eccc450b925bea268Guennadi Liakhovetski } 884db592a24656ec1028728eb4eccc450b925bea268Guennadi Liakhovetski } else if (ret != -ENOIOCTLCMD) { 885db592a24656ec1028728eb4eccc450b925bea268Guennadi Liakhovetski return ret; 886db592a24656ec1028728eb4eccc450b925bea268Guennadi Liakhovetski } else { 887db592a24656ec1028728eb4eccc450b925bea268Guennadi Liakhovetski common_flags = MX2_BUS_FLAGS; 888db592a24656ec1028728eb4eccc450b925bea268Guennadi Liakhovetski } 8892066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 890db592a24656ec1028728eb4eccc450b925bea268Guennadi Liakhovetski if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) && 891db592a24656ec1028728eb4eccc450b925bea268Guennadi Liakhovetski (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) { 8922066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (pcdev->platform_flags & MX2_CAMERA_HSYNC_HIGH) 893db592a24656ec1028728eb4eccc450b925bea268Guennadi Liakhovetski common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW; 8942066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach else 895db592a24656ec1028728eb4eccc450b925bea268Guennadi Liakhovetski common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH; 8962066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 8972066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 898db592a24656ec1028728eb4eccc450b925bea268Guennadi Liakhovetski if ((common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) && 899db592a24656ec1028728eb4eccc450b925bea268Guennadi Liakhovetski (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)) { 9002066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (pcdev->platform_flags & MX2_CAMERA_PCLK_SAMPLE_RISING) 901db592a24656ec1028728eb4eccc450b925bea268Guennadi Liakhovetski common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_FALLING; 9022066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach else 903db592a24656ec1028728eb4eccc450b925bea268Guennadi Liakhovetski common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_RISING; 9042066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 9052066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 906db592a24656ec1028728eb4eccc450b925bea268Guennadi Liakhovetski cfg.flags = common_flags; 907db592a24656ec1028728eb4eccc450b925bea268Guennadi Liakhovetski ret = v4l2_subdev_call(sd, video, s_mbus_config, &cfg); 908db592a24656ec1028728eb4eccc450b925bea268Guennadi Liakhovetski if (ret < 0 && ret != -ENOIOCTLCMD) { 909db592a24656ec1028728eb4eccc450b925bea268Guennadi Liakhovetski dev_dbg(icd->parent, "camera s_mbus_config(0x%lx) returned %d\n", 910db592a24656ec1028728eb4eccc450b925bea268Guennadi Liakhovetski common_flags, ret); 9112066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach return ret; 912db592a24656ec1028728eb4eccc450b925bea268Guennadi Liakhovetski } 9132066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 914db592a24656ec1028728eb4eccc450b925bea268Guennadi Liakhovetski if (common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) 915d86097e19cef2f13a29fc37db0dad17b99b6d5f8Michael Grzeschik csicr1 |= CSICR1_REDGE; 916db592a24656ec1028728eb4eccc450b925bea268Guennadi Liakhovetski if (common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) 9172066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach csicr1 |= CSICR1_SOF_POL; 918db592a24656ec1028728eb4eccc450b925bea268Guennadi Liakhovetski if (common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) 9192066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach csicr1 |= CSICR1_HSYNC_POL; 9202066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (pcdev->platform_flags & MX2_CAMERA_SWAP16) 9212066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach csicr1 |= CSICR1_SWAP16_EN; 9222066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (pcdev->platform_flags & MX2_CAMERA_EXT_VSYNC) 9232066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach csicr1 |= CSICR1_EXT_VSYNC; 9242066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (pcdev->platform_flags & MX2_CAMERA_CCIR) 9252066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach csicr1 |= CSICR1_CCIR_EN; 9262066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (pcdev->platform_flags & MX2_CAMERA_CCIR_INTERLACE) 9272066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach csicr1 |= CSICR1_CCIR_MODE; 9282066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (pcdev->platform_flags & MX2_CAMERA_GATED_CLOCK) 9292066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach csicr1 |= CSICR1_GCLK_MODE; 9302066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (pcdev->platform_flags & MX2_CAMERA_INV_DATA) 9312066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach csicr1 |= CSICR1_INV_DATA; 9322066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (pcdev->platform_flags & MX2_CAMERA_PACK_DIR_MSB) 9332066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach csicr1 |= CSICR1_PACK_DIR; 9342066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 9352066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->csicr1 = csicr1; 9362066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 9372066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach bytesperline = soc_mbus_bytes_per_line(icd->user_width, 9382066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach icd->current_fmt->host_fmt); 9392066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (bytesperline < 0) 9402066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach return bytesperline; 9412066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 9422066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (mx27_camera_emma(pcdev)) { 9432066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach ret = mx27_camera_emma_prp_reset(pcdev); 9442066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (ret) 9452066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach return ret; 9462066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 9472066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (pcdev->discard_buffer) 9482066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach dma_free_coherent(ici->v4l2_dev.dev, 9492066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->discard_size, pcdev->discard_buffer, 9502066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->discard_buffer_dma); 9512066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 9522066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach /* 9532066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach * I didn't manage to properly enable/disable the prp 9542066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach * on a per frame basis during running transfers, 9552066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach * thus we allocate a buffer here and use it to 9562066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach * discard frames when no buffer is available. 9572066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach * Feel free to work on this ;) 9582066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach */ 9592066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->discard_size = icd->user_height * bytesperline; 9602066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->discard_buffer = dma_alloc_coherent(ici->v4l2_dev.dev, 9612066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->discard_size, &pcdev->discard_buffer_dma, 9622066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach GFP_KERNEL); 9632066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (!pcdev->discard_buffer) 9642066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach return -ENOMEM; 9652066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 9662066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach mx27_camera_emma_buf_init(icd, bytesperline); 9672066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } else if (cpu_is_mx25()) { 9682066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach writel((bytesperline * icd->user_height) >> 2, 9692066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->base_csi + CSIRXCNT); 9702066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach writel((bytesperline << 16) | icd->user_height, 9712066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->base_csi + CSIIMAG_PARA); 9722066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 9732066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 9742066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach writel(pcdev->csicr1, pcdev->base_csi + CSICR1); 9752066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 9762066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach return 0; 9772066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach} 9782066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 9792066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic int mx2_camera_set_crop(struct soc_camera_device *icd, 9802066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct v4l2_crop *a) 9812066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{ 9822066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct v4l2_rect *rect = &a->c; 9832066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct v4l2_subdev *sd = soc_camera_to_subdev(icd); 9842066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct v4l2_mbus_framefmt mf; 9852066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach int ret; 9862066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 9872066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach soc_camera_limit_side(&rect->left, &rect->width, 0, 2, 4096); 9882066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach soc_camera_limit_side(&rect->top, &rect->height, 0, 2, 4096); 9892066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 9902066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach ret = v4l2_subdev_call(sd, video, s_crop, a); 9912066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (ret < 0) 9922066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach return ret; 9932066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 9942066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach /* The capture device might have changed its output */ 9952066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach ret = v4l2_subdev_call(sd, video, g_mbus_fmt, &mf); 9962066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (ret < 0) 9972066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach return ret; 9982066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 9997dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski dev_dbg(icd->parent, "Sensor cropped %dx%d\n", 10002066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach mf.width, mf.height); 10012066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 10022066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach icd->user_width = mf.width; 10032066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach icd->user_height = mf.height; 10042066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 10052066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach return ret; 10062066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach} 10072066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 1008f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martinstatic int mx2_camera_get_formats(struct soc_camera_device *icd, 1009f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin unsigned int idx, 1010f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin struct soc_camera_format_xlate *xlate) 1011f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin{ 1012f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin struct v4l2_subdev *sd = soc_camera_to_subdev(icd); 1013f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin const struct soc_mbus_pixelfmt *fmt; 1014f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin struct device *dev = icd->parent; 1015f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin enum v4l2_mbus_pixelcode code; 1016f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin int ret, formats = 0; 1017f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin 1018f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code); 1019f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin if (ret < 0) 1020f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin /* no more formats */ 1021f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin return 0; 1022f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin 1023f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin fmt = soc_mbus_get_fmtdesc(code); 1024f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin if (!fmt) { 1025f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin dev_err(dev, "Invalid format code #%u: %d\n", idx, code); 1026f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin return 0; 1027f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin } 1028f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin 1029f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin if (code == V4L2_MBUS_FMT_YUYV8_2X8) { 1030f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin formats++; 1031f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin if (xlate) { 1032f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin /* 1033f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin * CH2 can output YUV420 which is a standard format in 1034f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin * soc_mediabus.c 1035f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin */ 1036f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin xlate->host_fmt = 1037f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin soc_mbus_get_fmtdesc(V4L2_MBUS_FMT_YUYV8_1_5X8); 1038f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin xlate->code = code; 1039f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin dev_dbg(dev, "Providing host format %s for sensor code %d\n", 1040f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin xlate->host_fmt->name, code); 1041f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin xlate++; 1042f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin } 1043f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin } 1044f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin 1045f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin /* Generic pass-trough */ 1046f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin formats++; 1047f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin if (xlate) { 1048f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin xlate->host_fmt = fmt; 1049f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin xlate->code = code; 1050f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin xlate++; 1051f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin } 1052f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin return formats; 1053f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin} 1054f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin 10552066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic int mx2_camera_set_fmt(struct soc_camera_device *icd, 10562066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct v4l2_format *f) 10572066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{ 1058f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin struct soc_camera_host *ici = to_soc_camera_host(icd->parent); 1059f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin struct mx2_camera_dev *pcdev = ici->priv; 10602066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct v4l2_subdev *sd = soc_camera_to_subdev(icd); 10612066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach const struct soc_camera_format_xlate *xlate; 10622066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct v4l2_pix_format *pix = &f->fmt.pix; 10632066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct v4l2_mbus_framefmt mf; 10642066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach int ret; 10652066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 10662066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat); 10672066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (!xlate) { 10687dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski dev_warn(icd->parent, "Format %x not found\n", 10692066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pix->pixelformat); 10702066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach return -EINVAL; 10712066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 10722066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 10732066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach mf.width = pix->width; 10742066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach mf.height = pix->height; 10752066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach mf.field = pix->field; 10762066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach mf.colorspace = pix->colorspace; 10772066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach mf.code = xlate->code; 10782066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 10792066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf); 10802066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (ret < 0 && ret != -ENOIOCTLCMD) 10812066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach return ret; 10822066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 10832066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (mf.code != xlate->code) 10842066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach return -EINVAL; 10852066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 10862066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pix->width = mf.width; 10872066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pix->height = mf.height; 10882066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pix->field = mf.field; 10892066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pix->colorspace = mf.colorspace; 10902066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach icd->current_fmt = xlate; 10912066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 1092f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin if (mx27_camera_emma(pcdev)) 1093f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin pcdev->emma_prp = mx27_emma_prp_get_format(xlate->code, 1094f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin xlate->host_fmt->fourcc); 1095f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin 10962066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach return 0; 10972066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach} 10982066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 10992066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic int mx2_camera_try_fmt(struct soc_camera_device *icd, 11002066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct v4l2_format *f) 11012066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{ 11022066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct v4l2_subdev *sd = soc_camera_to_subdev(icd); 11032066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach const struct soc_camera_format_xlate *xlate; 11042066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct v4l2_pix_format *pix = &f->fmt.pix; 11052066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct v4l2_mbus_framefmt mf; 11062066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach __u32 pixfmt = pix->pixelformat; 11072066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach unsigned int width_limit; 11082066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach int ret; 11092066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 11102066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach xlate = soc_camera_xlate_by_fourcc(icd, pixfmt); 11112066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (pixfmt && !xlate) { 11127dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski dev_warn(icd->parent, "Format %x not found\n", pixfmt); 11132066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach return -EINVAL; 11142066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 11152066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 11162066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach /* FIXME: implement MX27 limits */ 11172066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 11182066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach /* limit to MX25 hardware capabilities */ 11192066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (cpu_is_mx25()) { 11202066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (xlate->host_fmt->bits_per_sample <= 8) 11212066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach width_limit = 0xffff * 4; 11222066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach else 11232066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach width_limit = 0xffff * 2; 11242066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach /* CSIIMAG_PARA limit */ 11252066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (pix->width > width_limit) 11262066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pix->width = width_limit; 11272066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (pix->height > 0xffff) 11282066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pix->height = 0xffff; 11292066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 11302066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pix->bytesperline = soc_mbus_bytes_per_line(pix->width, 11312066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach xlate->host_fmt); 11322066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (pix->bytesperline < 0) 11332066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach return pix->bytesperline; 11342066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pix->sizeimage = pix->height * pix->bytesperline; 113528281a71eb3bc08a0fb9514886e7d6e868f71b3fGuennadi Liakhovetski /* Check against the CSIRXCNT limit */ 113628281a71eb3bc08a0fb9514886e7d6e868f71b3fGuennadi Liakhovetski if (pix->sizeimage > 4 * 0x3ffff) { 113728281a71eb3bc08a0fb9514886e7d6e868f71b3fGuennadi Liakhovetski /* Adjust geometry, preserve aspect ratio */ 113828281a71eb3bc08a0fb9514886e7d6e868f71b3fGuennadi Liakhovetski unsigned int new_height = int_sqrt(4 * 0x3ffff * 113928281a71eb3bc08a0fb9514886e7d6e868f71b3fGuennadi Liakhovetski pix->height / pix->bytesperline); 114028281a71eb3bc08a0fb9514886e7d6e868f71b3fGuennadi Liakhovetski pix->width = new_height * pix->width / pix->height; 114128281a71eb3bc08a0fb9514886e7d6e868f71b3fGuennadi Liakhovetski pix->height = new_height; 114228281a71eb3bc08a0fb9514886e7d6e868f71b3fGuennadi Liakhovetski pix->bytesperline = soc_mbus_bytes_per_line(pix->width, 114328281a71eb3bc08a0fb9514886e7d6e868f71b3fGuennadi Liakhovetski xlate->host_fmt); 114428281a71eb3bc08a0fb9514886e7d6e868f71b3fGuennadi Liakhovetski BUG_ON(pix->bytesperline < 0); 11452066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 11462066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 11472066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 11482066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach /* limit to sensor capabilities */ 11492066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach mf.width = pix->width; 11502066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach mf.height = pix->height; 11512066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach mf.field = pix->field; 11522066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach mf.colorspace = pix->colorspace; 11532066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach mf.code = xlate->code; 11542066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 11552066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf); 11562066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (ret < 0) 11572066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach return ret; 11582066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 11592066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (mf.field == V4L2_FIELD_ANY) 11602066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach mf.field = V4L2_FIELD_NONE; 1161f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin /* 1162f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin * Driver supports interlaced images provided they have 1163f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin * both fields so that they can be processed as if they 1164f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin * were progressive. 1165f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin */ 1166f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin if (mf.field != V4L2_FIELD_NONE && !V4L2_FIELD_HAS_BOTH(mf.field)) { 11677dfff95366f48bf66f77c17cdc9ebd8be696ac5dGuennadi Liakhovetski dev_err(icd->parent, "Field type %d unsupported.\n", 11682066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach mf.field); 11692066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach return -EINVAL; 11702066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 11712066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 11722066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pix->width = mf.width; 11732066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pix->height = mf.height; 11742066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pix->field = mf.field; 11752066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pix->colorspace = mf.colorspace; 11762066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 11772066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach return 0; 11782066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach} 11792066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 11802066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic int mx2_camera_querycap(struct soc_camera_host *ici, 11812066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct v4l2_capability *cap) 11822066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{ 11832066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach /* cap->name is set by the friendly caller:-> */ 11842066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach strlcpy(cap->card, MX2_CAM_DRIVER_DESCRIPTION, sizeof(cap->card)); 11852066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; 11862066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 11872066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach return 0; 11882066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach} 11892066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 11906b101926f98b54549128db4d34f4a73b5f03feccSascha Hauerstatic int mx2_camera_reqbufs(struct soc_camera_device *icd, 11912066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct v4l2_requestbuffers *p) 11922066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{ 11932066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach int i; 11942066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 11952066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach for (i = 0; i < p->count; i++) { 11966b101926f98b54549128db4d34f4a73b5f03feccSascha Hauer struct mx2_buffer *buf = container_of(icd->vb_vidq.bufs[i], 11972066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct mx2_buffer, vb); 11982066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach INIT_LIST_HEAD(&buf->vb.queue); 11992066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 12002066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 12012066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach return 0; 12022066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach} 12032066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 12042066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#ifdef CONFIG_MACH_MX27 12052066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic void mx27_camera_frame_done(struct mx2_camera_dev *pcdev, int state) 12062066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{ 12072066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct videobuf_buffer *vb; 12082066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct mx2_buffer *buf; 12092066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach unsigned long flags; 12102066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach int ret; 12112066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 12122066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach spin_lock_irqsave(&pcdev->lock, flags); 12132066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 12142066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (!pcdev->active) { 12152066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach dev_err(pcdev->dev, "%s called with no active buffer!\n", 12162066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach __func__); 12172066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach goto out; 12182066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 12192066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 12202066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach vb = &pcdev->active->vb; 12212066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach buf = container_of(vb, struct mx2_buffer, vb); 12222066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach WARN_ON(list_empty(&vb->queue)); 12232066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, 12242066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach vb, vb->baddr, vb->bsize); 12252066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 12262066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach /* _init is used to debug races, see comment in pxa_camera_reqbufs() */ 12272066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach list_del_init(&vb->queue); 12282066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach vb->state = state; 12292066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach do_gettimeofday(&vb->ts); 12302066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach vb->field_count++; 12312066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 12322066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach wake_up(&vb->done); 12332066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 12342066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (list_empty(&pcdev->capture)) { 12352066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->active = NULL; 12362066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach goto out; 12372066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 12382066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 12392066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->active = list_entry(pcdev->capture.next, 12402066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct mx2_buffer, vb.queue); 12412066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 12422066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach vb = &pcdev->active->vb; 12432066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach vb->state = VIDEOBUF_ACTIVE; 12442066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 12452066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach ret = imx_dma_setup_single(pcdev->dma, videobuf_to_dma_contig(vb), 12462066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach vb->size, (u32)pcdev->base_dma + 0x10, DMA_MODE_READ); 12472066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 12482066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (ret) { 12492066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach vb->state = VIDEOBUF_ERROR; 12502066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->active = NULL; 12512066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach wake_up(&vb->done); 12522066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 12532066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 12542066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachout: 12552066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach spin_unlock_irqrestore(&pcdev->lock, flags); 12562066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach} 12572066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 12582066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic void mx27_camera_dma_err_callback(int channel, void *data, int err) 12592066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{ 12602066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct mx2_camera_dev *pcdev = data; 12612066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 12622066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach mx27_camera_frame_done(pcdev, VIDEOBUF_ERROR); 12632066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach} 12642066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 12652066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic void mx27_camera_dma_callback(int channel, void *data) 12662066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{ 12672066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct mx2_camera_dev *pcdev = data; 12682066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 12692066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach mx27_camera_frame_done(pcdev, VIDEOBUF_DONE); 12702066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach} 12712066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 12722066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#define DMA_REQ_CSI_RX 31 /* FIXME: Add this to a resource */ 12732066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 12742066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic int __devinit mx27_camera_dma_init(struct platform_device *pdev, 12752066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct mx2_camera_dev *pcdev) 12762066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{ 12772066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach int err; 12782066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 12792066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->dma = imx_dma_request_by_prio("CSI RX DMA", DMA_PRIO_HIGH); 12802066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (pcdev->dma < 0) { 12812066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach dev_err(&pdev->dev, "%s failed to request DMA channel\n", 12822066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach __func__); 12832066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach return pcdev->dma; 12842066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 12852066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 12862066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach err = imx_dma_setup_handlers(pcdev->dma, mx27_camera_dma_callback, 12872066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach mx27_camera_dma_err_callback, pcdev); 12882066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (err) { 12892066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach dev_err(&pdev->dev, "%s failed to set DMA callback\n", 12902066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach __func__); 12912066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach goto err_out; 12922066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 12932066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 12942066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach err = imx_dma_config_channel(pcdev->dma, 12952066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_FIFO, 12962066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR, 12972066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach DMA_REQ_CSI_RX, 1); 12982066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (err) { 12992066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach dev_err(&pdev->dev, "%s failed to config DMA channel\n", 13002066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach __func__); 13012066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach goto err_out; 13022066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 13032066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 13042066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach imx_dma_config_burstlen(pcdev->dma, 64); 13052066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 13062066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach return 0; 13072066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 13082066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siacherr_out: 13092066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach imx_dma_free(pcdev->dma); 13102066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 13112066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach return err; 13122066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach} 13132066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#endif /* CONFIG_MACH_MX27 */ 13142066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 13152066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic unsigned int mx2_camera_poll(struct file *file, poll_table *pt) 13162066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{ 13176b101926f98b54549128db4d34f4a73b5f03feccSascha Hauer struct soc_camera_device *icd = file->private_data; 13182066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 13196b101926f98b54549128db4d34f4a73b5f03feccSascha Hauer return videobuf_poll_stream(file, &icd->vb_vidq, pt); 13202066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach} 13212066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 13222066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic struct soc_camera_host_ops mx2_soc_camera_host_ops = { 13232066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach .owner = THIS_MODULE, 13242066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach .add = mx2_camera_add_device, 13252066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach .remove = mx2_camera_remove_device, 13262066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach .set_fmt = mx2_camera_set_fmt, 13272066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach .set_crop = mx2_camera_set_crop, 1328f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin .get_formats = mx2_camera_get_formats, 13292066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach .try_fmt = mx2_camera_try_fmt, 13302066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach .init_videobuf = mx2_camera_init_videobuf, 13312066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach .reqbufs = mx2_camera_reqbufs, 13322066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach .poll = mx2_camera_poll, 13332066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach .querycap = mx2_camera_querycap, 13342066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach .set_bus_param = mx2_camera_set_bus_param, 13352066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach}; 13362066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 13372066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev, 13382066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach int bufnum, int state) 13392066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{ 1340f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin u32 imgsize = pcdev->icd->user_height * pcdev->icd->user_width; 1341f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin struct mx2_fmt_cfg *prp = pcdev->emma_prp; 13422066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct mx2_buffer *buf; 13432066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct videobuf_buffer *vb; 13442066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach unsigned long phys; 13452066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 13462066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (!list_empty(&pcdev->active_bufs)) { 13472066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach buf = list_entry(pcdev->active_bufs.next, 13482066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct mx2_buffer, vb.queue); 13492066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 13502066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach BUG_ON(buf->bufnum != bufnum); 13512066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 13522066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach vb = &buf->vb; 13532066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#ifdef DEBUG 13542066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach phys = videobuf_to_dma_contig(vb); 1355f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin if (prp->cfg.channel == 1) { 1356f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin if (readl(pcdev->base_emma + PRP_DEST_RGB1_PTR + 1357f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin 4 * bufnum) != phys) { 1358f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin dev_err(pcdev->dev, "%p != %p\n", phys, 1359f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin readl(pcdev->base_emma + 1360f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin PRP_DEST_RGB1_PTR + 1361f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin 4 * bufnum)); 1362f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin } 1363f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin } else { 1364f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin if (readl(pcdev->base_emma + PRP_DEST_Y_PTR - 1365f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin 0x14 * bufnum) != phys) { 1366f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin dev_err(pcdev->dev, "%p != %p\n", phys, 1367f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin readl(pcdev->base_emma + 1368f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin PRP_DEST_Y_PTR - 1369f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin 0x14 * bufnum)); 1370f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin } 13712066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 13722066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#endif 13732066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, 13742066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach vb->baddr, vb->bsize); 13752066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 13762066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach list_del(&vb->queue); 13772066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach vb->state = state; 13782066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach do_gettimeofday(&vb->ts); 1379ccd1a499c1675fef5d2a138617507add63cb81dbJavier Martin vb->field_count = pcdev->frame_count * 2; 1380ccd1a499c1675fef5d2a138617507add63cb81dbJavier Martin pcdev->frame_count++; 13812066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 13822066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach wake_up(&vb->done); 13832066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 13842066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 13852066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (list_empty(&pcdev->capture)) { 1386f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin if (prp->cfg.channel == 1) { 1387f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin writel(pcdev->discard_buffer_dma, pcdev->base_emma + 1388f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin PRP_DEST_RGB1_PTR + 4 * bufnum); 1389f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin } else { 1390f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin writel(pcdev->discard_buffer_dma, pcdev->base_emma + 1391f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin PRP_DEST_Y_PTR - 1392f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin 0x14 * bufnum); 1393f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin if (prp->out_fmt == V4L2_PIX_FMT_YUV420) { 1394f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin writel(pcdev->discard_buffer_dma + imgsize, 1395f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin pcdev->base_emma + PRP_DEST_CB_PTR - 1396f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin 0x14 * bufnum); 1397f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin writel(pcdev->discard_buffer_dma + 1398f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin ((5 * imgsize) / 4), pcdev->base_emma + 1399f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin PRP_DEST_CR_PTR - 0x14 * bufnum); 1400f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin } 1401f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin } 14022066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach return; 14032066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 14042066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 14052066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach buf = list_entry(pcdev->capture.next, 14062066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct mx2_buffer, vb.queue); 14072066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 1408cd9ebdbc0541b4e8ee145c81642d68332f79b932Michael Grzeschik buf->bufnum = !bufnum; 14092066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 14102066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach list_move_tail(pcdev->capture.next, &pcdev->active_bufs); 14112066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 14122066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach vb = &buf->vb; 14132066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach vb->state = VIDEOBUF_ACTIVE; 14142066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 14152066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach phys = videobuf_to_dma_contig(vb); 1416f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin if (prp->cfg.channel == 1) { 1417f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin writel(phys, pcdev->base_emma + PRP_DEST_RGB1_PTR + 4 * bufnum); 1418f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin } else { 1419f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin writel(phys, pcdev->base_emma + 1420f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin PRP_DEST_Y_PTR - 0x14 * bufnum); 1421f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin if (prp->cfg.out_fmt == PRP_CNTL_CH2_OUT_YUV420) { 1422f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin writel(phys + imgsize, pcdev->base_emma + 1423f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin PRP_DEST_CB_PTR - 0x14 * bufnum); 1424f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin writel(phys + ((5 * imgsize) / 4), pcdev->base_emma + 1425f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin PRP_DEST_CR_PTR - 0x14 * bufnum); 1426f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin } 1427f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin } 14282066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach} 14292066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 14302066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic irqreturn_t mx27_camera_emma_irq(int irq_emma, void *data) 14312066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{ 14322066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct mx2_camera_dev *pcdev = data; 14332066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach unsigned int status = readl(pcdev->base_emma + PRP_INTRSTATUS); 14342066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct mx2_buffer *buf; 14352066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 14362066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (status & (1 << 7)) { /* overflow */ 14372066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach u32 cntl; 14382066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach /* 14392066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach * We only disable channel 1 here since this is the only 14402066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach * enabled channel 14412066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach * 14422066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach * FIXME: the correct DMA overflow handling should be resetting 14432066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach * the buffer, returning an error frame, and continuing with 14442066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach * the next one. 14452066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach */ 14462066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach cntl = readl(pcdev->base_emma + PRP_CNTL); 1447f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin writel(cntl & ~(PRP_CNTL_CH1EN | PRP_CNTL_CH2EN), 1448f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin pcdev->base_emma + PRP_CNTL); 14492066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach writel(cntl, pcdev->base_emma + PRP_CNTL); 14502066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 1451f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin if ((((status & (3 << 5)) == (3 << 5)) || 1452f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin ((status & (3 << 3)) == (3 << 3))) 14532066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach && !list_empty(&pcdev->active_bufs)) { 14542066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach /* 14552066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach * Both buffers have triggered, process the one we're expecting 14562066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach * to first 14572066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach */ 14582066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach buf = list_entry(pcdev->active_bufs.next, 14592066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct mx2_buffer, vb.queue); 14602066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach mx27_camera_frame_done_emma(pcdev, buf->bufnum, VIDEOBUF_DONE); 14612066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach status &= ~(1 << (6 - buf->bufnum)); /* mark processed */ 14622066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 1463f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin if ((status & (1 << 6)) || (status & (1 << 4))) 14642066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach mx27_camera_frame_done_emma(pcdev, 0, VIDEOBUF_DONE); 1465f410991dcf1fc3ad1d3311b79b4f1b917224ebedJavier Martin if ((status & (1 << 5)) || (status & (1 << 3))) 14662066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach mx27_camera_frame_done_emma(pcdev, 1, VIDEOBUF_DONE); 14672066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 14682066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach writel(status, pcdev->base_emma + PRP_INTRSTATUS); 14692066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 14702066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach return IRQ_HANDLED; 14712066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach} 14722066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 14732066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic int __devinit mx27_camera_emma_init(struct mx2_camera_dev *pcdev) 14742066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{ 14752066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct resource *res_emma = pcdev->res_emma; 14762066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach int err = 0; 14772066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 14782066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (!request_mem_region(res_emma->start, resource_size(res_emma), 14792066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach MX2_CAM_DRV_NAME)) { 14802066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach err = -EBUSY; 14812066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach goto out; 14822066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 14832066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 14842066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->base_emma = ioremap(res_emma->start, resource_size(res_emma)); 14852066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (!pcdev->base_emma) { 14862066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach err = -ENOMEM; 14872066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach goto exit_release; 14882066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 14892066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 14902066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach err = request_irq(pcdev->irq_emma, mx27_camera_emma_irq, 0, 14912066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach MX2_CAM_DRV_NAME, pcdev); 14922066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (err) { 14932066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach dev_err(pcdev->dev, "Camera EMMA interrupt register failed \n"); 14942066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach goto exit_iounmap; 14952066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 14962066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 14972066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->clk_emma = clk_get(NULL, "emma"); 14982066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (IS_ERR(pcdev->clk_emma)) { 14992066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach err = PTR_ERR(pcdev->clk_emma); 15002066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach goto exit_free_irq; 15012066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 15022066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 15032066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach clk_enable(pcdev->clk_emma); 15042066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 15052066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach err = mx27_camera_emma_prp_reset(pcdev); 15062066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (err) 15072066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach goto exit_clk_emma_put; 15082066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 15092066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach return err; 15102066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 15112066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachexit_clk_emma_put: 15122066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach clk_disable(pcdev->clk_emma); 15132066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach clk_put(pcdev->clk_emma); 15142066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachexit_free_irq: 15152066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach free_irq(pcdev->irq_emma, pcdev); 15162066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachexit_iounmap: 15172066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach iounmap(pcdev->base_emma); 15182066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachexit_release: 15192066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach release_mem_region(res_emma->start, resource_size(res_emma)); 15202066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachout: 15212066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach return err; 15222066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach} 15232066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 15242066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic int __devinit mx2_camera_probe(struct platform_device *pdev) 15252066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{ 15262066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct mx2_camera_dev *pcdev; 15272066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct resource *res_csi, *res_emma; 15282066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach void __iomem *base_csi; 15292066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach int irq_csi, irq_emma; 15302066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach irq_handler_t mx2_cam_irq_handler = cpu_is_mx25() ? mx25_camera_irq 15312066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach : mx27_camera_irq; 15322066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach int err = 0; 15332066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 15342066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach dev_dbg(&pdev->dev, "initialising\n"); 15352066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 15362066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach res_csi = platform_get_resource(pdev, IORESOURCE_MEM, 0); 15372066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach irq_csi = platform_get_irq(pdev, 0); 15382066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (res_csi == NULL || irq_csi < 0) { 15392066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach dev_err(&pdev->dev, "Missing platform resources data\n"); 15402066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach err = -ENODEV; 15412066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach goto exit; 15422066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 15432066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 15442066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev = kzalloc(sizeof(*pcdev), GFP_KERNEL); 15452066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (!pcdev) { 15462066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach dev_err(&pdev->dev, "Could not allocate pcdev\n"); 15472066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach err = -ENOMEM; 15482066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach goto exit; 15492066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 15502066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 15512066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->clk_csi = clk_get(&pdev->dev, NULL); 15522066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (IS_ERR(pcdev->clk_csi)) { 15532066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach err = PTR_ERR(pcdev->clk_csi); 15542066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach goto exit_kfree; 15552066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 15562066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 15572066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach dev_dbg(&pdev->dev, "Camera clock frequency: %ld\n", 15582066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach clk_get_rate(pcdev->clk_csi)); 15592066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 15602066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach /* Initialize DMA */ 15612066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#ifdef CONFIG_MACH_MX27 15622066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (cpu_is_mx27()) { 15632066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach err = mx27_camera_dma_init(pdev, pcdev); 15642066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (err) 15652066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach goto exit_clk_put; 15662066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 15672066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#endif /* CONFIG_MACH_MX27 */ 15682066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 15692066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->res_csi = res_csi; 15702066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->pdata = pdev->dev.platform_data; 15712066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (pcdev->pdata) { 15722066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach long rate; 15732066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 15742066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->platform_flags = pcdev->pdata->flags; 15752066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 15762066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach rate = clk_round_rate(pcdev->clk_csi, pcdev->pdata->clk * 2); 15772066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (rate <= 0) { 15782066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach err = -ENODEV; 15792066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach goto exit_dma_free; 15802066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 15812066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach err = clk_set_rate(pcdev->clk_csi, rate); 15822066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (err < 0) 15832066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach goto exit_dma_free; 15842066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 15852066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 15862066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach INIT_LIST_HEAD(&pcdev->capture); 15872066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach INIT_LIST_HEAD(&pcdev->active_bufs); 15882066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach spin_lock_init(&pcdev->lock); 15892066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 15902066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach /* 15912066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach * Request the regions. 15922066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach */ 15932066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (!request_mem_region(res_csi->start, resource_size(res_csi), 15942066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach MX2_CAM_DRV_NAME)) { 15952066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach err = -EBUSY; 15962066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach goto exit_dma_free; 15972066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 15982066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 15992066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach base_csi = ioremap(res_csi->start, resource_size(res_csi)); 16002066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (!base_csi) { 16012066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach err = -ENOMEM; 16022066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach goto exit_release; 16032066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 16042066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->irq_csi = irq_csi; 16052066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->base_csi = base_csi; 16062066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->base_dma = res_csi->start; 16072066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->dev = &pdev->dev; 16082066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 16092066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach err = request_irq(pcdev->irq_csi, mx2_cam_irq_handler, 0, 16102066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach MX2_CAM_DRV_NAME, pcdev); 16112066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (err) { 16122066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach dev_err(pcdev->dev, "Camera interrupt register failed \n"); 16132066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach goto exit_iounmap; 16142066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 16152066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 16162066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (cpu_is_mx27()) { 16172066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach /* EMMA support */ 16182066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach res_emma = platform_get_resource(pdev, IORESOURCE_MEM, 1); 16192066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach irq_emma = platform_get_irq(pdev, 1); 16202066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 16212066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (res_emma && irq_emma >= 0) { 16222066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach dev_info(&pdev->dev, "Using EMMA\n"); 16232066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->use_emma = 1; 16242066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->res_emma = res_emma; 16252066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->irq_emma = irq_emma; 16262066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (mx27_camera_emma_init(pcdev)) 16272066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach goto exit_free_irq; 16282066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 16292066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 16302066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 16312066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->soc_host.drv_name = MX2_CAM_DRV_NAME, 16322066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->soc_host.ops = &mx2_soc_camera_host_ops, 16332066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->soc_host.priv = pcdev; 16342066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->soc_host.v4l2_dev.dev = &pdev->dev; 16352066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach pcdev->soc_host.nr = pdev->id; 16362066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach err = soc_camera_host_register(&pcdev->soc_host); 16372066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (err) 16382066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach goto exit_free_emma; 16392066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 164045f4d4e8799ff1d7ef72747203935f1f2533743dMichael Grzeschik dev_info(&pdev->dev, "MX2 Camera (CSI) driver probed, clock frequency: %ld\n", 164145f4d4e8799ff1d7ef72747203935f1f2533743dMichael Grzeschik clk_get_rate(pcdev->clk_csi)); 164245f4d4e8799ff1d7ef72747203935f1f2533743dMichael Grzeschik 16432066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach return 0; 16442066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 16452066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachexit_free_emma: 16462066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (mx27_camera_emma(pcdev)) { 16472066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach free_irq(pcdev->irq_emma, pcdev); 16482066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach clk_disable(pcdev->clk_emma); 16492066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach clk_put(pcdev->clk_emma); 16502066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach iounmap(pcdev->base_emma); 16512066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach release_mem_region(res_emma->start, resource_size(res_emma)); 16522066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 16532066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachexit_free_irq: 16542066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach free_irq(pcdev->irq_csi, pcdev); 16552066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachexit_iounmap: 16562066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach iounmap(base_csi); 16572066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachexit_release: 16582066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach release_mem_region(res_csi->start, resource_size(res_csi)); 16592066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachexit_dma_free: 16602066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#ifdef CONFIG_MACH_MX27 16612066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (cpu_is_mx27()) 16622066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach imx_dma_free(pcdev->dma); 16632066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachexit_clk_put: 16642066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach clk_put(pcdev->clk_csi); 16652066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#endif /* CONFIG_MACH_MX27 */ 16662066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachexit_kfree: 16672066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach kfree(pcdev); 16682066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachexit: 16692066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach return err; 16702066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach} 16712066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 16722066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic int __devexit mx2_camera_remove(struct platform_device *pdev) 16732066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{ 16742066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev); 16752066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct mx2_camera_dev *pcdev = container_of(soc_host, 16762066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct mx2_camera_dev, soc_host); 16772066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach struct resource *res; 16782066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 16792066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach clk_put(pcdev->clk_csi); 16802066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#ifdef CONFIG_MACH_MX27 16812066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (cpu_is_mx27()) 16822066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach imx_dma_free(pcdev->dma); 16832066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach#endif /* CONFIG_MACH_MX27 */ 16842066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach free_irq(pcdev->irq_csi, pcdev); 16852066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (mx27_camera_emma(pcdev)) 16862066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach free_irq(pcdev->irq_emma, pcdev); 16872066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 16882066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach soc_camera_host_unregister(&pcdev->soc_host); 16892066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 16902066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach iounmap(pcdev->base_csi); 16912066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 16922066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach if (mx27_camera_emma(pcdev)) { 16932066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach clk_disable(pcdev->clk_emma); 16942066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach clk_put(pcdev->clk_emma); 16952066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach iounmap(pcdev->base_emma); 16962066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach res = pcdev->res_emma; 16972066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach release_mem_region(res->start, resource_size(res)); 16982066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach } 16992066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 17002066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach res = pcdev->res_csi; 17012066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach release_mem_region(res->start, resource_size(res)); 17022066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 17032066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach kfree(pcdev); 17042066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 17052066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach dev_info(&pdev->dev, "MX2 Camera driver unloaded\n"); 17062066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 17072066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach return 0; 17082066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach} 17092066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 17102066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic struct platform_driver mx2_camera_driver = { 17112066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach .driver = { 17122066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach .name = MX2_CAM_DRV_NAME, 17132066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach }, 17142066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach .remove = __devexit_p(mx2_camera_remove), 17152066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach}; 17162066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 17172066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 17182066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic int __init mx2_camera_init(void) 17192066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{ 17202066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach return platform_driver_probe(&mx2_camera_driver, &mx2_camera_probe); 17212066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach} 17222066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 17232066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachstatic void __exit mx2_camera_exit(void) 17242066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach{ 17252066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach return platform_driver_unregister(&mx2_camera_driver); 17262066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach} 17272066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 17282066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachmodule_init(mx2_camera_init); 17292066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siachmodule_exit(mx2_camera_exit); 17302066930de6296ef7470de11eaa9b8bc9129721e8Baruch Siach 17312066930de6296ef7470de11eaa9b8bc9129721e8Baruch SiachMODULE_DESCRIPTION("i.MX27/i.MX25 SoC Camera Host driver"); 17322066930de6296ef7470de11eaa9b8bc9129721e8Baruch SiachMODULE_AUTHOR("Sascha Hauer <sha@pengutronix.de>"); 17332066930de6296ef7470de11eaa9b8bc9129721e8Baruch SiachMODULE_LICENSE("GPL"); 173464dc3c1a906467d90c24913b0b38dd13d9378f4fMauro Carvalho ChehabMODULE_VERSION(MX2_CAM_VERSION); 1735