📄 csi2c.c
字号:
return 0;}void set_ov7649_reg_yuv422(){ int i; sccb_write(0x12,0x80); // Reset all registers for(i=0;i<1000;i++) delay10us(); sccb_write_check(0x03,0xA4); sccb_write_check(0x04,0x30); sccb_write_check(0x05,0x88); sccb_write_check(0x06,0x60); sccb_write_check(0x11,0x00); sccb_write_check(0x12,0x05); sccb_write_check(0x13,0xA3); sccb_write_check(0x14,0x24); //0x04 for VGA, 0x24 for QVGA sccb_write_check(0x15,0x04); sccb_write_check(0x1F,0x41); sccb_write_check(0x20,0xD0); sccb_write_check(0x23,0xDE); sccb_write_check(0x24,0xA0); sccb_write_check(0x25,0x80); sccb_write_check(0x26,0x32); sccb_write_check(0x27,0xE2); sccb_write_check(0x28,0x20); sccb_write_check(0x2A,0x11); sccb_write_check(0x2B,0x00); sccb_write_check(0x2D,0x05); sccb_write_check(0x2F,0x9C); sccb_write_check(0x30,0x00); sccb_write_check(0x31,0xC4); sccb_write_check(0x60,0x86); sccb_write_check(0x61,0xE0); sccb_write_check(0x62,0x88); sccb_write_check(0x63,0x11); sccb_write_check(0x64,0x89); sccb_write_check(0x65,0x00); sccb_write_check(0x67,0x14); //0x94 for YCrCb, 0x14 for YUV sccb_write_check(0x68,0x7A); sccb_write_check(0x69,0x04); sccb_write_check(0x6C,0x11); sccb_write_check(0x6D,0x33); sccb_write_check(0x6E,0x22); sccb_write_check(0x6F,0x00); sccb_write_check(0x74,0x20); sccb_write_check(0x75,0x0E); sccb_write_check(0x77,0xC4); } void set_ov7649_reg_rgb565(){ int i; sccb_write(0x12,0x80); // Reset all registers for(i=0;i<2000;i++) delay10us(); sccb_write_check(0x03,0xA4); sccb_write_check(0x04,0x34); sccb_write_check(0x05,0x88); sccb_write_check(0x06,0x80); //default 0x60 sccb_write_check(0x11,0x00); //0x00 for 30fps, 0x01 for 15fps sccb_write_check(0x12,0x5D); //mirror image enable sccb_write_check(0x13,0xA3); sccb_write_check(0x14,0x24); //0x04 for VGA, 0x24 for QVGA sccb_write_check(0x15,0x05); sccb_write_check(0x1F,0x51); sccb_write_check(0x20,0xD0); sccb_write_check(0x23,0xDE); sccb_write_check(0x24,0x90); //default 0x80 sccb_write_check(0x25,0x80); //default 0x60 sccb_write_check(0x26,0xC2); //default 0xC2 sccb_write_check(0x27,0xE2); sccb_write_check(0x28,0x20); sccb_write_check(0x2A,0x11); sccb_write_check(0x2B,0x00); sccb_write_check(0x2D,0x05); sccb_write_check(0x2F,0x9C); sccb_write_check(0x30,0x00); sccb_write_check(0x31,0xC4); sccb_write_check(0x60,0xA6); sccb_write_check(0x61,0x68); sccb_write_check(0x62,0x88); sccb_write_check(0x63,0x11); sccb_write_check(0x64,0x88); sccb_write_check(0x65,0x00); sccb_write_check(0x67,0x94); //0x94 for YCrCb, 0x14 for YUV sccb_write_check(0x68,0x7A); sccb_write_check(0x69,0x04); //0x04 for 1x, 0x0C for 1.5x sccb_write_check(0x6C,0x11); sccb_write_check(0x6D,0x33); sccb_write_check(0x6E,0x22); sccb_write_check(0x6F,0x00); sccb_write_check(0x74,0x20); sccb_write_check(0x75,0x0E); sccb_write_check(0x77,0xC4); sccb_write_check(0x71,0x40); //PCLK gated by HREF } SINT32 init_control_signal(void){ /* PWDN: PF21(~CS4), RESET:PF22(~CS5) */ /* Set GPIO functionality */ _reg_GPIO_GIUS(GPIOF) |= 0x00600000; /* Set output configure register */ _reg_GPIO_OCR2(GPIOF) |= 0x00003C00; /* Set direction configure register,output */ _reg_GPIO_DDIR(GPIOF) |= 0x00600000; return 0;}/* PB13 - avtive hign */SINT32 pwdn_ov7649(SINT8 flag){ if(flag) _reg_GPIO_DR(GPIOF) |= 0x00200000; else _reg_GPIO_DR(GPIOF) &= ~(0x00200000); return 0;} /* PB12 - avtive hign */SINT32 reset_ov7649(SINT8 flag){ if(flag) _reg_GPIO_DR(GPIOF) |= 0x00400000; else _reg_GPIO_DR(GPIOF) &= ~(0x00400000); return 0;} void enable_sof_interrupt(){ _reg_CSI_CSISR = 0x10000; //clear last SOF irq _reg_CSI_CSICR1 |= 0x10000; //enable SOF intr}void disable_sof_interrupt(){ _reg_CSI_CSICR1 &= ~0x10000; //disable SOF intr}static int csi2c_open(struct inode *inode, struct file *filp){ MOD_INC_USE_COUNT; return 0;}static int dma_init(){ dma_request_t dma; _reg_DMA_DCR |= 0x01; //Enable DMA module if(mx_request_dma(&_gDmaChanel,"CSI")) { printk("Request Dma Fail\n"); }else { printk("Dma Channel is %d\n",_gDmaChanel); memset(&dma,0,sizeof(dma_request_t)); dma.sourceType=DMA_TYPE_FIFO; dma.sourceAddr=(u32 *)0x80000010; dma.request = DMA_REQ_CSI_RX; dma.destAddr=(u32 *)dma_buf_phy_addr; dma.destType=DMA_TYPE_LINEAR; dma.destPort=DMA_MEM_SIZE_32; dma.count=QVGA_SIZE; dma.burstLength=64; dma.callback=(dma_callback_t)dma_complete_handler; mx_dma_set_config(_gDmaChanel,&dma); } return 0;}static int csi2c_release(struct inode *inode, struct file *filp){ MOD_DEC_USE_COUNT; if(_gDmaChanel>=0) { mx_free_dma(_gDmaChanel); _gDmaChanel=-1; } return 0;}static ssize_t csi2c_read(struct file *filp, char *buf, size_t size, loff_t *l){ g_bad_frame = 0; //number_sof = 0; enable_sof_interrupt(); if(!interruptible_sleep_on_timeout(&g_capture_wait,500)) { printk("\nread time out\n"); return -1; } // if(g_bad_frame)// return -1; copy_to_user(buf, csi_data_buf, size); return size;}static ssize_t csi2c_write(struct file *filp, const char *buf, size_t size, loff_t *l){ return 0;}static int malloc_buffer(){ long i; if ((csi_data_buf = (UINT32 *)__get_free_pages(GFP_KERNEL, 7))) // 256 pages = 128x4K = 512K { dma_buf_phy_addr = virt_to_phys((void *)csi_data_buf); } else { printk("*** ERROR: cannot allocate buffer memory for driver ! ***\n"); return -1; } for(i=0;i<QVGA_SIZE/4;i++) csi_data_buf[i] = 0x44332211; return 0;}static void free_buffer(){ if (csi_data_buf) __free_pages((void *)csi_data_buf,7); // 512K}static int csi2c_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ return 0;}static void dma_complete_handler(){ //printk("dma end!\n"); _reg_DMA_CCR(_gDmaChanel) = 0x800; // disable DMA channel _reg_DMA_DISR = (1 << _gDmaChanel); // clear DMA channel number_dma++; if(_reg_CSI_CSISR) g_bad_frame = 1; if(number_dma != number_sof) g_bad_frame = 1; //printk("sof=%d,dma=%d\n",number_sof,number_dma); /* if(flag) { PA_DR |= 0x04; flag = 0; } else { PA_DR &= ~0x04; flag = 1; } printk("\n%d, %d\n",number_sof,number_dma);*/ wake_up_interruptible(&g_capture_wait); }SINT32 csi_init(){ disable_sof_interrupt(); _reg_CRM_PCDR1 &= 0xc0ffffff; _reg_CRM_PCDR1 |= 0x02000000; //PerClk4 = MPLL/3 _reg_CRM_PCCR0 |= 0x80000000; _reg_CRM_PCCR0 |= 0x00400000; _reg_GPIO_GIUS(GPIOB) &= ~0x3FFC00; //disable GPIO _reg_GPIO_GPR(GPIOB) &= ~0x3FFC00; _reg_CSI_CSICR1=0; //module reset _reg_CSI_CSICR1 |= 0x2; //latch on rising edge _reg_CSI_CSICR1 |= 0x10; //gated clock mode _reg_CSI_CSICR1 |= 0x800; //hsync active mode _reg_CSI_CSICR1 |= 0x100; //sync FIFO clear _reg_CSI_CSICR1 |= 0x1200; //MCLK = PerCLK4/4 _reg_CSI_CSICR1 |= 0x40000000; //SOF rising edge _reg_CSI_CSICR1 |= 0x20000; //SOF rising edge _reg_CSI_CSICR1 |= 0x10000; //SOF INT //_reg_CSI_CSICR1 |= 0x40000; //RXFF int _reg_CSI_CSICR1 |= 0x100000; //RXFF level =16; //_reg_CSI_CSICR1 |= 0x1000000; //RXFF overflow int //_reg_CSI_CSICR1 |= 0x80000000;//2 byte of 4 byte swap //_reg_CSI_CSICR1 |= 0x80; //big endian disable_sof_interrupt(); return 0;} //number_dma++; static void csi_intr_handler(){ if(_reg_CSI_CSISR & 0x10000) // SOF intr ? {// printk("\nSOF interrupt\n"); _reg_CSI_CSISR = 0x10000; // clear SOF intr // CSI_STS_REG |= 0x06; //Clear rxfifo //_reg_DMA_CCR(dma_channel) = 0x800; // disable DMA channel if(_gDmaChanel>=0) mx_dma_start(_gDmaChanel); number_sof++; //if(number_sof == 1000) disable_sof_interrupt(); return; } printk("*** unknown interrupt ***\n"); return;}static devfs_handle_t devfs_handle;int init_module(){ int result,i; UINT8 ret; /* 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;// iCaptureDone = 1; 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(); init_control_signal(); sccb_init(); csi_init(); dma_init(); pwdn_ov7649(1); pwdn_ov7649(0); reset_ov7649(1); for(i=0;i<2000;i++); reset_ov7649(0); for(i=0;i<2000;i++); set_ov7649_reg_rgb565(); delay10us(); disable_sof_interrupt(); return 0;}void cleanup_module(){ if (gMajor > 0){ devfs_unregister_chrdev(gMajor, "csi2c"); devfs_unregister(devfs_handle); } free_irq(CSI_IRQ, 0); free_buffer(); printk("Say goodbye to csi2c\n");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -