?? csi.c
字號:
/*
*
* MX21 CSI driver
*
* cliff.wong@motorola.com
* 12 Jun, 04
*/
#include <asm/dma.h>
#include <asm/mach/dma.h>
#include <asm/arch/dma.h>
#include <asm/arch/mx2.h>
#include <asm/arch/platform.h>
#include "khead.h"
#include "csi.h"
#include "ov9650.h"
//tapeout 2 specific
#ifndef _reg_CSI_CSICR3
#define _reg_CSI_CSICR3 (*((volatile unsigned long *)(CSI_IO_ADDRESS(CSI_BASE_ADDR+0x1C))))
#endif
//reset values
#define CSICR1_RESET_VAL 0x40000800
#define CSICR2_RESET_VAL 0x0
#define CSICR3_RESET_VAL 0x0
//csi control reg 1
#define BIT_SWAP16_EN (0x1 << 31)
#define BIT_EXT_VSYNC (0x1 << 30)
#define BIT_EOF_INT_EN (0x1 << 29)
#define BIT_PRP_IF_EN (0x1 << 28)
#define BIT_CCIR_MODE (0x1 << 27)
#define BIT_COF_INT_EN (0x1 << 26)
#define BIT_SF_OR_INTEN (0x1 << 25)
#define BIT_RF_OR_INTEN (0x1 << 24)
#define BIT_STATFF_LEVEL (0x3 << 22)
#define BIT_STATFF_INTEN (0x1 << 21)
#define BIT_RXFF_LEVEL (0x3 << 19)
#define BIT_RXFF_INTEN (0x1 << 18)
#define BIT_SOF_POL (0x1 << 17)
#define BIT_SOF_INTEN (0x1 << 16)
#define BIT_MCLKDIV (0xF << 12)
#define BIT_HSYNC_POL (0x1 << 11)
#define BIT_CCIR_EN (0x1 << 10)
#define BIT_MCLKEN (0x1 << 9)
#define BIT_FCC (0x1 << 8)
#define BIT_PACK_DIR (0x1 << 7)
#define BIT_CLR_STATFIFO (0x1 << 6)
#define BIT_CLR_RXFIFO (0x1 << 5)
#define BIT_GCLK_MODE (0x1 << 4)
#define BIT_INV_DATA (0x1 << 3)
#define BIT_INV_PCLK (0x1 << 2)
#define BIT_REDGE (0x1 << 1)
#define SHIFT_STATFF_LEVEL 22
#define SHIFT_RXFF_LEVEL 19
#define SHIFT_MCLKDIV 12
//control reg 3
#define BIT_FRMCNT (0xFFFF << 16)
#define BIT_FRMCNT_RST (0x1 << 15)
#define BIT_CSI_SUP (0x1 << 3)
#define BIT_ZERO_PACK_EN (0x1 << 2)
#define BIT_ECC_INT_EN (0x1 << 1)
#define BIT_ECC_AUTO_EN (0x1)
#define SHIFT_FRMCNT 16
//csi status reg
#define BIT_SFF_OR_INT (0x1 << 25)
#define BIT_RFF_OR_INT (0x1 << 24)
#define BIT_STATFF_INT (0x1 << 21)
#define BIT_RXFF_INT (0x1 << 18)
#define BIT_EOF_INT (0x1 << 17)
#define BIT_SOF_INT (0x1 << 16)
#define BIT_F2_INT (0x1 << 15)
#define BIT_F1_INT (0x1 << 14)
#define BIT_COF_INT (0x1 << 13)
#define BIT_ECC_INT (0x1 << 1)
#define BIT_DRDY (0x1 << 0)
static U32 SFCM_capture_DMA(U32 nPixel);
static void dma_complete_handler(void);
static void dma_error_handler(int error_type);
static void csi_read_cfg(CSI_CFG * _cfg);
static void csi_config(CSI_CFG * _cfg);
static void csi_reset_frame_count(void);
static int csi_get_frame_count(void);
//global
int sensorFrameCount = 0;
static int g_csi_ver;
static CSI_CFG g_csi_cfg;
static CSI_STATUS g_csi_status;
static U32 *csi_data_buf = 0;
static U32 *csi_data_buf2 = 0;
static dmach_t dma_channel;
static U32 dma_buf_phy_addr;
static U32 dma_buf_phy_addr2;
static U32 dma_data_size;
static U32 readSeqNum;
static U32 capSeqNum;
static U32 SOFseqNum;
static U8 stopCapture;
static int DMA_ModuleInitDone = 0;
static DECLARE_WAIT_QUEUE_HEAD(dma_wait);
#include "dma.c"
static void csi_read_status(CSI_STATUS * _status)
{
_status->sff_or_int = (_reg_CSI_CSISR & BIT_SFF_OR_INT) ? 1 : 0;
_status->rff_or_int = (_reg_CSI_CSISR & BIT_RFF_OR_INT) ? 1 : 0;
_status->statff_int = (_reg_CSI_CSISR & BIT_STATFF_INT) ? 1 : 0;
_status->rxff_int = (_reg_CSI_CSISR & BIT_RXFF_INT) ? 1 : 0;
_status->eof_int = (_reg_CSI_CSISR & BIT_EOF_INT) ? 1 : 0;
_status->sof_int = (_reg_CSI_CSISR & BIT_SOF_INT) ? 1 : 0;
_status->f2_int = (_reg_CSI_CSISR & BIT_F2_INT) ? 1 : 0;
_status->f1_int = (_reg_CSI_CSISR & BIT_F1_INT) ? 1 : 0;
_status->cof_int = (_reg_CSI_CSISR & BIT_COF_INT) ? 1 : 0;
_status->ecc_int = (_reg_CSI_CSISR & BIT_ECC_INT) ? 1 : 0;
_status->drdy = (_reg_CSI_CSISR & BIT_DRDY) ? 1 : 0;
return;
}
static void csi_irq_handler(int irq, void * data, struct pt_regs * pt)
{
csi_read_status(&g_csi_status);
//go to individual handlers
//leave it untouched if user has not enabled the interrupt
if(g_csi_cfg.rf_or_inten)
{
if(g_csi_status.rff_or_int)
{
g_csi_status.rff_or_int = 0;
printk("csi error: rxff overflow\n");
//flush fifo
_reg_CSI_CSICR1 &= ~BIT_FCC;
_reg_CSI_CSICR1 |= BIT_CLR_RXFIFO;
if(g_csi_cfg.fcc)
_reg_CSI_CSICR1 |= BIT_FCC;
_reg_CSI_CSISR = BIT_RFF_OR_INT;
}
}
if(g_csi_cfg.sof_inten)
{
if(g_csi_status.sof_int)
{
_reg_CSI_CSISR = BIT_SOF_INT;
g_csi_status.sof_int = 0;
}
}
return;
}
static void csi_read_cfg(CSI_CFG * _cfg)
{
unsigned int tmp;
unsigned val;
//1. read from register
//control reg 1
val = _reg_CSI_CSICR1;
_cfg->swap16_en = (val & BIT_SWAP16_EN) ? 1 : 0;
_cfg->ext_vsync = (val & BIT_EXT_VSYNC) ? 1 : 0;
_cfg->eof_int_en = (val & BIT_EOF_INT_EN) ? 1 : 0;
_cfg->prp_if_en = (val & BIT_PRP_IF_EN) ? 1 : 0;
_cfg->ccir_mode = (val & BIT_CCIR_MODE) ? 1 : 0;
_cfg->cof_int_en = (val & BIT_COF_INT_EN) ? 1 : 0;
_cfg->sf_or_inten = (val & BIT_SF_OR_INTEN) ? 1 : 0;
_cfg->rf_or_inten = (val & BIT_RF_OR_INTEN) ? 1 : 0;
tmp = (val & BIT_STATFF_LEVEL) >> SHIFT_STATFF_LEVEL;
if(tmp == 0x3)
_cfg->statff_level = 16;
else if(tmp == 0x2)
_cfg->statff_level = 12;
else if(tmp == 0x1)
_cfg->statff_level = 8;
else
_cfg->statff_level = 4;
_cfg->staff_inten = (val & BIT_STATFF_INTEN)? 1 : 0;
tmp = (val & BIT_RXFF_LEVEL) >> SHIFT_RXFF_LEVEL;
if(tmp == 0x3)
_cfg->rxff_level = 24;
else if(tmp == 0x2)
_cfg->rxff_level = 16;
else if(tmp == 0x1)
_cfg->rxff_level = 8;
else
_cfg->rxff_level = 4;
_cfg->rxff_inten = (val & BIT_RXFF_INTEN)? 1 : 0;
_cfg->sof_pol = (val & BIT_SOF_POL)? 1 : 0;
_cfg->sof_inten = (val & BIT_SOF_INTEN)? 1 : 0;
tmp = (val & BIT_MCLKDIV) >> SHIFT_MCLKDIV;
_cfg->mclkdiv = (tmp + 1) * 2;
_cfg->hsync_pol = (val & BIT_HSYNC_POL)? 1 : 0;
_cfg->ccir_en = (val & BIT_CCIR_EN)? 1 : 0;
_cfg->mclken = (val & BIT_MCLKEN)? 1 : 0;
_cfg->fcc = (val & BIT_FCC)? 1 : 0;
_cfg->pack_dir = (val & BIT_PACK_DIR)? 1 : 0;
_cfg->gclk_mode = (val & BIT_GCLK_MODE)? 1 : 0;
_cfg->inv_data = (val & BIT_INV_DATA)? 1 : 0;
_cfg->inv_pclk = (val & BIT_INV_PCLK)? 1 : 0;
_cfg->redge = (val & BIT_REDGE)? 1 : 0;
//control reg 3
val = _reg_CSI_CSICR3;
_cfg->csi_sup = (val & BIT_CSI_SUP)? 1 : 0;
_cfg->zero_pack_en = (val & BIT_ZERO_PACK_EN)? 1 : 0;
_cfg->ecc_int_en = (val & BIT_ECC_INT_EN)? 1 : 0;
_cfg->ecc_auto_en = (val & BIT_ECC_AUTO_EN)? 1 : 0;
//rxfifo reg
val = _reg_CSI_CSIRXCNT;
//keep system settings
_cfg->module_irq_enable = g_csi_cfg.module_irq_enable;
//2. update global config
memcpy(&g_csi_cfg, _cfg, sizeof(CSI_CFG));
return;
}
static void csi_config(CSI_CFG * _cfg)
{
unsigned int tmp;
unsigned val = 0x0;
int rt;
//1. write to registers
//control reg 1
if(_cfg->swap16_en)
val |= BIT_SWAP16_EN;
if(_cfg->ext_vsync)
val |= BIT_EXT_VSYNC;
if(_cfg->eof_int_en)
val |= BIT_EOF_INT_EN;
if(_cfg->prp_if_en)
val |= BIT_PRP_IF_EN;
if(_cfg->ccir_mode)
val |= BIT_CCIR_MODE;
if(_cfg->cof_int_en)
val |= BIT_COF_INT_EN;
if(_cfg->sf_or_inten)
val |= BIT_SF_OR_INTEN;
if(_cfg->rf_or_inten)
val |= BIT_RF_OR_INTEN;
if(_cfg->statff_level == 16)
tmp = 0x3;
else if(_cfg->statff_level == 12)
tmp = 0x2;
else if(_cfg->statff_level == 8)
tmp = 0x1;
else
tmp = 0x0;
val |= (tmp << SHIFT_STATFF_LEVEL);
if(_cfg->staff_inten)
val|= BIT_STATFF_INTEN;
if(_cfg->rxff_level == 24)
tmp = 0x3;
else if(_cfg->rxff_level == 16)
tmp = 0x2;
else if(_cfg->rxff_level == 8)
tmp = 0x1;
else
tmp = 0x0;
val |= (tmp << SHIFT_RXFF_LEVEL);
if(_cfg->rxff_inten)
val |= BIT_RXFF_INTEN;
if(_cfg->sof_pol)
val |= BIT_SOF_POL;
if(_cfg->sof_inten)
val |= BIT_SOF_INTEN;
tmp = (_cfg->mclkdiv / 2) - 1;
val |= (tmp << SHIFT_MCLKDIV);
if(_cfg->hsync_pol)
val |= BIT_HSYNC_POL;
if(_cfg->ccir_en)
val |= BIT_CCIR_EN;
if(_cfg->mclken)
val |= BIT_MCLKEN;
if(_cfg->fcc)
val |= BIT_FCC;
if(_cfg->pack_dir)
val |= BIT_PACK_DIR;
if(_cfg->gclk_mode)
val |= BIT_GCLK_MODE;
if(_cfg->inv_data)
val |= BIT_INV_DATA;
if(_cfg->inv_pclk)
val |= BIT_INV_PCLK;
if(_cfg->redge)
val |= BIT_REDGE;
_reg_CSI_CSICR1 = val;
//control reg 3
val = 0x0;
if(_cfg->csi_sup)
val |= BIT_CSI_SUP;
if(_cfg->zero_pack_en)
val |= BIT_ZERO_PACK_EN;
if(_cfg->ecc_int_en)
val |= BIT_ECC_INT_EN;
if(_cfg->ecc_auto_en)
val |= BIT_ECC_AUTO_EN;
_reg_CSI_CSICR3 = val;
//rxfifo counter
_reg_CSI_CSIRXCNT = _cfg->rxcnt;
//2. update global config
memcpy(&g_csi_cfg, _cfg, sizeof(CSI_CFG));
//3. interrupt enable
if(_cfg->module_irq_enable)
{
rt = request_irq(INT_CSI,
csi_irq_handler,
SA_INTERRUPT,
"csi",
"csi");
if(rt)
printk("csi error: irq request fail\n");
}
//4. init status flags
memset(&g_csi_status, 0, sizeof(CSI_CFG));
return;
}
static void csi_module_init(void)
{
unsigned int val;
unsigned int perclk4div = 3; //default set to fclk/3 => 88MHz
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -