📄 cc303.c
字号:
/*!****************************************************************************! 05.03.2002 splitted huge cmoscam.c*! FILE NAME : cc303.c*! DESCRIPTION: TBD*//****************** INCLUDE FILES SECTION ***********************************/#include <linux/module.h>#include <linux/sched.h>#include <linux/slab.h>#include <linux/errno.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/string.h>#include <linux/init.h>#include <linux/config.h>#include <asm/system.h>#include <asm/svinto.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/delay.h>#include <asm/uaccess.h>#include <asm/cmoscama.h>#include "cc303.h"#include "cci2c.h"#ifdef CONFIG_ETRAX_CMOSCAM_MCP#include "ccmcp.h"#else#define MCPpresent() 0#endif#ifdef CONFIG_ETRAX_CMOSCAM_ZR32112#include "cczr32112.h"#endif#ifdef CONFIG_ETRAX_CMOSCAM_ZR32212#include "cczr32212.h"#endif#ifdef CONFIG_ETRAX_CMOSCAM_KAC1310#include "cckac1310.h"#endif//#define D(x) x#define D(x)#define D1(x)#define D2(x)#define D3(x)#define D4(x)#define CMOSCAM_MAJOR 126 /* LOCAL/EXPERIMENTAL */static const char cmoscam_name[] = "cmoscam";#define _IOC_CSP0RW_CMD(x) (_IOC_NR(x) >> 4)#define _IOC_CSP0RW_ADR(x) (_IOC_NR(x) & 0xf)#define EXT_DMA_0_START \ *R_EXT_DMA_0_CMD = (extdma0_cmd_shadow |= IO_STATE( R_EXT_DMA_0_CMD, run, start ) )#define EXT_DMA_0_STOP \ *R_EXT_DMA_0_CMD = (extdma0_cmd_shadow &= ~IO_MASK( R_EXT_DMA_0_CMD, run ) )#define RS_MAX_LEN 0x0fffff#define RS_EXTERNAL 0x100000#define RS_INTERNAL 0x300000/* Camera revision dependent defines are here */#ifdef CONFIG_ETRAX_303// Defines for rev0 camera#define MY_MODULE_DESCRIPTION "Elphel model 303 rev 0 camera driver"#define CMOSCAM_DRIVER_NAME "CMOS/MCP camera 303 driver v4.1\n"#define FPGA_DMA_START ccamCROr ( CCAM_BITS(DMA_EN,1) )#define FPGA_DMA_STOP ccamCRAnd (~CCAM_BITS(DMA_EN,1) )#define FPGA_DMA_START_INTERNAL ccamCROr ( CCAM_BITS(DMA_EN,1) )#define EN_INTERRUPT(x) ccamCROr ( CCAM_BITS(INT_M, 1 << x) )#define DIS_INTERRUPT(x) ccamCRAnd (~CCAM_BITS(INT_M, 1 << x) )#define DIS_INTERRUPTS ccamCRAnd (~CCAM_BITS(INT_M, 0xff ) )// program DMA block size#define PROGRAM_BLKSZ(x) ccamCRAndOr(~(((1 << CCAM__BLKSZ__WIDTH)-1) << CCAM__BLKSZ__BITNM) ,\ (((x) & ((1 << CCAM__BLKSZ__WIDTH)-1)) << CCAM__BLKSZ__BITNM) )// program FPGA mclk and others - not implemented in rev "0"#define PROGRAM_CLK_DIV(x)#define PROGRAM_CLK_EN(x)#define PROGRAM_DEPTH(x)#define PROGRAM_SHIFT(x)#define PROGRAM_COLOR(x)#define PROGRAM_AUXCM(x)#else// Defines for Model 303 revA/M camera#define MY_MODULE_DESCRIPTION "Elphel model 303 rev A camera driver"#define CMOSCAM_DRIVER_NAME "CMOS/MCP camera 303M driver v4.1\n"/*#define FPGA_DMA_STOP port_csp0_addr[CCAM_WA_RSLEN]=0#define FPGA_DMA_START port_csp0_addr[CCAM_WA_RSLEN]=\ ((imageParamsR[P_VIDEO] && imageParamsR[P_TRIG])?RS_EXTERNAL:RS_INTERNAL) | \ (RS_MAX_LEN & ((imageParamsR[P_IMAGE_SIZE] >>2) + imageParamsR[P_OVERLAP]))#define FPGA_DMA_START_INTERNAL port_csp0_addr[CCAM_WA_RSLEN]=\ RS_INTERNAL | \ (RS_MAX_LEN & ((imageParamsR[P_IMAGE_SIZE] >>2) + imageParamsR[P_OVERLAP]))*/#define FPGA_DMA_STOP port_csp0_addr[CCAM_WA_RSLEN]=0#define FPGA_DMA_START port_csp0_addr[CCAM_WA_RSLEN]=(testDMA=\ ((imageParamsR[P_VIDEO] && imageParamsR[P_TRIG])?RS_EXTERNAL:RS_INTERNAL) | \ (RS_MAX_LEN & ((imageParamsR[P_IMAGE_SIZE] >>2) + imageParamsR[P_OVERLAP])))#define FPGA_DMA_START_INTERNAL port_csp0_addr[CCAM_WA_RSLEN]=(testDMA=\ RS_INTERNAL | \ (RS_MAX_LEN & ((imageParamsR[P_IMAGE_SIZE] >>2) + imageParamsR[P_OVERLAP])))//testDMA#define EN_INTERRUPT(x) port_csp0_addr[CCAM_WA_INTMASK]= (intm_shadow |= (1<< x ))#define DIS_INTERRUPT(x) port_csp0_addr[CCAM_WA_INTMASK]= (intm_shadow &= ~(1<< x ))#define DIS_INTERRUPTS port_csp0_addr[CCAM_WA_INTMASK]= (intm_shadow = 0)// program DMA block size#define PROGRAM_BLKSZ(x) port_csp0_addr[CCAM_WA_WBLKSZ]= x// program FPGA mclk#define PROGRAM_CLK_DIV(x) CCAM_SETFIELD(CLKDIV, x )// enable clock to sensor#define PROGRAM_CLK_EN(x) CCAM_SETFIELD(CLKEN, x )// program depth#define PROGRAM_DEPTH(x) CCAM_SETFIELD(DEPTH,(( x )==4)? 2 :((( x )==8)? 1 : 0))// program left shift#define PROGRAM_SHIFT(x) CCAM_SETFIELD(SHFT,(( x )==3)? 3 :((( x )==2)? 0 : ((( x )==1)? 1 : 2)))// program color compressor mode#define PROGRAM_COLOR(x) CCAM_SETFIELD(COLOR, x)// program aux clock (0/1/20MHz)#define PROGRAM_AUXCM(x) CCAM_SETFIELD(AUXCM, x)#endif#define CCAM_ARO_ON \ ccamCROr( CCAM_BITS(ARO,1) )#define CCAM_ARO_OFF \ ccamCRAnd(~CCAM_BITS(ARO,1) )#define CCAM_ARST_ON \ ccamCROr( CCAM_BITS(ARST,1) )#define CCAM_ARST_OFF \ ccamCRAnd(~CCAM_BITS(ARST,1) )#define CCAM_MRST_OFF \ ccamCROr( CCAM_BITS(MRST,1) )#define CCAM_MRST_ON \ ccamCRAnd(~CCAM_BITS(MRST,1) )// output "EXPOS" is used to communicate with FPGA on MCP board, else - as external output#define CCAM_EXP_EN \ if (!MCPpresent()) ccamCRAnd(~(CCAM_BITS(EXP,1) | CCAM_BITS(EXPPOL,1) ) )#define CCAM_EXP_DIS \ if (!MCPpresent()) ccamCROr ( CCAM_BITS(EXP,1) | CCAM_BITS(EXPPOL,1) )#define CCAM_MAXMINOR 10/* * Initial parameters, common for all for all sensors */static unsigned long default_common[]= \ { P_SENSOR, 0, P_TRIG, 0, P_EXPOS, 1, P_DMA_SZ, 0x0f, // default DMA blok size = 16 words P_DMA_LOOP, CCAM_DMA_SIZE, // will be updated P_OVERLAP, 0, // (will be overwritten) Rolling Shutter DMA length (number of words to be acquired over frame size) P_AUXCM, 0, // 0 on auxclk pin P_BIN_HOR, 0, // no binning h P_BIN_VERT, 0, // no binning h P_COLOR, 0, // monochrome mode P_VIDEO, 0, // still mode P_TEST, 0, // normal mode P_MCLK, 4, // divide by 4 -- FPGA, divide by 80MHz by P_MCLK P_MCLK_DIS, 0, // enable MCLK to sensor P_DCM_HOR, 0, // 0 - no decimation, 1 - 1/2, 2 - 1/4, 3 - 1/8, etc. P_DCM_VERT, 0, // 0 - no decimation, 1 - 1/2, 2 - 1/4, 3 - 1/8, etc. P_BITS, 10, // 10-bit mode P_SHIFTL, 0, // no pre-scaling P_VEXPOS, 0, P_GAINR, 0, P_GAING, 0, P_GAINB, 0, P_GAINGB, 0 };/* really huge static DMA buffer (1288+8)*1032/3=445824 long-s *///static unsigned long ccam_dma_buf[CCAM_DMA_SIZE + PAGE_SIZE]; //to align to page laterstatic unsigned long ccam_dma_buf0[CCAM_DMA_SIZE + PAGE_SIZE] __attribute__ ((aligned (PAGE_SIZE)));static etrax_dma_descr ccam_dma_descr[CCAM_DESCR_SIZE];static unsigned long *ccam_dma_buf;static unsigned long DMABufferLength;static int minors[CCAM_MAXMINOR+1]; // each minor can be opened only oncestatic unsigned char sensor_i2c_addr; // 0x60 for ZR32112, ZR32212; 0x66 for KAC1310static unsigned char sensor_i2c_regs[0x100]; // was 0x17 -- only first 32 accessible through ioctl// static unsigned long otherParamsRW[32]; // other parameres accessible through ioctl - 5-bit address// static unsigned long otherParamsRO[16]; // other parameres accessible through ioctl (read only)static unsigned long imageParamsW[64]; // Sensor parameters (user write)static unsigned long imageParamsR[64]; // Sensor Parameters (user read)static int blFrame=0; // black Framestatic int testDMA=0; // just testing DMA commands assigned in IRQ routinestatic volatile unsigned long ccam_cr_shadow=0;static unsigned long extdma0_cmd_shadow;#ifndef CONFIG_ETRAX_303static unsigned long intm_shadow=0;#endif/* * Functios used in only in this file */static int getCamSeqState(void);static int getCamSeqCount(void);static void setCamSeqState(int v);static void setCamSeqCount(int v);static void setCamSeqPreCount(int v);static void initCamIRQs(void);static void setCamSeq(int expTime);static void camSeq_interrupt(int irq, void *dev_id, struct pt_regs * regs);static void ccamInitWndSize (void);static int csp0rw_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);static int ccam_DMA_ioctl(struct inode *inode, struct file *file,unsigned int cmd, unsigned long arg);static int cmoscam_open_raw(struct inode *inode, struct file *filp);static int cmoscam_open_dma(struct inode *inode, struct file *filp);static int cmoscam_mmap_dma (struct file *filp, struct vm_area_struct *vma);static int cmoscam_open(struct inode *inode, struct file *filp);static int cmoscam_release(struct inode *inode, struct file *filp);static int cmoscam_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);static loff_t cmoscam_lseek(struct file * file, loff_t offset, int orig);static ssize_t cmoscam_read(struct file * file, char * buf, size_t count, loff_t *off);static ssize_t cmoscam_write(struct file * file, const char * buf, size_t count, loff_t *off);static int cmoscam_mmap (struct file *filp, struct vm_area_struct *vma);static ssize_t cmoscam_raw_read(struct file * file, char * buf, size_t count, loff_t *off);static ssize_t cmoscam_raw_read10(struct file * file, char * buf, size_t count, loff_t *off);static ssize_t cmoscam_raw_read8(struct file * file, char * buf, size_t count, loff_t *off);static ssize_t cmoscam_raw_read4(struct file * file, char * buf, size_t count, loff_t *off);static loff_t cmoscam_raw_lseek(struct file * file, loff_t offset, int orig);static int __init cmoscam_init(void);int setDMABuffer(unsigned long length);int init_sensor(void);int programSensor(void);#ifdef CONFIG_ETRAX_303#define programEncoder(x) // just do nothing#elsevoid programEncoder (void);#endifstatic struct file_operations cmoscam_fops = { owner: THIS_MODULE, llseek: cmoscam_lseek, read: cmoscam_read, write: cmoscam_write, ioctl: cmoscam_ioctl, open: cmoscam_open, mmap: cmoscam_mmap, release: cmoscam_release,};/* * Functions used in other files (implementation) */unsigned char get_sensor_i2c_regs(int n) {return sensor_i2c_regs[n] ;}unsigned long get_imageParamsR (int n) {return imageParamsR[n];}unsigned long get_imageParamsW (int n) {return imageParamsW[n];}unsigned char get_sensor_i2c_addr(void) {return sensor_i2c_addr ;}void set_sensor_i2c_regs(int n, unsigned char d) {sensor_i2c_regs[n]=d;}void set_imageParamsR (int n, unsigned long d) {imageParamsR[n]=d;}void set_imageParamsW (int n, unsigned long d) {imageParamsW[n]=d;}void set_sensor_i2c_addr( unsigned char d) {sensor_i2c_addr=d;}void ccamCRAnd(unsigned long d) { unsigned long flags; save_flags(flags); cli(); port_csp0_addr[CCAM_WA_WCTL]= (ccam_cr_shadow &= d); restore_flags(flags);}void ccamCROr(unsigned long d) { unsigned long flags; save_flags(flags); cli(); port_csp0_addr[CCAM_WA_WCTL]= (ccam_cr_shadow |= d); restore_flags(flags);}void ccamCRXor(unsigned long d) { unsigned long flags; save_flags(flags); cli(); port_csp0_addr[CCAM_WA_WCTL]= (ccam_cr_shadow ^= d); restore_flags(flags);}void ccamCRAndOr(unsigned long d_and, unsigned long d_or) { unsigned long flags; save_flags(flags); cli(); ccam_cr_shadow &= d_and; port_csp0_addr[CCAM_WA_WCTL]= (ccam_cr_shadow |= d_or); restore_flags(flags);}unsigned long ccamGetCR(void) {return ccam_cr_shadow;}void writeSensorDefaults(unsigned long * data, int count) { int i; for (i=0;i<count;i++) imageParamsW[data[2*i]]=data[2*i+1]; imageParamsR[P_PARS_CHANGED]=1;}int readSensorReg(unsigned char ra, int mode) { // mode=0 - shadow, 1 - actual register int i; if(mode) { if ((i= i2c_writeData(0, sensor_i2c_addr & 0xfe, &ra, 1))) return -i; // error if ((i= i2c_readData(0, sensor_i2c_addr | 0x01, &sensor_i2c_regs[ra], 1))) return -i-1000; // error } return (int)sensor_i2c_regs[ra];}int writeSensorReg(unsigned char ra, unsigned char rd, int uncond) { // returns -1 (error) , 1 - set, 0 - did not have to change int i, res; unsigned char d[2]; if (!uncond && (sensor_i2c_regs[ra] == rd)) return 0; d[0]=ra; d[1]=rd; if (i2c_writeData(0, sensor_i2c_addr, &d[0], 2)) { // was 0x60 i=d[0]; res=d[1]; printk ("\tError writing I2C register %2x with data %2x\r\n",i,res); return -1; } sensor_i2c_regs[ra] = rd; return 1;}/* ++++++++++++++++++++++++++++ IRQ/camseq related stuff +++++++++++++++++++++++++++++++++++ */// parameters, copied from Verilog file "emultasks.v"// define interrupt numbers#define nint_xint 0 // external enterrupt#ifdef CONFIG_ETRAX_303#define nint_hact_end 1 // end of HACT pulse#else#define nint_xferovr 1 // DMA xfer over#endif#define nint_vact_end 2 // end of VACT pulse (DMA end?)#define nint_vact_start 3 // beginning of VACT pulse (end of exposure, DMA start)#define nint_seq_xtrn 4 // sequencer serviced external trigger#define nint_wfirq 5 // write/increment of sequencer RA failed because sequencer branched due to external trigger#define nint_seq_ovr 6 // sequencer external-trigger-interrupt happend before INTA to normal sequencer interrupt#define nint_seq_norm 7 // sequencer normal interrupt
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -