⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 camif.c

📁 用于三星S3C2440A和S3C24A0A的VGA或SXGA驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
	}	else {		*ratio=1;		*shift=0;	}  	return 0;}int camif_g_fifo_status(camif_cfg_t *cfg) {	u32 reg;	if (cfg->dma_type & CAMIF_CODEC) {		u32 flag = CO_OVERFLOW_Y|CO_OVERFLOW_CB|CO_OVERFLOW_CR;		reg = CICOSTATUS;		if (reg & flag) {			printk("CODEC: FIFO error(0x%08x) and corrected\n",reg);			/* FIFO Error Count ++  */			CIWDOFST |= CO_FIFO_Y|CO_FIFO_CB|CO_FIFO_CR;			CIWDOFST &= ~(CO_FIFO_Y|CO_FIFO_CB|CO_FIFO_CR);			return 1; /* Error */		}	}	if (cfg->dma_type & CAMIF_PREVIEW) {		u32 flag = PR_OVERFLOW_CB|PR_OVERFLOW_CR;		reg = CIPRSTATUS;		if (reg & flag) {			printk("PREVIEW:FIFO error(0x%08x) and corrected\n",reg);			CIWDOFST |= PR_FIFO_CB|PR_FIFO_CR;			CIWDOFST &= ~(CO_FIFO_Y|CO_FIFO_CB|CO_FIFO_CR);			/* FIFO Error Count ++  */			return 1; /* Error */		}	}	return 0;		/* No Error */}/* Policy: * if codec or preview define the win offset, *    other must follow that value. */int camif_win_offset(camif_gc_t *gc ){	u32 h = gc->win_hor_ofst;	u32 v = gc->win_ver_ofst;	/*Clear Overflow */	CIWDOFST = CO_FIFO_Y|CO_FIFO_CB|CO_FIFO_CR|PR_FIFO_CB|PR_FIFO_CB;	CIWDOFST = 0;		/* ? Dummy */	if (!h && !v)	{		CIWDOFST = 0;		return 0;	}	CIWDOFST = WINOFEN | WINHOROFST(h) | WINVEROFST(v);	return 0;}/*   * when you change the resolution in a specific camera, * sometimes, it is necessary to change the polarity  *                                       -- SW.LEE */static void camif_polarity(camif_gc_t *gc){	u32 cmd = CIGCTRL;		cmd = cmd & ~(BIT26|BIT25|BIT24); /* clear polarity */	if (gc->polarity_pclk)		cmd |= GC_INVPOLPCLK;	if (gc->polarity_vsync)		cmd |= GC_INVPOLVSYNC;	if (gc->polarity_href)		cmd |= GC_INVPOLHREF;	CIGCTRL |= cmd;}int camif_dynamic_open(camif_cfg_t *cfg){	camif_win_offset(cfg->gc);	camif_polarity(cfg->gc);		if(camif_scaler(cfg)) {		printk(KERN_ERR "CAMERA:Preview Scaler, Change WinHorOfset or Target Size\n");		return 1;	}	camif_target_fmt(cfg);	if (camif_dma_burst(cfg)) {		printk(KERN_ERR "CAMERA:DMA Busrt Length Error \n");		return 1;	}	if(camif_malloc(cfg) ) {		printk(KERN_ERR "    Instead of using consistent_alloc()\n"			        "    lease use dedicated memory allocation for DMA memory\n");		return -1;	}	camif_pingpong(cfg);	return 0;}int camif_dynamic_close(camif_cfg_t *cfg){	camif_demalloc(cfg);	return 0;}static int camif_target_area(camif_cfg_t *cfg) {	u32 rect = cfg->target_x * cfg->target_y;	if (cfg->dma_type & CAMIF_CODEC ) {		CICOTAREA = rect;	}	if (cfg->dma_type & CAMIF_PREVIEW) {		CIPRTAREA = rect;	}	return 0;}static int inline camif_hw_reg(camif_cfg_t *cfg){	u32 cmd = 0;	if (cfg->dma_type & CAMIF_CODEC) {		CICOSCPRERATIO = PRE_SHIFT(cfg->sc.shfactor)			|PRE_HRATIO(cfg->sc.prehratio)|PRE_VRATIO(cfg->sc.prevratio);		CICOSCPREDST = 			PRE_DST_WIDTH(cfg->sc.predst_x)|PRE_DST_HEIGHT(cfg->sc.predst_y);		/* Differ from Preview */		if (cfg->sc.scalerbypass)			cmd |= SCALERBYPASS;		if (cfg->sc.scaleup_h & cfg->sc.scaleup_v)			cmd |= BIT30|BIT29;		CICOSCCTRL = cmd | MAIN_HRATIO(cfg->sc.mainhratio)			|MAIN_VRATIO(cfg->sc.mainvratio);		return 0;	}	else if (cfg->dma_type & CAMIF_PREVIEW) {		CIPRSCPRERATIO = PRE_SHIFT(cfg->sc.shfactor)			|PRE_HRATIO(cfg->sc.prehratio)|PRE_VRATIO(cfg->sc.prevratio);		CIPRSCPREDST = 			PRE_DST_WIDTH(cfg->sc.predst_x)|PRE_DST_HEIGHT(cfg->sc.predst_y);		/* Differ from Codec */		if (cfg->fmt & CAMIF_RGB24) {			cmd |= RGB_FMT24;  		}		else {			/* RGB16 */;		}				if (cfg->sc.scaleup_h & cfg->sc.scaleup_v)			cmd |= BIT29|BIT28;		CIPRSCCTRL = cmd |MAIN_HRATIO(cfg->sc.mainhratio)|S_METHOD			|MAIN_VRATIO(cfg->sc.mainvratio);	}else {		panic("CAMERA:DMA_TYPE Wrong \n");	}	return 0;}/* Configure Pre-scaler control  & main scaler control register */static int camif_scaler(camif_cfg_t *cfg){	int tx = cfg->target_x,ty=cfg->target_y;	int sx, sy;	if (tx <= 0 || ty<= 0) 	panic("CAMERA: Invalid target size \n");	sx = cfg->gc->source_x - 2*cfg->gc->win_hor_ofst;	sy = cfg->gc->source_y - 2*cfg->gc->win_ver_ofst;		if (sx <= 0 || sy<= 0) 	panic("CAMERA: Invalid source size \n");	cfg->sc.modified_src_x = sx;	cfg->sc.modified_src_y = sy;	/* Pre-scaler control register 1 */	camif_scaler_internal(sx,tx,&cfg->sc.prehratio,&cfg->sc.hfactor);	camif_scaler_internal(sy,ty,&cfg->sc.prevratio,&cfg->sc.vfactor);	if (cfg->dma_type & CAMIF_PREVIEW) {		if ( (sx /cfg->sc.prehratio) <= 640 ) {}		else {			printk(KERN_INFO "CAMERA: Internal Preview line buffer is 640 pixels\n");			return 1; /* Error */		}	}	cfg->sc.shfactor = 10-(cfg->sc.hfactor+cfg->sc.vfactor);	/* Pre-scaler control register 2 */	cfg->sc.predst_x = sx / cfg->sc.prehratio;	cfg->sc.predst_y = sy / cfg->sc.prevratio;	/* Main-scaler control register */	cfg->sc.mainhratio = (sx << 8)/(tx << cfg->sc.hfactor);	cfg->sc.mainvratio = (sy << 8)/(ty << cfg->sc.vfactor);	DPRINTK(" sx %d, sy %d tx %d ty %d  \n",sx,sy,tx,ty);	DPRINTK(" hfactor %d  vfactor %d \n",cfg->sc.hfactor,cfg->sc.vfactor);	cfg->sc.scaleup_h  = (sx <= tx) ? 1: 0;	cfg->sc.scaleup_v  = (sy <= ty) ? 1: 0;	if ( cfg->sc.scaleup_h != cfg->sc.scaleup_v) 		printk(KERN_ERR "scaleup_h must be same to scaleup_v \n");	camif_hw_reg(cfg);	camif_target_area(cfg);	return 0;}/****************************************************** CalculateBurstSize - Calculate the busrt lengths Description: - dstHSize: the number of the byte of H Size.********************************************************/static void camif_g_bsize(u32 hsize, u32 *mburst, u32 *rburst){	u32 tmp;	tmp = (hsize/4) % 16;	switch(tmp) {		case 0:			*mburst=16;			*rburst=16;			break;		case 4:			*mburst=16;			*rburst=4;			break;		case 8:			*mburst=16;			*rburst=8;			break;		default:			tmp=(hsize/4)%8;			switch(tmp) {				case 0:					*mburst=8;					*rburst=8;					break;				case 4:					*mburst=8;					*rburst=4;				default:					*mburst=4;					tmp=(hsize/4)%4;					*rburst= (tmp) ? tmp: 4;					break;			}			break;	}}/* SXGA 1028x1024*//* XGA 1024x768 *//* SVGA 800x600 *//* VGA 640x480 *//* CIF 352x288 *//* QVGA 320x240 *//* QCIF 176x144 *//* ret val         1 : DMA Size Error */#define BURST_ERR 1 static int camif_dma_burst(camif_cfg_t *cfg){	int width = cfg->target_x;	if (cfg->dma_type & CAMIF_CODEC ) {		u32 yburst_m, yburst_r;		u32 cburst_m, cburst_r;		/* CODEC DMA WIDHT is multiple of 16 */		if (width %16 != 0 )  return BURST_ERR;   /* DMA Burst Length Error */		camif_g_bsize(width,&yburst_m,&yburst_r);		camif_g_bsize(width/2,&cburst_m,&cburst_r);		CICOCTRL =YBURST_M(yburst_m)|CBURST_M(cburst_m)			|YBURST_R(yburst_r)|CBURST_R(cburst_r);	}	if (cfg->dma_type & CAMIF_PREVIEW) {		u32 rgburst_m, rgburst_r;		if(cfg->fmt == CAMIF_RGB24) {			if (width %2 != 0 )  return BURST_ERR;   /* DMA Burst Length Error */			camif_g_bsize(width*4,&rgburst_m,&rgburst_r);		}		else {		/* CAMIF_RGB16 */			if ((width/2) %2 != 0 )  return BURST_ERR; /* DMA Burst Length Error */			camif_g_bsize(width*2,&rgburst_m,&rgburst_r);  		}			CIPRCTRL = RGBURST_M(rgburst_m) | RGBURST_R(rgburst_r);	}	return 0;}static int camif_gpio_init(void){#ifdef CONFIG_ARCH_S3C24A0A	/* S3C24A0A has the dedicated signal pins for Camera */#else	set_gpio_ctrl(GPIO_CAMDATA0);	set_gpio_ctrl(GPIO_CAMDATA1);	set_gpio_ctrl(GPIO_CAMDATA2);	set_gpio_ctrl(GPIO_CAMDATA3);	set_gpio_ctrl(GPIO_CAMDATA4);	set_gpio_ctrl(GPIO_CAMDATA5);	set_gpio_ctrl(GPIO_CAMDATA6);	set_gpio_ctrl(GPIO_CAMDATA7);	set_gpio_ctrl(GPIO_CAMPCLKIN);	set_gpio_ctrl(GPIO_CAMVSYNC);	set_gpio_ctrl(GPIO_CAMHREF);	set_gpio_ctrl(GPIO_CAMPCLKOUT);	set_gpio_ctrl(GPIO_CAMRESET);#endif        return 0;}#define ROUND_ADD 0x100000#ifdef CONFIG_ARCH_S3C24A0Aint camif_clock_init(camif_gc_t *gc){	unsigned int upll, camclk_div, camclk;	if (!gc) camclk = 24000000;	else  {		camclk = gc->camclk;		if (camclk > 48000000)			printk(KERN_ERR "Wrong Camera Clock\n");	}	CLKCON |= CLKCON_CAM_UPLL | CLKCON_CAM_HCLK;	upll = get_bus_clk(GET_UPLL);	printk(KERN_INFO "CAMERA:Default UPLL %08d and Assing 96Mhz to UPLL\n",upll);		UPLLCON = FInsrt(56, fPLL_MDIV) | FInsrt(2, fPLL_PDIV)| FInsrt(1, fPLL_SDIV);	upll = get_bus_clk(GET_UPLL);	camclk_div = (upll+ROUND_ADD) / camclk - 1;	CLKDIVN = (CLKDIVN & 0xFF) | CLKDIVN_CAM(camclk_div);	printk(KERN_INFO"CAMERA:upll %d MACRO 0x%08X CLKDIVN 0x%08X \n",				upll, CLKDIVN_CAM(camclk_div),CLKDIVN);	CIIMGCPT = 0;		/* Dummy ? */	return 0;}#elseint camif_clock_init(camif_gc_t *gc){	unsigned int upll, camclk_div, camclk;	if (!gc) camclk = 24000000;	else  {		camclk = gc->camclk;		if (camclk > 48000000)			printk(KERN_ERR "Wrong Camera Clock\n");	}	CLKCON |= CLKCON_CAMIF;	upll = elfin_get_bus_clk(GET_UPLL);	printk(KERN_INFO "CAMERA:Default UPLL %08d and Assing 96Mhz to UPLL\n",upll);		{		UPLLCON = FInsrt(60, fPLL_MDIV) | FInsrt(4, fPLL_PDIV)| FInsrt(1, fPLL_SDIV);		CLKDIVN |= DIVN_UPLL;	/* For USB */		upll = elfin_get_bus_clk(GET_UPLL);	}	camclk_div = (upll+ROUND_ADD) /(camclk * 2) -1;	CAMDIVN = CAMCLK_SET_DIV|(camclk_div&0xf);	printk(KERN_INFO "CAMERA:upll %08d  cam_clk %08d CAMDIVN 0x%08x \n",upll,camclk, CAMDIVN);	CIIMGCPT = 0;		/* Dummy ? */	return 0;}#endif/*    Reset Camera IP in CPU   Reset External Sensor  */void camif_reset(int is, int delay){	switch (is) {		case CAMIF_RESET:			CIGCTRL |= GC_SWRST;			mdelay(1);			CIGCTRL &= ~GC_SWRST;			break;		case CAMIF_EX_RESET_AH: /*Active High */			CIGCTRL &= ~GC_CAMRST; 			udelay(200);			CIGCTRL |= GC_CAMRST;			udelay(delay);			CIGCTRL &= ~GC_CAMRST;			break;		case CAMIF_EX_RESET_AL:	/*Active Low */			CIGCTRL |=  GC_CAMRST;			udelay(200);			CIGCTRL &= ~GC_CAMRST;			udelay(delay);			CIGCTRL |= GC_CAMRST;			break;		default:			break;	}}		/* For Camera Operation, * we can give the high priority to REQ2 of ARBITER1  *//* Please move me into proper place  *  camif_gc_t is not because "rmmod imgsenor" will delete the instance of camif_gc_t   */static u32 old_priority; static void camif_bus_priority(int flag){	if (flag) {#ifdef CONFIG_ARCH_S3C24A0A		old_priority = PRIORITY0;		PRIORITY0 = PRIORITY_I_FIX;		PRIORITY1 = PRIORITY_I_FIX;#else		old_priority = PRIORITY;			PRIORITY &= ~(3<<7);		PRIORITY |=  (1<<7); /* Arbiter 1, REQ2 first */		PRIORITY &= ~(1<<1); /* Disable Priority Rotate */#endif	} 	else {#ifdef CONFIG_ARCH_S3C24A0A		PRIORITY0 = old_priority;		PRIORITY1 = old_priority;#else		PRIORITY = old_priority;#endif	}}static void inline camif_clock_off(void){	CIIMGCPT = 0;#if defined (CONFIG_ARCH_S3C24A0A)	CLKCON &= ~CLKCON_CAM_UPLL;	CLKCON &= ~CLKCON_CAM_HCLK;#else	CLKCON &= ~CLKCON_CAMIF;#endif}/* Init external image sensor  *  Before make some value into image senor, *  you must set up the pixel clock. */void camif_setup_sensor(void){	camif_reset(CAMIF_RESET, 0);	camif_gpio_init();	camif_clock_init(NULL);/* Sometimes ,Before loading I2C module, we need the reset signal */#ifdef CONFIG_ARCH_S3C24A0A	camif_reset(CAMIF_EX_RESET_AL,1000);#else	camif_reset(CAMIF_EX_RESET_AH,1000);#endif}void camif_hw_close(camif_cfg_t *cfg){	camif_bus_priority(0);	camif_clock_off();}void camif_hw_open(camif_gc_t *gc){	camif_source_fmt(gc);	camif_win_offset(gc);	camif_bus_priority(1);}/*  * Local variables: * tab-width: 8 *  c-indent-level: 8 *  c-basic-offset: 8 *  c-set-style: "K&R" * End: */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -