?? cim.c
字號:
/* * ucosii/jz4730/drv/cim.c * * Camera Interface Module (CIM) driver for JzSOC * This driver is independent of the camera sensor * * Copyright (C) 2005 JunZheng semiconductor * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include "includes.h" //ucosii#include "jz4740.h"#include "camera.h" // Select one of the sensors#undef dprintf#define dprintf(x...)int printf(char *format, ...);/* If use cachable descriptor, enable this *///#define USE_CACHE 1/* * CIM configuration. */typedef struct{ u32 cfg; u32 ctrl; u32 mclk;} cim_config_t;struct cim_config { int mclk;/* Master clock output to the sensor */ int vsp; /* VSYNC Polarity:0-rising edge is active,1-falling edge is active */ int hsp; /* HSYNC Polarity:0-rising edge is active,1-falling edge is active */ int pcp; /* PCLK Polarity:0-rising edge sampling,1-falling edge sampling */ int dsm; /* Data Sampling Mode:0-CCIR656 Progressive Mode, 1-CCIR656 Interlace Mode,2-Gated Clock Mode,3-Non-Gated Clock Mode */ int pack; /* Data Packing Mode: suppose received data sequence were 0x11 0x22 0x33 0x44, then packing mode will rearrange the sequence in the RXFIFO: 0: 0x11 0x22 0x33 0x44 1: 0x22 0x33 0x44 0x11 2: 0x33 0x44 0x11 0x22 3: 0x44 0x11 0x22 0x33 4: 0x44 0x33 0x22 0x11 5: 0x33 0x22 0x11 0x44 6: 0x22 0x11 0x44 0x33 7: 0x11 0x44 0x33 0x22 */ int inv_dat; /* Inverse Input Data Enable */ int frc; /* Frame Rate Control:0-15 */ int trig; /* RXFIFO Trigger 0:4 | 1:8 | 2:12 | 3:16 | 4:20 | 5:24 | 6:28 | 7:32 */};/* Actual image size, must less than max values */static int img_width, img_height, img_bpp;/* * CIM DMA descriptor */struct cim_desc { u32 nextdesc; /* Physical address of next desc */ u32 framebuf; /* Physical address of frame buffer */ u32 frameid; /* Frame ID */ u32 dmacmd; /* DMA command */};/* * CIM device structure */struct cim_device { unsigned char *framebuf; unsigned int frame_size; OS_EVENT *WaitSem; OS_EVENT *JpegWaitSem; struct cim_desc *frame_desc __attribute__ ((aligned (16)));};// globalstatic struct cim_device *cim_dev;static struct cim_desc cim_frame_desc[CIM_BUF_NUM] __attribute__ ((aligned (16)));static struct cim_desc cim_jpeg_desc __attribute__ ((aligned (16)));static struct cim_desc cim_test_jpeg_desc __attribute__ ((aligned (16)));#ifndef USE_CACHEstatic struct cim_desc *cim_uncached_frame_desc;#endif/* Buffer ID for buffer mutex handling */static int cim_id_init = 1;static int init_post = 0;static int cim_tran_buf_id; /*cim dma current transfer buffer ID*/static int data_ready_buf_id; /*data ready for yuv convert buffer ID*/static int last_data_buf_id; /*last buf of yuv convert, if equal to data_ready_buf_id, wait eof intr*/static int data_buf_reading_flag, jpeg_reading_flag;static int img_width, img_height, img_bpp;static unsigned char *frm_buf; /*current trans buffer pointer*/static unsigned char *jpeg_buf; /* buf for jpeg data *///#define CameraSize (4096 + (IMG_WIDTH * IMG_HEIGHT * IMG_BPP / 8 + 4095) / 4096 *4096 * CIM_BUF_NUM)#define CameraSize (4096 + (img_width * img_height * img_bpp / 8 + 4095) / 4096 *4096 * CIM_BUF_NUM)typedef void (* ALLOCMEMFUNC)( void *, int);static ALLOCMEMFUNC allocmemfunc=NULL, allocjpgmemfunc = NULL;void SetAllocMemfunc(ALLOCMEMFUNC func){ allocmemfunc=func;}void SetAllocJpgMemfunc(ALLOCMEMFUNC func){ allocjpgmemfunc = func;}/*========================================== * Sensor Configure CIM depend on Sensor *==========================================*/static struct cim_config cim_cfg = {#if CAMERATYPE == 1 /*OV2640*/ 24000000, 1, 0, 0, 2, 4, 0, 0, 1,#endif#if CAMERATYPE == 2 /*OV3640*/// 24000000, 1, 0, 0, 2, 4, 0, 0, 1, 24000000, 1, 0, 0, 2, 4, 0, 0, 0,#endif};/*============================= * CIM init routines *=============================*/static void camera_gpio_init(void) { __gpio_as_cim(); __gpio_as_i2c();}/*=================================================== * Config CIM Modules depends on Sensor arguments *===================================================*/static void cim_config(cim_config_t *c){ REG_CIM_CFG = c->cfg; REG_CIM_CTRL = c->ctrl; /* Set the master clock output */ __cim_set_master_clk(__cpm_get_hclk(), c->mclk); // Enable sof, eof and stop interrupts// __cim_enable_sof_intr(); __cim_enable_eof_intr();// __cim_enable_stop_intr(); __cim_enable_rxfifo_overflow_intr();}/* * Split YUV to three buf */void split_yuv422(unsigned char * yuv_buf,unsigned char * y_buf,unsigned char * u_buf,unsigned char * v_buf){ int i = 0, j; for (j = 0;j < cim_dev->frame_size; i+=4, j+=4){ y_buf[i/2] = yuv_buf[j+0]; y_buf[i/2+1] = yuv_buf[j+2]; u_buf[i/4] = yuv_buf[j+1]; v_buf[i/4] = yuv_buf[j+3]; } __dcache_writeback_all(); }static unsigned char * cim_start_dma(void){ frm_buf = (u8 *)VIRT(cim_frame_desc[data_ready_buf_id].framebuf); return frm_buf;}void framebuf_handled(void) { data_buf_reading_flag = 0; //last_data_buf_id = data_ready_buf_id;}/*=================================================== *Start cim and dma to transfer data from sensor *===================================================*/void cim_start(void){ if (cim_id_init == 1) { cim_tran_buf_id = 0; last_data_buf_id = data_ready_buf_id = 0; data_buf_reading_flag = 0; cim_id_init = 0; } __cim_disable(); __cim_set_da(PHYS((unsigned int)(&cim_frame_desc[cim_tran_buf_id])));// __cim_set_da(PHYS(cim_dev->frame_desc)); __cim_clear_state(); // clear state register __cim_reset_rxfifo(); // resetting rxfifo __cim_unreset_rxfifo(); __cim_enable_dma(); // enable dma __cim_enable();}void cim_stop(void){ __cim_disable(); __cim_clear_state();}/*============================================ * Framebuffer allocation and destroy *============================================*/static void cim_fb_destroy(void){ if (cim_dev->framebuf) { cim_dev->framebuf = NULL; }}/*======================================= *Alloc JPEG buf y-buf, u-buf, v-buf *=======================================*/static unsigned char * get_jpeg_buf(void) {// static unsigned char jpeg_heap[JPEG_BUF_SIZE + 0x10]; static unsigned char *jpeg_heap; if(allocjpgmemfunc) allocjpgmemfunc(&jpeg_heap, JPEG_BUF_SIZE + 0x10); printf("_____________jpeg_heap____________ = 0x%08x\n", (unsigned int)jpeg_heap); return jpeg_heap;}/*======================= * Set cim desc list *=======================*/static struct cim_desc *get_desc_list(u8 *cim_heap){ int i, num, page_nums = 0; unsigned char *p_buf; struct cim_desc *desc_list_head __attribute__ ((aligned (16))); struct cim_desc *desc_list_tail __attribute__ ((aligned (16))); struct cim_desc *p_desc __attribute__ ((aligned (16))); int frm_id = 0;#ifndef USE_CACHE struct cim_desc *cim_uncached_jpeg_desc, *cim_uncached_test_jpeg_desc; cim_uncached_frame_desc = (struct cim_desc *)CIM_UNCACHED(cim_frame_desc); cim_uncached_jpeg_desc = (struct cim_desc *)CIM_UNCACHED(&cim_jpeg_desc); cim_uncached_test_jpeg_desc = (struct cim_desc *)CIM_UNCACHED(&cim_test_jpeg_desc);#endif desc_list_head = desc_list_tail = NULL; /* Prepare CIM_BUF_NUM-1 link descriptors for getting sensor data */ for (i = 0; i < CIM_BUF_NUM; i++) {#ifdef USE_CACHE p_desc = &cim_frame_desc[i];#else /* uncached */ p_desc = &cim_uncached_frame_desc[i];#endif p_buf = (u8 *)((u32)cim_dev->framebuf + cim_dev->frame_size * i); if (desc_list_head == NULL) desc_list_head = p_desc; else desc_list_tail->nextdesc = PHYS(p_desc); desc_list_tail = p_desc; desc_list_tail->framebuf = PHYS(p_buf); desc_list_tail->frameid = frm_id; desc_list_tail->dmacmd = (cim_dev->frame_size >> 2) | CIM_CMD_EOFINT; frm_id++; } desc_list_tail->nextdesc = PHYS(desc_list_head);#ifdef USE_CACHE /* cachable */ dma_cache_wback_inv(cim_frame_desc, sizeof(struct cim_desc) * CIM_BUF_NUM); cim_test_jpeg_desc->framebuf = PHYS(jpeg_buf); cim_test_jpeg_desc->nextdesc = PHYS(NULL); cim_test_jpeg_desc->frameid = 0xf; cim_test_jpeg_desc->dmacmd = (4 >> 2) | CIM_CMD_EOFINT | CIM_CMD_STOP; dma_cache_wback_inv(&cim_test_jpeg_desc, sizeof(struct cim_desc)); cim_jpeg_desc.framebuf = PHYS(jpeg_buf); cim_jpeg_desc.nextdesc = PHYS(NULL); cim_jpeg_desc.frameid = 0xf; cim_jpeg_desc.dmacmd = (JPEG_BUF_SIZE >> 2) | CIM_CMD_EOFINT | CIM_CMD_STOP; dma_cache_wback_inv(&cim_jpeg_desc, sizeof(struct cim_desc));#else /* uncached */ cim_uncached_test_jpeg_desc->framebuf = PHYS(jpeg_buf); cim_uncached_test_jpeg_desc->nextdesc = PHYS(NULL); cim_uncached_test_jpeg_desc->frameid = 0xf; cim_uncached_test_jpeg_desc->dmacmd = (4 >> 2) | CIM_CMD_EOFINT | CIM_CMD_STOP; cim_uncached_jpeg_desc->framebuf = PHYS(jpeg_buf); cim_uncached_jpeg_desc->nextdesc = PHYS(NULL); cim_uncached_jpeg_desc->frameid = 0xf; cim_uncached_jpeg_desc->dmacmd = (JPEG_BUF_SIZE >> 2) | CIM_CMD_EOFINT | CIM_CMD_STOP;#endif#if 0 for (i = 0; i < CIM_BUF_NUM; i++) { printf("cim_frame_desc[%d] addr \t= 0x%08x\n", i, (unsigned int)(&cim_frame_desc[i])); printf("cim_frame_desc[%d].framebuf \t= 0x%08x\n",i, (unsigned int)cim_frame_desc[i].framebuf); printf("cim_frame_desc[%d].frameid \t= 0x%08x\n",i, (unsigned int)cim_frame_desc[i].frameid); printf("cim_frame_desc[%d].dmacmd \t= 0x%08x\n",i, (unsigned int)cim_frame_desc[i].dmacmd); printf("cim_frame_desc[%d].nextdesc \t= 0x%08x\n",i, (unsigned int)cim_frame_desc[i].nextdesc); }#endif return desc_list_head;}/*================================================ * Alloc framebuf for get camera data through DMA *================================================*/static int cim_fb_alloc(void){// static u8 cim_heap[4096 + (IMG_WIDTH * IMG_HEIGHT * IMG_BPP / 8 + 4095) / 4096 *4096 * CIM_BUF_NUM] __attribute__ ((aligned(4096))); static u8 *cim_heap; if(allocmemfunc) allocmemfunc(&cim_heap, CameraSize); cim_dev->frame_size = img_width * img_height * (img_bpp/8);// cim_dev->framebuf = (u8 *)(((u32)cim_heap & ~0xfff) + 0x1000); cim_dev->framebuf = (u8 *)((u32)cim_heap & ~0x3); if ( !(cim_dev->framebuf) ) { return -1; } jpeg_buf = get_jpeg_buf(); cim_dev->frame_desc = get_desc_list(cim_heap); return 0;}/*========================= * File operations *=========================*/unsigned char * cim_read(void){ return cim_start_dma();}/* * Snapshot functions */unsigned char * cim_snapshot(int mode){ int i; u8 err; cim_stop(); jpeg_reading_flag = 1; output_jpeg(0); for(i = 0; i < 2; i++) { __cim_disable(); __cim_set_da(PHYS((unsigned int)(&cim_test_jpeg_desc))); __cim_clear_state(); // clear state register __cim_reset_rxfifo(); // resetting rxfifo __cim_unreset_rxfifo(); __cim_enable_dma(); // enable dma __cim_enable(); OSSemPend(cim_dev->JpegWaitSem, 0, &err); } for(i = 0; i < 1; i++) { __cim_disable(); __cim_set_da(PHYS((unsigned int)(&cim_jpeg_desc))); __cim_clear_state(); // clear state register __cim_reset_rxfifo(); // resetting rxfifo __cim_unreset_rxfifo(); __cim_enable_dma(); // enable dma __cim_enable(); //printf(" 5 ======================== cim_snapshot \n"); OSSemPend(cim_dev->JpegWaitSem, 0, &err); } //printf(" 6 ======================== cim_snapshot \n"); __cim_disable(); //printf(" 7 ======================== cim_snapshot \n"); return jpeg_buf;}void cim_snapshot_finish(void) { jpeg_reading_flag = 0; output_yuv(); cim_start();}void cim_close(void){ cim_stop(); // free_irq(IRQ_CIM); cim_fb_destroy();}/*========================= * Interrupt handler *=========================*/static void cim_irq_handler(int irq, void *dev_id){ u32 state = REG_CIM_STATE, curr_frmid = REG_CIM_FID; if (state & CIM_STATE_DMA_EOF) { if (jpeg_reading_flag != 1) { data_ready_buf_id = cim_tran_buf_id; cim_tran_buf_id = curr_frmid; } else { printf("JPEG EOF interrupt\n"); OSSemPost(cim_dev->JpegWaitSem); } } if (state & CIM_STATE_RXF_OF) { printf("OverFlow interrupt...\n"); printf("REG_CIM_STATE = 0x%08x\n", state); __cim_disable(); __cim_reset_rxfifo(); // resetting rxfifo __cim_unreset_rxfifo(); __cim_enable_dma(); // enable dma __cim_enable(); } /* clear status flags*/ REG_CIM_STATE = 0;}/*=========================================================== * Get image parameters from app, Call it before cim_init() *===========================================================*//*============================ * Module init *============================*///int cim_init(void)int cim_init(img_param_t *img){ static struct cim_device *dev; int ret; cim_config_t c; static struct cim_device dev0; camera_gpio_init(); /* set image parameter*/ img_width = img->in_width; img_height = img->in_height; img_bpp = img->in_bpp; /* config cim */ c.mclk = cim_cfg.mclk; c.cfg = (cim_cfg.vsp << 14) | (cim_cfg.hsp << 13) | (cim_cfg.pcp << 12) | (cim_cfg.dsm << 0) | (cim_cfg.pack << 4) | (cim_cfg.inv_dat << 15); c.ctrl = (cim_cfg.frc << 16) | (cim_cfg.trig << 4); cim_config(&c); /* cim image parameter isn't set newly */ /* allocate device */ dev = &dev0; /* record device */ cim_dev = dev; /* allocate a frame buffer */ if (cim_fb_alloc() < 0) { return -1; } dev->WaitSem = OSSemCreate(0); dev->JpegWaitSem = OSSemCreate(0); if ((ret = request_irq(IRQ_CIM, cim_irq_handler, dev)) == -1) { cim_fb_destroy(); printf("CIM could not get IRQ"); return ret; } printf("JzSOC Camera Interface(CIM) driver init OK\n"); return 0;}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -