📄 csi2c.c
字号:
return 0;} void set_ov7660_reg_rgb565(){ int i; sccb_write(0x12,0x80); // Reset all registers for(i=0;i<2000;i++) delay10us(); sccb_write_check(0x11 ,0x83); sccb_write_check(0x92 ,0x00); sccb_write_check(0x93 ,0x00); sccb_write_check(0x9d ,0x31); sccb_write_check(0x9e ,0x29); sccb_write_check(0x3b ,0x02);//02 for 60Hz, 0a for 50Hz sccb_write_check(0x13 ,0xf2); sccb_write_check(0x10 ,0x00); sccb_write_check(0x00 ,0x00); sccb_write_check(0x01 ,0x80); sccb_write_check(0x02 ,0x80); sccb_write_check(0x13 ,0xf7); sccb_write_check(0x12 ,0x14); sccb_write_check(0x04 ,0x00); sccb_write_check(0x18 ,0x4b); sccb_write_check(0x17 ,0x23); sccb_write_check(0x32 ,0xbf); sccb_write_check(0x19 ,0x02); sccb_write_check(0x1a ,0x7a); sccb_write_check(0x03 ,0x00); sccb_write_check(0x0e ,0x84); sccb_write_check(0x0f ,0x62); sccb_write_check(0x15 ,0x00); sccb_write_check(0x16 ,0x02); sccb_write_check(0x1b ,0x01); sccb_write_check(0x1e ,0x21); sccb_write_check(0x29 ,0x3c);// ;20 for internal regulator sccb_write_check(0x33 ,0x00); sccb_write_check(0x34 ,0x07); sccb_write_check(0x35 ,0x84); sccb_write_check(0x36 ,0x00); sccb_write_check(0x38 ,0x13); sccb_write_check(0x39 ,0x43); sccb_write_check(0x3a ,0x08); sccb_write_check(0x3c ,0x6c); sccb_write_check(0x3d ,0x90); sccb_write_check(0x3f ,0x29); sccb_write_check(0x40 ,0xd1); sccb_write_check(0x41 ,0x20); sccb_write_check(0x6b ,0x0a); sccb_write_check(0xa1 ,0xc8); sccb_write_check(0x69 ,0x80); sccb_write_check(0x43 ,0xf0); sccb_write_check(0x44 ,0x10); sccb_write_check(0x45 ,0x78); sccb_write_check(0x46 ,0xa8); sccb_write_check(0x47 ,0x60); sccb_write_check(0x48 ,0x80); sccb_write_check(0x59 ,0xba); sccb_write_check(0x5a ,0x9a); sccb_write_check(0x5b ,0x22); sccb_write_check(0x5c ,0xb9); sccb_write_check(0x5d, 0x9b); sccb_write_check(0x5e ,0x10); sccb_write_check(0x5f ,0xe0); sccb_write_check(0x60 ,0x85);// ;05 for advanced AWB sccb_write_check(0x61 ,0x60); sccb_write_check(0x9f ,0x9d); sccb_write_check(0xa0 ,0xa0); sccb_write_check(0x4f ,0xae); sccb_write_check(0x50 ,0x26); sccb_write_check(0x51 ,0x08); sccb_write_check(0x52 ,0x1a); sccb_write_check(0x53 ,0xa9); sccb_write_check(0x54 ,0x0f); sccb_write_check(0x55 ,0x05); sccb_write_check(0x56 ,0x46); sccb_write_check(0x57 ,0xcb); sccb_write_check(0x58 ,0x77); sccb_write_check(0x8b ,0xcc); sccb_write_check(0x8c ,0xcc); sccb_write_check(0x8d ,0xcf); sccb_write_check(0x6c ,0x40); sccb_write_check(0x6d ,0x30); sccb_write_check(0x6e ,0x4b); sccb_write_check(0x6f ,0x60); sccb_write_check(0x70 ,0x70); sccb_write_check(0x71 ,0x70); sccb_write_check(0x72 ,0x70); sccb_write_check(0x73 ,0x70); sccb_write_check(0x74 ,0x60); sccb_write_check(0x75 ,0x60); sccb_write_check(0x76 ,0x50); sccb_write_check(0x77 ,0x48); sccb_write_check(0x78 ,0x3a); sccb_write_check(0x79 ,0x2e); sccb_write_check(0x7a ,0x28); sccb_write_check(0x7b ,0x22); sccb_write_check(0x7c ,0x04); sccb_write_check(0x7d ,0x07); sccb_write_check(0x7e ,0x10); sccb_write_check(0x7f ,0x28); sccb_write_check(0x80 ,0x36); sccb_write_check(0x81 ,0x44); sccb_write_check(0x82 ,0x52); sccb_write_check(0x83 ,0x60); sccb_write_check(0x84 ,0x6c); sccb_write_check(0x85 ,0x78); sccb_write_check(0x86 ,0x8c); sccb_write_check(0x87 ,0x9e); sccb_write_check(0x88 ,0xbb); sccb_write_check(0x89 ,0xd2); sccb_write_check(0x8a ,0xe6); sccb_write_check(0x14 ,0x2e); sccb_write_check(0x24 ,0x68); sccb_write_check(0x25 ,0x58); } 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_ov7660(SINT8 flag){ if(flag) _reg_GPIO_DR(GPIOF) |= 0x00200000; else _reg_GPIO_DR(GPIOF) &= ~(0x00200000); return 0;} /* PB12 - avtive hign */SINT32 reset_ov7660(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;} 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_ov7660(1); pwdn_ov7660(0); reset_ov7660(1); for(i=0;i<2000;i++); reset_ov7660(0); for(i=0;i<2000;i++); set_ov7660_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 + -