📄 chg-pxa_ov_camera.c
字号:
// want a divisor that gives us a clock rate as close to, but not more than the given mclk. div = (ciclk / (2 * mclk_khz)); div = div - 1; // write cicr4 value = CICR4; value &= ~(CI_CICR4_PCLK_EN | CI_CICR4_MCLK_EN | (CI_CICR4_DIV_SMASK<<CI_CICR4_DIV_SHIFT));//clear PCLK_EN,MCLK_EN AND DIV CICR4[23,19&7:0] value |= (pclk_enable) ? CI_CICR4_PCLK_EN : 0; value |= (mclk_enable) ? CI_CICR4_MCLK_EN : 0; value |= div << CI_CICR4_DIV_SHIFT; CICR4 = value; ovcamprint("CICR4 =%16x\n",value); ovcamprint("ci_set_clock( - ) \n"); return; }void ci_set_polarity(int pclk_sample_falling, int hsync_active_low, int vsync_active_low){ unsigned int value; // write cicr4 value = CICR4; value &= ~(CI_CICR4_PCP | CI_CICR4_HSP | CI_CICR4_VSP); value |= (pclk_sample_falling)? CI_CICR4_PCP : 0; value |= (hsync_active_low) ? CI_CICR4_HSP : 0; value |= (vsync_active_low) ? CI_CICR4_VSP : 0; CICR4 = value; return; }//////////////////////////////////////////////////////////////////////////////////////////FIFO control ////////////////////////////////////////////////////////////////////////////////////////void ci_set_fifo(unsigned int timeout, CI_FIFO_THRESHOLD threshold, int fifo1_enable, int fifo2_enable){ unsigned int value; // write citor CITOR = timeout; // write cifr: always enable fifo 0! also reset input fifo value = CIFR; value &= ~(CI_CIFR_FEN0 | CI_CIFR_FEN1 | CI_CIFR_FEN2 | CI_CIFR_RESETF | CI_CIFR_THL_0_SMASK<<CI_CIFR_THL_0_SHIFT); value |= (unsigned int)threshold << CI_CIFR_THL_0_SHIFT; value |= (fifo1_enable) ? CI_CIFR_FEN1 : 0; value |= (fifo2_enable) ? CI_CIFR_FEN2 : 0; value |= CI_CIFR_RESETF | CI_CIFR_FEN0; CIFR = value; return; }/////////////////////////////////////////////////////////////////////////////////reset fifo of quick capture interface///////////////////////////////////////////////////////////////////////////////void ci_reset_fifo(void){ unsigned int value; value = CIFR; value |= CI_CIFR_RESETF; CIFR = value;}void ci_set_int_mask(unsigned int mask){ unsigned int value; // write mask in cicr0 value = CICR0; value &= ~CI_CICR0_INTERRUPT_MASK; value |= (mask & CI_CICR0_INTERRUPT_MASK); CICR0 = value; return; }unsigned int ci_get_int_mask(void){ unsigned int value; // write mask in cicr0 value = CICR0; return (value & CI_CICR0_INTERRUPT_MASK);}////////////////////////////////////////////////////////////Clear all interrupt status//////////////////////////////////////////////////////////void ci_clear_int_status(unsigned int status){ // write 1 to clear CISR = status;}unsigned int ci_get_int_status(void){ int value; value = CISR; return value;}void ci_set_reg_value(unsigned int reg_offset, unsigned int value){ CI_REG((u32)(ci_regs_base) + reg_offset) = value;}int ci_get_reg_value(unsigned int reg_offset){ int value; value = CI_REG((u32)(ci_regs_base) + reg_offset); return value;}void ovcamera_set_int_mask(p_ovcamera_context_t ovcam_ctx, unsigned int mask){ pxa_dma_desc *end_des_virtual; int dmaend_irq_enable,i; /* set QCI interrupt mask to enable/disable interrupt */ //ci_set_int_mask( mask & CI_CICR0_INTERRUPT_MASK); //set dma end interrupt if ( mask & CAMERA_INTMASK_END_OF_DMA ) { dmaend_irq_enable = 1; } else { dmaend_irq_enable = 0; } // set fifo0 dma chains' flag end_des_virtual = (pxa_dma_desc*)ovcam_ctx->fifo0_descriptors_virtual + ovcam_ctx->fifo0_num_descriptors - 1; for(i=0; i<ovcam_ctx->block_number; i++) { if (dmaend_irq_enable) { end_des_virtual->dcmd |= DCMD_ENDIRQEN; } else { end_des_virtual->dcmd &= ~DCMD_ENDIRQEN; } //end_des_virtual += ovcam_ctx->fifo0_num_descriptors; end_des_virtual += (ovcam_ctx->fifo0_num_descriptors + ovcam_ctx->fifo1_num_descriptors +ovcam_ctx->fifo2_num_descriptors ); } return;}void ovcamerachip_gpio_init ( void ){ set_GPIO_mode( 81 | GPIO_ALT_FN_2_IN); /* CIF_DD[0] */ set_GPIO_mode( 55 | GPIO_ALT_FN_1_IN); /* CIF_DD[1] */ set_GPIO_mode( 51 | GPIO_ALT_FN_1_IN); /* CIF_DD[2] */ set_GPIO_mode( 50 | GPIO_ALT_FN_1_IN); /* CIF_DD[3] */ set_GPIO_mode( 52 | GPIO_ALT_FN_1_IN); /* CIF_DD[4] */ set_GPIO_mode( 48 | GPIO_ALT_FN_1_IN); /* CIF_DD[5] */ set_GPIO_mode( 93 | GPIO_ALT_FN_2_IN); /* CIF_DD[6] */ set_GPIO_mode( 108 | GPIO_ALT_FN_1_IN); /* CIF_DD[7] */ set_GPIO_mode( 53 | GPIO_ALT_FN_2_OUT); /* CIF_MCLK */ set_GPIO_mode( 54 | GPIO_ALT_FN_3_IN); /* CIF_PCLK */ set_GPIO_mode( 85 | GPIO_ALT_FN_3_IN); /* CIF_LV */ set_GPIO_mode( 84 | GPIO_ALT_FN_3_IN); /* CIF_FV */ //jhy GAFR0_U &= ~0x00000003; GPDR0 |= 0x00010000; GPSR0 |= 0x00010000; mdelay(10); GAFR3_L &= ~0x00000003; GPDR3 |= 0x00000001; GPCR3 |= 0x00000001; mdelay(10); GPSR3 |= 0x00000001; mdelay(10); return;}void ovcamerachip_clock_set ( unsigned int clk_regs_base, int pclk_enable, int mclk_enable, unsigned int mclk_khz){ unsigned int ciclk=0,value,div,cccr_l; cccr_l = ( CCCR & 0x0000001F ); if ( cccr_l < 8 ) { ciclk = ( 13 * cccr_l ) * 100; } else if ( cccr_l < 17 ) { ciclk = (( 13 * cccr_l ) * 100 ) >> 1; } else if ( cccr_l < 32 ) { ciclk = (( 13 * cccr_l ) * 100 ) >> 2; } ovcamprint("the mclk = %d \n", mclk_khz); div = ( ciclk + mclk_khz ) / (2 * mclk_khz ) -1; /* zhudavid: ciclk > mclk_khz ?*/ value = CICR4; value &= ~( CI_CICR4_PCLK_EN | CI_CICR4_MCLK_EN | CI_CICR4_DIV_SMASK << CI_CICR4_DIV_SHIFT); value |= (mclk_enable) ? CI_CICR4_MCLK_EN : 0; value |= (pclk_enable) ? CI_CICR4_PCLK_EN : 0; value |= div << CI_CICR4_DIV_SHIFT; CICR4 = value;}int ci_init(){ int cken_val; (unsigned long*)ci_regs_base = (unsigned long*)ioremap(CI_REGS_PHYS, CI_REG_SIZE); if(!ci_regs_base) { ovcamprint("Remap Quick Capture Interface I/O registers failed \n"); return -1; } // clear all CI registers CICR0 = 0x3FF; // disable all interrupts CICR1 = 0; CICR2 = 0; CICR3 = 0; CICR4 = 0; CISR = ~0; CIFR = 0; CITOR = 0; // enable CI clock cken_val = CKEN; cken_val |= CKEN24_CAMERA; CKEN = cken_val; return 0;}void ci_deinit(){ CKEN &= ~CKEN24_CAMERA;}void ci_enable ( int dma_en ){ unsigned int value; value = CICR0; value |= CI_CICR0_ENB; if ( dma_en ) { value |= CI_CICR0_DMA_EN; } CICR0 = value;}int ci_disable ( int quick ){ volatile unsigned int value, mask; int retry; value = CICR0; if ( quick ) { value &= ~CI_CICR0_ENB; mask = CI_CISR_CQD; } else { value |= CI_CICR0_DIS; mask = CI_CISR_CDD; } CICR0 = value; retry = 50; while ( 0 < retry-- ) { value = CISR; if (value & mask) { CISR = mask; return 0; } mdelay(10); } return -1;}/*Generate dma descriptorsPre-condition: these variables must be set properly block_number, fifox_transfer_size dma_descriptors_virtual, dma_descriptors_physical, dma_descirptors_sizePost-condition: these variables will be set fifox_descriptors_virtual, fifox_descriptors_physical fifox_num_descriptors */int update_dma_chain( p_ovcamera_context_t p_ovcam_ctx ){ pxa_dma_desc *cur_des_virtual, *cur_des_physical, *last_des_virtual = NULL; pxa_dma_desc *y_last_virtual = NULL; pxa_dma_desc *u_last_virtual = NULL; pxa_dma_desc *v_last_virtual = NULL; int des_transfer_size, remain_size; unsigned int i, entry_size, desc_num; struct dma_buf_struct *buf_entry; struct list_head *cur_node; int target_physical = 0; int target_virtual = 0; p_ovcamera_context_t camera_context = p_ovcam_ctx; ovcamprint("update_dma_chain( + ) \n"); // clear descriptor pointers p_ovcam_ctx->fifo0_descriptors_virtual = p_ovcam_ctx->fifo0_descriptors_physical = 0; p_ovcam_ctx->fifo1_descriptors_virtual = p_ovcam_ctx->fifo1_descriptors_physical = 0; p_ovcam_ctx->fifo2_descriptors_virtual = p_ovcam_ctx->fifo2_descriptors_physical = 0; // calculate how many descriptors are needed per frame p_ovcam_ctx->fifo0_num_descriptors = ( p_ovcam_ctx->fifo0_transfer_size + SINGLE_DESCRIPTORS_TRANSFER_MAX -1 ) / SINGLE_DESCRIPTORS_TRANSFER_MAX; p_ovcam_ctx->fifo1_num_descriptors = ( p_ovcam_ctx->fifo1_transfer_size + SINGLE_DESCRIPTORS_TRANSFER_MAX -1 ) / SINGLE_DESCRIPTORS_TRANSFER_MAX; p_ovcam_ctx->fifo2_num_descriptors = ( p_ovcam_ctx->fifo2_transfer_size + SINGLE_DESCRIPTORS_TRANSFER_MAX -1 ) / SINGLE_DESCRIPTORS_TRANSFER_MAX; ovcamprint("fif0 descriptors = %d\n", p_ovcam_ctx->fifo0_num_descriptors); ovcamprint("fif1 descriptors = %d\n", p_ovcam_ctx->fifo1_num_descriptors); ovcamprint("fif2 descriptors = %d\n", p_ovcam_ctx->fifo2_num_descriptors); ovcamprint("block number = %d\n", p_ovcam_ctx->block_number); // check if enough memory to generate descriptors if ( (p_ovcam_ctx->fifo0_num_descriptors + p_ovcam_ctx->fifo1_num_descriptors + p_ovcam_ctx->fifo2_num_descriptors) * p_ovcam_ctx->block_number > p_ovcam_ctx->ui_dmadest_size) { ovcamprint("update_dma_chain( -0 ) \n"); return -1; } // generate fifo0 dma chains p_ovcam_ctx->fifo0_descriptors_virtual = (unsigned)p_ovcam_ctx->p_dmadest_virtual; p_ovcam_ctx->fifo0_descriptors_physical = (unsigned)p_ovcam_ctx->p_dmadest_physical; cur_des_virtual = (pxa_dma_desc *)p_ovcam_ctx->fifo0_descriptors_virtual; cur_des_physical = (pxa_dma_desc *)p_ovcam_ctx->fifo0_descriptors_physical; cur_node = &camera_context->buf_head; entry_size = 0; desc_num = 0; for(i=0; i<p_ovcam_ctx->block_number; i++) { // in each iteration, generate one dma chain for one frame remain_size = p_ovcam_ctx->fifo0_transfer_size; while(remain_size){ if (desc_num >= camera_context->dma_descriptors_size){ printk("%s: %d, BUG.\n", __FUNCTION__, __LINE__); return -ENOMEM; } if (entry_size == 0){ buf_entry = get_list_entry(cur_node); if (!buf_entry){ printk("%s: %d, BUG.\n", __FUNCTION__, __LINE__); return -ENOMEM; } target_physical = (unsigned int)buf_entry->paddr; target_virtual = (unsigned int)buf_entry->vaddr; entry_size = buf_entry->size; cur_node = cur_node->next; } if (remain_size > FIFO_0_SINGLE_DESC_TRANS_MAX) des_transfer_size = FIFO_0_SINGLE_DESC_TRANS_MAX; else des_transfer_size = remain_size; if (entry_size < des_transfer_size){ des_transfer_size = entry_size; } cur_des_virtual->ddadr = (unsigned)cur_des_physical + sizeof(pxa_dma_desc); cur_des_virtual->dsadr = CIBR0_PHY; // FIFO0 physical address cur_des_virtual->dtadr = target_physical; cur_des_virtual->dcmd = des_transfer_size | DCMD_FLOWSRC | DCMD_INCTRGADDR | DCMD_BURST32; if (y_last_virtual){ y_last_virtual->ddadr = (unsigned)cur_des_physical; if (camera_context->capture_mode == CAPTURE_STILL_IMAGE) y_last_virtual->ddadr |= 0x1; y_last_virtual->dcmd |= DCMD_ENDIRQEN; y_last_virtual = NULL; } // advance pointers remain_size -= des_transfer_size; entry_size -= des_transfer_size; cur_des_virtual++; cur_des_physical++; target_physical += des_transfer_size; camera_context->fifo0_num_descriptors ++; desc_num ++; } last_des_virtual = cur_des_virtual - 1; y_last_virtual = last_des_virtual; /* setup U Channel*/ if (!camera_context->fifo1_descriptors_virtual){ camera_context->fifo1_descriptors_virtual = (unsigned)cur_des_virtual; camera_context->fifo1_descriptors_physical = (unsigned)cur_des_physical; } remain_size = camera_context->fifo1_transfer_size; if(remain_size){ while(remain_size){ if (desc_num >= camera_context->dma_descriptors_size){ printk("%s: %d, BUG.\n", __FUNCTION__, __LINE__); return -ENOMEM; } if (entry_size == 0){ buf_entry = get_list_entry(cur_node); if (!buf_entry){ printk("%s: %d, BUG.\n", __FUNCTION__, __LINE__); return -ENOMEM; } target_physical = (unsigned)buf_entry->paddr; target_virtual = (unsigned)buf_entry->vaddr; entry_size = buf_entry->size; cur_node = cur_node->next; } if (remain_size > FIFO_1_SINGLE_DESC_TRANS_MAX) des_transfer_size = FIFO_1_SINGLE_DESC_TRANS_MAX; else des_transfer_size = remain_size; if (entry_size < des_transfer_size){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -