📄 saa7113_prp.c
字号:
return 0;}int pwdn_saa7113(int flag){ if(flag) _reg_GPIO_DR(GPIOF) |= 0x00200000; else _reg_GPIO_DR(GPIOF) &= ~(0x00200000); return 0;}static void saa7113h_hard_reset(void){ unsigned short i; pwdn_saa7113(0); for(i=0;i<1000;i++) delay10us(); pwdn_saa7113(1); for(i=0;i<1000;i++) delay10us(); return;}/*** Test on I2C channel* Read / write one of the register* compare and verify if the data is correct*/static int saa7113h_i2c_test(void){ unsigned char chip_ver; //silicon ID unsigned char rdata, wdata; unsigned int error = 0; printk("I2C Test...\n"); saa7113h_hard_reset(); //read silicon ID sccb_read(0x00, &chip_ver); printk("Chip version = 0x%02X\n", chip_ver); for(wdata = 0x1; wdata < 0x3F; wdata ++) { //register read write test sccb_write(0x0D, wdata); //test on reg 0x0D sccb_read(0x0D, &rdata); if(rdata != wdata) error = 1; } if(error) printk("saa7113h: i2c test failed\n"); else printk("saa7113h: i2c test ok\n"); saa7113h_hard_reset(); return error;}/*** SAA7113 Basic Init* Composite/S-Video Input** - Accept composite or s-video video from input A11* - Automatic field detection, PAL or NTSC expected* - Standard CCIR656 output enable* - VBI-data slicer disable* - VSYNC & HSYNC out enable* - ITU recommended contrast, brightness & saturation control* - Chrominance processin with nominal BW (800kHz)** @param type SAA7113H_INPUT_COMPOSITE Accept composite video* SAA7113H_INPUT_SVIDEO Accept s-video video*/static int saa7113h_init(void){// unsigned int chipVer; unsigned char status; unsigned int reg,i;//hard reset saa7113h_hard_reset();//recommended startup settings sccb_write_check(0x01, 0x08); //increment delay sccb_write_check(0x02, 0xC0); //analog input control 1 sccb_write_check(0x03, 0x33); //analog input control 2 sccb_write_check(0x04, 0x00); //analog input control 3 sccb_write_check(0x05, 0x00); //analog input control 4 sccb_write_check(0x06, 0xE9); //HSYNC start sccb_write_check(0x07, 0x0D); //HSYNC stop sccb_write_check(0x08, 0x98); //SYNC control sccb_write_check(0x09, 0x01); //luminance control sccb_write_check(0x0A, 0x80); //luminance brightness sccb_write_check(0x0B, 0x47); //luminance contrast sccb_write_check(0x0C, 0x40); //chrom sat sccb_write_check(0x0D, 0x00); //chrom hue sccb_write_check(0x0E, 0x01); //chrom control //sccb_write_check(0x0F, 0x2A); //chrom gain control sccb_write(0x0F, 0x2A); //format / delay control sccb_write_check(0x10, 0x00); //format / delay control sccb_write_check(0x11, 0x0C); //output control 1// sccb_write_check(0x11, 0x0D); //output control 1 (color kill disable) sccb_write_check(0x12, 0x7B); //output control 2 sccb_write_check(0x13, 0x00); //output control 3 sccb_write_check(0x15, 0x00); //VGATE start sccb_write_check(0x16, 0x00); //VGATE stop sccb_write_check(0x17, 0x00); //MSBs for VGATE control sccb_write_check(0x40, 0x02); //silcer control 1 for(reg = 0x41; reg <= 0x57; reg ++) sccb_write_check(reg, 0xFF); //line control register 2 to 24 sccb_write_check(0x58, 0x00); //framing code sccb_write_check(0x59, 0x54); //horizontal offset for slicer sccb_write_check(0x5A, 0x07); //vertical offset for slicer sccb_write_check(0x5B, 0x83); //field offset and SBs for H & V offset sccb_write_check(0x5E, 0x00); //silced data ID code for(i=0;i<100;i++) delay10us();//read out status sccb_read(0x1F, &status); if(status & 0x20) { printk("NTSC\n"); return 60; //60Hz => NTSC } else{ printk("PAL\n"); return 50; //50Hz => PAL }} 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;}static int csi_prp_open(struct inode *inode, struct file *filp){ MOD_INC_USE_COUNT; return 0;}static int csi_prp_release(struct inode *inode, struct file *filp){ MOD_DEC_USE_COUNT; return 0;}static ssize_t csi_prp_read(struct file *filp, char *buf, size_t size, loff_t *l){ //printk("cntl = 0x%x\n",_reg_EMMA_PRP_CNTL); //printk("cntl = 0x%x\n",(*((volatile unsigned long *)(MX2_IO_ADDRESS(EMMA_PRP_BASE+0x80))))); if(_reg_EMMA_PRP_CNTL & 0x20000000) return -1; copy_to_user(buf, pDstYAddr, Y_BUFFER_SIZE); copy_to_user(buf+Y_BUFFER_SIZE, pDstUAddr, Y_BUFFER_SIZE/4); copy_to_user(buf+Y_BUFFER_SIZE+Y_BUFFER_SIZE/4, pDstVAddr, Y_BUFFER_SIZE/4); _reg_EMMA_PRP_CNTL |= 0x60000000; return size;}static ssize_t csi_prp_write(struct file *filp, const char *buf, size_t size, loff_t *l){ return 0;}static int csi_prp_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ return 0;}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 |= 0x10000000; //Enable csi-prp; _reg_CSI_CSICR1 |= 0x80000; //RXFF level =8; _reg_CSI_CSICR1 |= 0x10000; //SOF INT _reg_CSI_CSICR1 |= 0x08000000; //Interlace _reg_CSI_CSICR1 |= 0x400; //CCIR mode _reg_CSI_CSICR1 |= 0x80; //Big indian mode _reg_CSI_CSICR1 |= (1 << 31); //Swap 16bits mode return 0;}static void prp_intr_handler(){ //_reg_EMMA_PRP_CNTL &= ~0x60000000; //wake_up_interruptible(&gDctWaitQueue); return;}int malloc_buffer(){ pDstYAddr = NULL; pDstUAddr = NULL; pDstVAddr = NULL; /* Alloc memory for inout and output buffer */ pDstYAddr = consistent_alloc(GFP_KERNEL|GFP_DMA,Y_BUFFER_SIZE+1024,&phyDestYAddr); pDstUAddr = consistent_alloc(GFP_KERNEL|GFP_DMA,Y_BUFFER_SIZE/4+1024,&phyDestUAddr); pDstVAddr = consistent_alloc(GFP_KERNEL|GFP_DMA,Y_BUFFER_SIZE/4+1024,&phyDestVAddr); pDstYAddr2 = consistent_alloc(GFP_KERNEL|GFP_DMA,Y_BUFFER_SIZE+1024,&phyDestYAddr2); pDstUAddr2 = consistent_alloc(GFP_KERNEL|GFP_DMA,Y_BUFFER_SIZE/4+1024,&phyDestUAddr2); pDstVAddr2 = consistent_alloc(GFP_KERNEL|GFP_DMA,Y_BUFFER_SIZE/4+1024,&phyDestVAddr2); return 0;}static int mx21_prp_init(){ int i; _reg_CRM_PCCR0 |= 0x08008000;/* _reg_EMMA_PRP_CNTL = 0; _reg_EMMA_PRP_CNTL |= (1<<2); //csi en _reg_EMMA_PRP_CNTL |= (1<<11); //frame skip:stop _reg_EMMA_PRP_CNTL |= (1<<15); //Disable cascade of Channel-1 resize _reg_EMMA_PRP_CNTL |= 0x08000000; //resize fifo level 48 words _reg_EMMA_PRP_CNTL |= (1<<10); _reg_EMMA_PRP_CNTL |= (1<<14); _reg_EMMA_PRP_CNTL |= 0xe0000000; _reg_EMMA_PRP_CNTL |= 0x8; _reg_EMMA_PRP_SPIX_FMT = 0x01180888; _reg_EMMA_PRP_CNTL |= 0x0;*/ //reset the PRP module _reg_EMMA_PRP_CNTL |= 0x1000; for(i=0;i<2000;i++); _reg_EMMA_PRP_CNTL = 0xE800CE2C; //_reg_EMMA_PRP_CNTL |= (1 << 14); //Enable window control _reg_EMMA_PRP_DY_PTR = phyDestYAddr; _reg_EMMA_PRP_DCB_PTR = phyDestUAddr; _reg_EMMA_PRP_DCR_PTR = phyDestVAddr; _reg_EMMA_PRP_SY_PTR = phyDestYAddr2; _reg_EMMA_PRP_SCB_PTR = phyDestUAddr2; _reg_EMMA_PRP_SCR_PTR = phyDestVAddr2; _reg_EMMA_PRP_SFRM_SIZE = IN_Y_WIDTH_SIZE; _reg_EMMA_PRP_SFRM_SIZE = (_reg_EMMA_PRP_SFRM_SIZE << 16 | IN_Y_HIGHT_SIZE); _reg_EMMA_PRP_SPIX_FMT = 0x01180888; _reg_EMMA_PRP_DISIZE_CH2 = OUT_Y_WIDTH_SIZE; _reg_EMMA_PRP_DISIZE_CH2 = (_reg_EMMA_PRP_DISIZE_CH2 << 16 | OUT_Y_HIGHT_SIZE); //_reg_EMMA_PRP_SOURCE_LINE_STRIDE = 8; //Skip 8 pixels _reg_EMMA_PRP_SLIN_STRID = 8; //_reg_EMMA_PRP_RSIZE_CTRL = 0x40; //_reg_EMMA_PRP_INTRCTRL = 0x20; //Enable interupt if(mode) //320x240 { /* Horizatle 11:5 */ _reg_EMMA_PrP_CH2_RZ_HORI_COEF1 = 0x37244924; _reg_EMMA_PrP_CH2_RZ_HORI_COEF2 = 0x00000002; _reg_EMMA_PrP_CH2_RZ_HORI_VALID = 0x0b0004aa; /* Verticle 6:5 */ _reg_EMMA_PrP_CH2_RZ_VERT_COEF1 = 0x00001536; _reg_EMMA_PrP_CH2_RZ_VERT_COEF2 = 0x00000000; _reg_EMMA_PrP_CH2_RZ_VERT_VALID = 0x8600001f; } else //352x288 { /* Horizatle 2:1 */ _reg_EMMA_PrP_CH2_RZ_HORI_COEF1 = 0x00000024; _reg_EMMA_PrP_CH2_RZ_HORI_COEF2 = 0x00000000; _reg_EMMA_PrP_CH2_RZ_HORI_VALID = 0x02000002; /* Verticle 1:1 */ // _reg_EMMA_PrP_CH2_RZ_VERT_COEF1 = 0x00000008; // _reg_EMMA_PrP_CH2_RZ_VERT_COEF2 = 0x00000000; // _reg_EMMA_PrP_CH2_RZ_VERT_VALID = 0x01000001; } _reg_EMMA_PRP_CNTL |= 0x2; //Enable PRP ch2 return 0;}static devfs_handle_t devfs_handle;MODULE_PARM(mode, "i");int init_module(){ int result,i; switch(mode) { case 0: IN_Y_WIDTH_SIZE = 704; IN_Y_HIGHT_SIZE = 288; OUT_Y_WIDTH_SIZE = 352; OUT_Y_HIGHT_SIZE = 288; Y_BUFFER_SIZE = OUT_Y_WIDTH_SIZE*OUT_Y_HIGHT_SIZE; break; case 1: IN_Y_WIDTH_SIZE = 704; IN_Y_HIGHT_SIZE = 288; OUT_Y_WIDTH_SIZE = 320; OUT_Y_HIGHT_SIZE = 240; Y_BUFFER_SIZE = OUT_Y_WIDTH_SIZE*OUT_Y_HIGHT_SIZE; break; default: printk("unsupported image size!\n"); break; } /* register our character device */ result = devfs_register_chrdev(0, "saa7113_prp", &csi_prp_fops); if ( result < 0 ) { printk("csi_prp driver: Unable to register driver\n"); return -ENODEV; } devfs_handle = devfs_register(NULL, "saa7113_prp", DEVFS_FL_DEFAULT, result, 0, S_IFCHR | S_IRUSR | S_IWUSR, &csi_prp_fops, NULL); printk("make node for csi_prp with 'mknod csi_prp c %d 0'\n", result); gMajor = result; //if (request_irq(EMMA_PRP_IRQ, prp_intr_handler, SA_INTERRUPT, "PRP", NULL)) // printk("*** Cannot register interrupt handler for PRP ! ***\n"); //else // printk("PRP interrupt handler registered\n"); init_control_signal(); sccb_init(); csi_init(); saa7113h_i2c_test(); saa7113h_init(); delay10us(); malloc_buffer(); mx21_prp_init(); return 0;}void cleanup_module(){ if (gMajor > 0){ devfs_unregister_chrdev(gMajor, "csi_prp"); devfs_unregister(devfs_handle); } //free_irq(EMMA_PRP_IRQ, 0); free_buffer(); printk("Say goodbye to csi_prp\n");}void free_buffer(){ /* Free memory for inout and output buffer */ consistent_free(pDstYAddr,Y_BUFFER_SIZE+1024,phyDestYAddr); consistent_free(pDstUAddr,Y_BUFFER_SIZE/4+1024,phyDestUAddr); consistent_free(pDstVAddr,Y_BUFFER_SIZE/4+1024,phyDestVAddr); consistent_free(pDstYAddr2,Y_BUFFER_SIZE+1024,phyDestYAddr2); consistent_free(pDstUAddr2,Y_BUFFER_SIZE/4+1024,phyDestUAddr2); consistent_free(pDstVAddr2,Y_BUFFER_SIZE/4+1024,phyDestVAddr2); return;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -