📄 csi2c.c
字号:
#include "mx1hw.h"#include "khead.h"#include "csi2c.h"#include "i2c.h"#include "im8803.h"#include "csi.h"//static void port_init_SENSOR(void);static U32 SFCM_capture_DMA(U32 nPixel);static void dma_complete_handler(void);static void dma_error_handler(int error_type);static int gMajor = 0;static U32 *csi_data_buf = 0;//static U32 gSensorClock;int sensorFrameCount = 0;static dmach_t dma_channel;static U32 readSeqNum;static U32 capSeqNum;static U32 SOFseqNum;static U8 stopCapture;static U32 dma_buf_phy_addr;static U32 dma_data_size;static DECLARE_WAIT_QUEUE_HEAD(dma_wait);#include "dma_fun.c"#include "dma.c"// functions and interfacestatic int csi2c_open(struct inode *inode, struct file *filp);static int csi2c_release(struct inode *inode, struct file *filp);static ssize_t csi2c_read(struct file *filp, char *buf, size_t size, loff_t * l);static ssize_t csi2c_write(struct file *filp, const char *buf, size_t size, loff_t * l);static int csi2c_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);struct file_operations csi2c_fops = { open:csi2c_open, release:csi2c_release, read:csi2c_read, write:csi2c_write, ioctl:csi2c_ioctl,};static int csi2c_open(struct inode *inode, struct file *filp){ dprintcsi2c("*** open ***\n"); MOD_INC_USE_COUNT; /* request DMA channel for RxFIFO data */ for (dma_channel = 3; dma_channel < 11; dma_channel++) { if ((request_dma(dma_channel, "CMOS Sensor")) == 0) { printk("dma channel %d granted\n", dma_channel); //Burst length: 32 //Src: 0x00224010(CSI RxFifo) //ByteCount: 153600(240x320x2) //Dest: dma_buf_phy_addr //ReqSrc: 7(CSI) //Rpt: 1 DMA_init(dma_channel, 32, 0x00224010, 153600, dma_buf_phy_addr, 7, 1); request_dma_intr(dma_channel, (callback_t) dma_complete_handler, (err_callback_t) dma_error_handler); break; } } if (dma_channel > 11) printk("*** ERROR: no dma channel is available ! ***\n"); return 0;}static int csi2c_release(struct inode *inode, struct file *filp){ dprintcsi2c("*** close ***\n"); MOD_DEC_USE_COUNT; free_dma_intr(dma_channel); free_dma(dma_channel); return 0;}static ssize_tcsi2c_read(struct file *filp, char *buf, size_t size, loff_t * l){ dprintcsi2c("*** read ***\n"); interruptible_sleep_on(&dma_wait); copy_to_user(buf, csi_data_buf, size); return size;}static ssize_tcsi2c_write(struct file *filp, const char *buf, size_t size, loff_t * l){ dprintcsi2c("*** write ***\n"); return 0;}static intcsi2c_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ unsigned long tmp; tmp = arg; dprintcsi2c("cmd: 0x%08x, arg: 0x%08x\n", cmd, (int) arg); switch (cmd) { case IOCTL_CSI_INIT: break; case IOCTL_I2C_WRITE: dprintcsi2c("I2C write - reg: 0x%02lx, data: 0x%02lx\n", arg >> 8, arg & 0xFF); I2C_write(arg >> 8, arg & 0xFF); break; case IOCTL_I2C_READ: { int rv; dprintcsi2c("I2C read\n"); I2C_read(arg, &rv); return (rv); } break; case IOCTL_SUBSAMPLE: dprintcsi2c("Set subsample: %d\n", (int) arg); //setSubsample(arg); break; case IOCTL_SET_GAIN: dprintcsi2c("Set global gain to %d\n", (int) arg); //setGlobalGain(arg); break; case IOCTL_SET_VF_WIDTH: dprintcsi2c("Set virtual frame width to 0x%04x\n", (int) arg); //setVFwidth(arg); break; case IOCTL_SET_INT_TIME: dprintcsi2c("Set integration time to 0x%04x\n", (int) arg); //setIntegrationTime(arg); break; case IOCTL_DMA_CAPTURE: printk("DMA capture for %d bytes\n", (int) arg); return SFCM_capture_DMA((U32) arg); break; /* case IOCTL_RESET_ASSERT: * (U32 *)PTB_DR |= (0x1 << 18); // RESET asserted break; case IOCTL_RESET_RELEASE: * (U32 *)PTB_DR &= ~(0x1 << 18); // RESET released break; */ case IOCTL_STOP_CAPTURE: *(U32 *) CSI_CTRL_REG1 &= ~0x10000; *(U32 *) (DMA_CCR0 + dma_channel * 0x40) = 0x800; stopCMOScapture(); break; case IOCTL_INC_FRM: { U32 flags = 0; save_flags(flags); cli(); sensorFrameCount++; restore_flags(flags); } break; case IOCTL_MOD_SATURATION: PDEBUG("Set saturation to %d\n", (int) tmp); //set_saturation(tmp); break; } return 0;}//// Test on I2C channel//// Read / write one of the register// compare and verify if the data is correct//U32 I2C_test(void){ U32 rdata; U32 wdata; //generat MCLK to sensor CSI_init(); //init sensor port#ifdef MP3DSC standby_disable(); sensor_reset();#endif#ifdef ADS ADS_standby_disable(); ADS_sensor_reset();#endif //This part test on reading default value read //should read 0x4 I2C_read(0x01, &rdata); PDEBUG("should be 0x01: %08x\n", rdata); /* while(1) { I2C_read(0x09, &rdata); PDEBUG("should be 0x4: %08x\n", rdata); my_delay(); } */ //This part test on the access to Image Core I2C_write(0x01, 0x04); //select Image Core channel wdata = 0x03FF; //least 10 bits can be R/W I2C_write(0x02, wdata); PDEBUG("wdata: %08x\n", wdata); I2C_read(0x02, &rdata); PDEBUG("rdata: %08x\n", rdata); //soft reset I2C_write(0x0D, 0x01); I2C_write(0x0D, 0x00); if (rdata == wdata) { printk("I2C test OK\n"); return 0; //OK } else { printk("I2C test FAIL\n"); return 1; //fail }}static devfs_handle_t devfs_handle;int init_module(){ int result; printk("CSI driver " __DATE__ " / " __TIME__ "\n"); /* register our character device */ result = devfs_register_chrdev(0, "csi2c", &csi2c_fops); if (result < 0) { printk("csi2c driver: Unable to register driver\n"); return -ENODEV; } devfs_handle = devfs_register(NULL, "csi2c", DEVFS_FL_DEFAULT, result, 0, S_IFCHR | S_IRUSR | S_IWUSR, &csi2c_fops, NULL); printk("make node for csi2c with 'mknod csi2c c %d 0'\n", result); gMajor = result; if (request_irq (CSI_IRQ, csi_intr_handler, SA_INTERRUPT, "CSI", NULL)) printk ("*** Cannot register interrupt handler for CSI ! ***\n"); else printk("CSI interrupt handler registered\n"); malloc_buffer(); //I2C_init(); I2C_test(); //TestFrameSize(); CSI_init(); IM8803_QVGA_init4(); //240x320 WOI //IM8803_QVGA_init(); //320x240 Decimation return 0;}void cleanup_module(){ if (gMajor > 0) { devfs_unregister_chrdev(gMajor, "csi2c"); devfs_unregister(devfs_handle); } free_irq(CSI_IRQ, 0); //I2C_cleanup(); free_buffer(); printk("Say goodbye to csi2c\n");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -