📄 cc303.c
字号:
return count;}static ssize_t cmoscam_raw_read4(struct file * file, char * buf, size_t count, loff_t *off) { unsigned long p,bp,dp,fs,x,l,n,bw; char * bccam_dma_buf= (char *) ccam_dma_buf;//imageParamsR[P_LPR]// printk("cmoscam_raw_read: buf address=%x count=%x\r\n",(long) buf, (long) count); bw=imageParamsR[P_ACTUAL_WIDTH]; if (bw & 1) bw++; // byte align bw=bw>>1; // in bytes fs=(bw*imageParamsR[P_ACTUAL_HEIGHT]); p = file->f_pos;// printk ("p= %x imageParamsR[P_IMAGE_SIZE]=%x file size=%x\r\n",p,imageParamsR[P_IMAGE_SIZE],fs); if(p >= fs) return -EFAULT; if( (p + count) > fs) { /* truncate count */ count = fs - p; }// line length may be not aligned to 32-bit words l=imageParamsR[P_LPR]<<2; n=p/bw; x=p-n*bw; dp=n*l+x; //copy first line n=bw-x; if (n>count) n=count; bp=0; while (bp<count) { for (;dp<n;bp++) buf[bp]=bccam_dma_buf[dp++]; dp+=(l-bw); n=bw; if (n>(count-bp)) n=count-bp; } file->f_pos += count;// printk("cmoscam_raw_read returned %x\r\n", count); return count;}static loff_t cmoscam_raw_lseek(struct file * file, loff_t offset, int orig){/* * orig 0: position from begning of eeprom * orig 1: relative from current position * orig 2: position from last eeprom address */ unsigned long fs;//printk("cmoscam_raw_lseek: orig= %x\r\n",orig); fs=((imageParamsR[P_ACTUAL_WIDTH]*imageParamsR[P_ACTUAL_HEIGHT]) << 1); switch (orig) { case 0: file->f_pos = offset; break; case 1: file->f_pos += offset; break; case 2: file->f_pos = fs - offset; break; default: return -EINVAL; } /* truncate position */ if (file->f_pos < 0) { file->f_pos = 0; return(-EOVERFLOW); } if (file->f_pos >= fs) { file->f_pos = fs - 1; return(-EOVERFLOW); } return ( file->f_pos );}// **************************************************************static int __init cmoscam_init(void){ extern void init_ioremap(void); int i,res;// unsigned long dmaArrIndex;// unsigned long dai;// unsigned char data[2]; ccam_cr_shadow=0; res = register_chrdev(CMOSCAM_MAJOR, cmoscam_name, &cmoscam_fops); if(res < 0) { printk(KERN_ERR "ccam: couldn't get a major number.\n"); return res; } printk(CMOSCAM_DRIVER_NAME); ccam_dma_buf=ccam_dma_buf0; if (((unsigned long)(&ccam_dma_buf[0])) & (PAGE_SIZE-1)) { ccam_dma_buf=(unsigned long *) (((unsigned long)(&ccam_dma_buf[0]) & ~(PAGE_SIZE-1)) + PAGE_SIZE); printk("+++++++++++ should not get here - why??? \n"); }// else printk("++++++++++ remove this alingment alltogether - not needed anymore!!!\n"); for (i=0;i<=CCAM_MAXMINOR;i++) minors[i]=0; init_ioremap();// Initialize genconfig and it's shadow - needed only once printk("Initializing genconfig/DMA registers\n"); genconfig_shadow = ( (genconfig_shadow & ~IO_MASK(R_GEN_CONFIG, dma5) ) | ( IO_STATE( R_GEN_CONFIG, dma5, extdma0 ) ) ); *R_GEN_CONFIG = genconfig_shadow;// additional configuration for external dma 0 *R_EXT_DMA_0_ADDR = 0x90000000; // csp0, uncashed extdma0_cmd_shadow = \ IO_STATE( R_EXT_DMA_0_CMD, cnt, disable ) | // disable transfer counter IO_STATE( R_EXT_DMA_0_CMD, rqpol, ahigh ) | // DREQ active high IO_STATE( R_EXT_DMA_0_CMD, apol, ahigh ) | // DACK active high IO_STATE( R_EXT_DMA_0_CMD, rq_ack, burst ) | // burst mode IO_STATE( R_EXT_DMA_0_CMD, wid, dword ) | // 32-bit mode IO_STATE( R_EXT_DMA_0_CMD, dir, input ) | // input mode IO_STATE( R_EXT_DMA_0_CMD, run, stop ); *R_EXT_DMA_0_CMD = extdma0_cmd_shadow; // initialize static DMA descriptor list DMABufferLength=0;// setDMABuffer(CCAM_DMA_SIZE); // just init to the longest size - will be called from programSensor from init_sensor init_sensor(); programEncoder();// Init MCP here#ifdef CONFIG_ETRAX_CMOSCAM_MCP if (MCP_initmodule()== 0) printk ("MCP module initialized\r\n"); else printk ("no MCP module detected\r\n");#endif printk("after MCP_initmodule ccam_cr_shadow=%lx, MCPpresent()=%x\n\r",ccam_cr_shadow,MCPpresent()); initCamIRQs(); printk("after initCamIRQs ccam_cr_shadow=%lx\n\r",ccam_cr_shadow); return 0;}int setDMABuffer(unsigned long length) { unsigned long dai; int i=0; if (length>CCAM_DMA_SIZE) return -1; if (length == DMABufferLength) return 0;// Stop DMA (just in case) EXT_DMA_0_STOP; for (dai=0; dai < length; dai+=0x4000) {/* printk("dai=%x &ccam_dma_buf[dai]=%x (unsigned long) virt_to_phys (&ccam_dma_buf[dai])=%x\r\n",dai,\ (unsigned long) &ccam_dma_buf[dai], (unsigned long) virt_to_phys (&ccam_dma_buf[dai])); */ ccam_dma_descr[i].buf= ((unsigned long) virt_to_phys (&ccam_dma_buf[dai])) | 0x80000000; ccam_dma_descr[i].hw_len= 0; ccam_dma_descr[i].status= 0; if (dai + 0x4000 >= length) { //last descriptor ccam_dma_descr[i].sw_len= ((dai + 0x4000 - length) & 0x3fff) << 2; ccam_dma_descr[i].ctrl= 1; // last in list ccam_dma_descr[i].next= // let's loop it (just in case) ((unsigned long) virt_to_phys (&ccam_dma_descr[0])) | 0x80000000; } else { // not the last one ccam_dma_descr[i].sw_len= 0; ccam_dma_descr[i].ctrl= 0; ccam_dma_descr[i].next= ((unsigned long) virt_to_phys (&ccam_dma_descr[i+1])) | 0x80000000; } i++; } DMABufferLength=length; return 0;}int init_sensor(void) { int i; printk("removing MRST from the sensor, setting DMA burst size, setting MCLK to 20MHz\n"); ccamCRAndOr(0,0); // just clear control register CCAM_MRST_OFF; PROGRAM_CLK_DIV(2) ; PROGRAM_CLK_EN(1); PROGRAM_BLKSZ(0x10); writeSensorDefaults(&default_common[0],sizeof(default_common)/sizeof(default_common[0])/2); // set common defaults for (i=0;i<256;i++) sensor_i2c_regs[i]=0; // shadow registers#ifdef CONFIG_ETRAX_CMOSCAM_ZR32112 if (imageParamsR[P_SENSOR]==0) init_ZR32112(); // try ZR32112#endif#ifdef CONFIG_ETRAX_CMOSCAM_ZR32212 if (imageParamsR[P_SENSOR]==0) init_ZR32212(); // try ZR32212#endif#ifdef CONFIG_ETRAX_CMOSCAM_KAC1310 if (imageParamsR[P_SENSOR]==0) init_KAC1310(); // try KAC-1310#endif if (imageParamsR[P_SENSOR]==0) { printk("No image sensor found\n"); return -1; } else return programSensor();}int programSensor(void){ // program appropriate sensor int i=-1; unsigned long flags;// remove disabling irqs if desired save_flags(flags); cli(); if (imageParamsR[P_PARS_CHANGED]) {// TODO: stop sensor if running before writing parameters ??? imageParamsR[P_DMA_VALID]=0;// process common parameters (not sensor specific)//P_BAYER imageParamsR[P_BAYER]=imageParamsW[P_BAYER]; // TODO: remove imageParamsR[P_DMA_SZ]=(imageParamsW[P_DMA_SZ] < 0x3f)? imageParamsW[P_DMA_SZ]:0x3f; imageParamsR[P_EXPOS]= (imageParamsW[P_EXPOS]>0)?imageParamsW[P_EXPOS]:1; imageParamsR[P_OVERLAP]=imageParamsW[P_OVERLAP];// reset videomode if it was on and now off if (imageParamsR[P_VIDEO] && !imageParamsW[P_VIDEO]) { imageParamsR[P_VIDEO]=0; setCamSeq(0); // reset sequencer state, toggle ARST } imageParamsR[P_VIDEO]= imageParamsW[P_VIDEO];#ifdef CONFIG_ETRAX_303 imageParamsR[P_TRIG]= (imageParamsW[P_TRIG] && (imageParamsW[P_VIDEO]==0))?1:0; // no xtern trigger in video mode for Rev "0" imageParamsR[P_BITS]= 10; imageParamsR[P_SHIFTL]=0; imageParamsR[P_AUXCM]=0; imageParamsR[P_MCLK]= 4; imageParamsR[P_MCLK_DIS]= 0;#else imageParamsR[P_TRIG]= imageParamsW[P_TRIG]; imageParamsR[P_BITS]= (imageParamsW[P_BITS] < 5)? 4 : (imageParamsW[P_BITS] < 9)? 8: 10; // TODO: add DMA size support imageParamsR[P_SHIFTL]=(imageParamsW[P_SHIFTL] < 3)? imageParamsW[P_SHIFTL] : 3; imageParamsR[P_AUXCM]=(imageParamsW[P_AUXCM] < 2)? imageParamsW[P_AUXCM] : 2; imageParamsR[P_MCLK]= (imageParamsW[P_MCLK]<129)?((imageParamsW[P_MCLK]>1)?imageParamsW[P_MCLK]:2):129; imageParamsR[P_MCLK_DIS]= imageParamsW[P_MCLK_DIS];#endif// MD(printk ("imageParamsR[P_VIDEO]= %x, imageParamsW[P_VIDEO]= %x\r\n",imageParamsR[P_VIDEO],imageParamsW[P_VIDEO]));// set MCLK to 20MHz (for I2C, etc)// program FPGA mclk PROGRAM_CLK_DIV(2); PROGRAM_CLK_EN(1);// process sensor specific parameters switch (imageParamsR[P_SENSOR] & SENSOR_MASK) {#ifdef CONFIG_ETRAX_CMOSCAM_ZR32112 case SENSOR_ZR32112: {i=program_ZR32112();break;}#endif#ifdef CONFIG_ETRAX_CMOSCAM_ZR32212 case SENSOR_ZR32212: {i=program_ZR32212();break;}#endif#ifdef CONFIG_ETRAX_CMOSCAM_KAC1310 case SENSOR_KAC1310: {i=program_KAC1310();break;}#endif }// adjust exposure to variable MCLK if (imageParamsR[P_MCLK]!=4) imageParamsR[P_EXPOS]= (imageParamsR[P_EXPOS]<<2)/imageParamsR[P_MCLK]; if (imageParamsR[P_EXPOS]<1) imageParamsR[P_EXPOS]=1;// program FPGA mclk PROGRAM_CLK_DIV( imageParamsR[P_MCLK]-2 ); PROGRAM_CLK_EN( 1-imageParamsR[P_MCLK_DIS] ); ccamInitWndSize();// program DMA block size PROGRAM_BLKSZ(imageParamsR[P_DMA_SZ]);// program depth PROGRAM_DEPTH(imageParamsR[P_BITS]);// program shift PROGRAM_SHIFT( (imageParamsR[P_BITS]==10) ? 2 : imageParamsR[P_SHIFTL] );// program color PROGRAM_COLOR(imageParamsR[P_COLOR]); // set in program_XXX// program auxclk PROGRAM_AUXCM(imageParamsR[P_AUXCM]);// program DMA buffer length 1 - 1 frame, 2 - 2 frames..15 - 15 frames, else - as specified.// imageParamsR[P_IMAGE_SIZE] calculated in ccamInitWndSize() imageParamsR[P_DMA_LOOP]=(imageParamsW[P_DMA_LOOP] > 15) ?\ imageParamsW[P_DMA_LOOP]: (imageParamsW[P_DMA_LOOP] * imageParamsR[P_IMAGE_SIZE]); setDMABuffer(imageParamsR[P_DMA_LOOP]); imageParamsR[P_PARS_CHANGED]=0; } imageParamsR[P_UPDATE]=1; // in sync imageParamsW[P_UPDATE]=0; // not needed restore_flags(flags);// restart video mode (skip frame) if parameters were actually changed in sensor's registers if ((i>0) && imageParamsR[P_VIDEO] ) setCamSeq(2); // start waiting for frame to skip return i;}// **************************************************************static void ccamInitWndSize (void) { int i,ppl; switch (imageParamsR[P_SENSOR] & SENSOR_MASK) {#ifdef CONFIG_ETRAX_CMOSCAM_ZR32112 case SENSOR_ZR32112: {ccamInitWndSizeZR32112();break;}#endif#ifdef CONFIG_ETRAX_CMOSCAM_ZR32212 case SENSOR_ZR32212: {ccamInitWndSizeZR32212();break;}#endif#ifdef CONFIG_ETRAX_CMOSCAM_KAC1310 case SENSOR_KAC1310: {ccamInitWndSizeKAC1310();break;}#endif } switch (imageParamsR[P_BITS]) { case 10: {ppl=3;break;} case 8: {ppl=4;break;} case 4: {ppl=8;break;} default: {ppl=3;break;} } i=imageParamsR[P_ACTUAL_WIDTH]/ppl; imageParamsR[P_LPR] = (ppl*i == imageParamsR[P_ACTUAL_WIDTH])? i: i+1; imageParamsR[P_IMAGE_SIZE] = (imageParamsR[P_LPR] * imageParamsR[P_ACTUAL_HEIGHT]) << 2; D2(printk("imageParamsR[P_ACTUAL_WIDTH]= %d\r\n",imageParamsR[P_ACTUAL_WIDTH])); D2(printk("imageParamsR[P_ACTUAL_HEIGHT]=%d\r\n",imageParamsR[P_ACTUAL_HEIGHT])); D2(printk("imageParamsR[P_LPR]= %d\r\n",imageParamsR[P_LPR])); D2(printk("imageParamsR[P_IMAGE_SIZE]= %d\r\n",imageParamsR[P_IMAGE_SIZE])); imageParamsR[P_DMA_VALID]=1; // updated;}//*******************************************************************#ifndef CONFIG_ETRAX_303void programEncoder (void) { int a=0; int d=0; int i,c, adiff2code; int codetab[]= {128,1,3,7,15,31,63,95}; int threshtab[]= {1,2,5,11,23,47,79,111}; port_csp0_addr[CCAM_WA_WWA]= 0; // reset address counter for (a=0;a<128;a++) { adiff2code=0; for (i=0;i<8;i++) if (a<threshtab[i]) {adiff2code=i;break;} d= (adiff2code << 22) | (((codetab[adiff2code]-a) & 0x3f) << 16); if ((a & 0x18) != 0x08) { c=((a & 0x10)?((a & 0x08)?(a-1):(a+1)):a) & 7; d|= (( (c == 0)? 8:((a & 0x20) ? (-c):c)) & 0x0f) << 8; d|= ( (a & 0x20) ? (-codetab[c]): codetab[c]) & 0xff; } port_csp0_addr[CCAM_WA_ENCOD]= d; // write data, inc address if ((a & 0x7) == 0) printk ("\r\n%2x:",a);// printk(" %x:%x:%07x",adiff2code,c,d); printk(" %07x",d); } printk("\r\n");}#endif/* this makes sure that cmoscam_init is called during boot */module_init(cmoscam_init);MODULE_LICENSE("GPL");MODULE_AUTHOR("Andrey Filippov <andrey@elphel.com>.");MODULE_DESCRIPTION(MY_MODULE_DESCRIPTION);MODULE_DESCRIPTION("Elphel model 303 rev A camera driver");/****************** END OF FILE cmoscam.c ********************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -