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

📄 cam_interface1.c

📁 这是一个用c语言编写的摄像头驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
		divisor = 2; //CCIR-422
	else
		divisor = 4; //CCIR-420
		
	//constant for calculating preview dma address
	if(Cam_Dev.p_format == CAM_RGB24B)
		multiplier = 4;
	else
		multiplier = 2;
	
	if(Cam_Dev.WinHorOffset == 0 && Cam_Dev.WinVerOffset == 0)
		WinOfsEn = 0;
	else
		WinOfsEn = 1;

	SrcWidth = CAM_SRC_HSIZE - Cam_Dev.WinHorOffset*2;
	SrcHeight = CAM_SRC_VSIZE - Cam_Dev.WinVerOffset*2;

	if(SrcWidth >= Cam_Dev.CoDstWidth) ScaleUp_H_Co=0; //down
	else ScaleUp_H_Co=1;		//up

	if(SrcHeight >= Cam_Dev.CoDstHeight) ScaleUp_V_Co=0;
	else ScaleUp_V_Co=1;		

	if(SrcWidth >= Cam_Dev.PrDstWidth) ScaleUp_H_Pr=0; //down
	else ScaleUp_H_Pr=1;		//up

	if(SrcHeight >= Cam_Dev.PrDstHeight) ScaleUp_V_Pr=0;   // edited 040225
	else ScaleUp_V_Pr=1;		

	////////////////// common control setting
	Cam_Dev.regs->global_control = (1<<29)|(1<<26)|(0<<27); // inverse PCLK, test pattern
	Cam_Dev.regs->window_offset = (1<<30)|(0xf<<12); // clear overflow 
	Cam_Dev.regs->window_offset = 0;	
	Cam_Dev.regs->window_offset = (WinOfsEn<<31)|(Cam_Dev.WinHorOffset<<16)|(Cam_Dev.WinVerOffset);
	Cam_Dev.regs->source_format = (1<<30)|(0<<29)|(CAM_SRC_HSIZE<<16)|(CAM_ORDER_YCBYCR<<14)|(CAM_SRC_VSIZE);
	if (Cam_Dev.CodecMode)	{
	////////////////// codec dma setting
	CbFrameInterval = Cam_Dev.CoDstWidth * Cam_Dev.CoDstHeight;
	CrFrameInterval = Cam_Dev.CoDstWidth * Cam_Dev.CoDstHeight / divisor;
	if (Cam_Dev.c_pp_num == 4)
	{
		int i;
		YFrameInterval = Cam_Dev.CoDstWidth * Cam_Dev.CoDstHeight + 2 * Cam_Dev.CoDstWidth * Cam_Dev.CoDstHeight / divisor;
		for (i = 0; i < 4; i++)
		{
			Cam_Dev.regs->codec.Y.sa[i] = CoFrameBuffer + i * YFrameInterval;
			Cam_Dev.regs->codec.Cb.sa[i] = Cam_Dev.regs->codec.Y.sa[i] + CbFrameInterval;
			Cam_Dev.regs->codec.Cr.sa[i] = Cam_Dev.regs->codec.Cb.sa[i] + CrFrameInterval;
		}
	}
	else
	{
		int i;
		for (i = 0; i < 4; i++)
		{
			Cam_Dev.regs->codec.Y.sa[i] = CoFrameBuffer;
			Cam_Dev.regs->codec.Cb.sa[i] = CoFrameBuffer + CbFrameInterval;
			Cam_Dev.regs->codec.Cr.sa[i] = Cam_Dev.regs->codec.Cb.sa[i] + CrFrameInterval;
		}
	}

	////////////////// codec target regs setting
	Cam_Dev.regs->codec.target_format = (CAM_CODEC_IN_422<<31)|(CAM_CODEC_OUTPUT<<30)|(Cam_Dev.CoDstWidth<<16)|(CAM_FLIP_NORMAL<<14)|(Cam_Dev.CoDstHeight);
	CalculateBurstSize(Cam_Dev.CoDstWidth, &MainBurstSizeY, &RemainedBurstSizeY);
	CalculateBurstSize(Cam_Dev.CoDstWidth / 2, &MainBurstSizeC, &RemainedBurstSizeC);
	Cam_Dev.regs->codec.dma_control = (MainBurstSizeY<<19)|(RemainedBurstSizeY<<14)|(MainBurstSizeC<<9)|(RemainedBurstSizeC<<4);	

	////////////////// codec scaler regs setting
	CalculatePrescalerRatioShift(SrcWidth, Cam_Dev.CoDstWidth, &PreHorRatio, &H_Shift);
	CalculatePrescalerRatioShift(SrcHeight, Cam_Dev.CoDstHeight, &PreVerRatio, &V_Shift);
	MainHorRatio=(SrcWidth<<8)/(Cam_Dev.CoDstWidth<<H_Shift);
	MainVerRatio=(SrcHeight<<8)/(Cam_Dev.CoDstHeight<<V_Shift);
    			
	Cam_Dev.regs->codec.scaler.pre_ratio = ((10-H_Shift-V_Shift)<<28)|(PreHorRatio<<16)|(PreVerRatio);
	Cam_Dev.regs->codec.scaler.pre_destination = ((SrcWidth/PreHorRatio)<<16)|(SrcHeight/PreVerRatio); 
	Cam_Dev.regs->codec.scaler.main_control=(CAM_SCALER_BYPASS_OFF<<31)|(ScaleUp_H_Co<<30)|(ScaleUp_V_Co<<29)|(MainHorRatio<<16)|(MainVerRatio);

	Cam_Dev.regs->codec.scaler.target_area = Cam_Dev.CoDstWidth * Cam_Dev.CoDstHeight;
	}		if (Cam_Dev.PrevMode)	{
	///////////////// preview dma regs setting
	RGBFrameInterval = Cam_Dev.PrDstWidth * Cam_Dev.PrDstHeight * multiplier;
	if (Cam_Dev.p_pp_num == 4) // codec view mode
	{
		int i;
		for (i = 0; i < 4; i++)
			Cam_Dev.regs->prev.RGB.sa[i] = PrFrameBuffer + i * RGBFrameInterval;	
	}	
	else // direct preview mode
	{
		int i;
		for (i = 0; i < 4; i++)
			Cam_Dev.regs->prev.RGB.sa[i] = PrFrameBuffer;   //LCDFRAMEBUFFER
	}

	////////////////// preview target regs setting
	Cam_Dev.regs->prev.target_format = (Cam_Dev.PrDstWidth<<16)|(CAM_FLIP_NORMAL<<14)|(Cam_Dev.PrDstHeight);
	if (Cam_Dev.p_format == CAM_RGB24B)
		CalculateBurstSize(Cam_Dev.PrDstWidth*4, &MainBurstSizeRGB, &RemainedBurstSizeRGB);
	else // RGB16B
		CalculateBurstSize(Cam_Dev.PrDstWidth*2, &MainBurstSizeRGB, &RemainedBurstSizeRGB);
   	Cam_Dev.regs->prev.dma_control = (MainBurstSizeRGB<<19)|(RemainedBurstSizeRGB<<14);
	
	///////////////// preview scaler regs setting
	CalculatePrescalerRatioShift(SrcWidth, Cam_Dev.PrDstWidth, &PreHorRatio, &H_Shift);
	CalculatePrescalerRatioShift(SrcHeight, Cam_Dev.PrDstHeight, &PreVerRatio, &V_Shift);
	MainHorRatio=(SrcWidth<<8)/(Cam_Dev.PrDstWidth<<H_Shift);
	MainVerRatio=(SrcHeight<<8)/(Cam_Dev.PrDstHeight<<V_Shift);
	Cam_Dev.regs->prev.scaler.pre_ratio = ((10-H_Shift-V_Shift)<<28)|(PreHorRatio<<16)|(PreVerRatio);		 
	Cam_Dev.regs->prev.scaler.pre_destination = ((SrcWidth/PreHorRatio)<<16)|(SrcHeight/PreVerRatio);
	Cam_Dev.regs->prev.scaler.main_control = (1<<31)|(CAM_PVIEW_OUTPUT<<30)|(ScaleUp_H_Pr<<29)|(ScaleUp_V_Pr<<28)|(MainHorRatio<<16)|(MainVerRatio);
    
	Cam_Dev.regs->prev.scaler.target_area = Cam_Dev.PrDstWidth * Cam_Dev.PrDstHeight;	}
	
	return 0;
}

static int cam_dma_malloc()
{
	unsigned int t_size;
	unsigned int daon = Cam_Dev.CoDstWidth * Cam_Dev.CoDstHeight;

	if(Cam_Dev.CodecMode)
	{
		if (Cam_Dev.c_format == CAM_CCIR420)
		{
			t_size = daon * 3 / 2 ;
		}
		else
		{ 
			t_size = daon * 2; /* CAMIF_OUT_YCBCR422 */
			t_size = t_size * Cam_Dev.c_pp_num;
		}
		Cam_Dev.cbuf = consistent_alloc(GFP_KERNEL | GFP_DMA, t_size, &Cam_Dev.c_phyaddr);
		if (!Cam_Dev.cbuf) {
			printk("CAMERA:Failed to request YCBCR MEM\n");
			return -ENOMEM;
		}		printk("vaddr=0x%x,paddr=0x%x\n", Cam_Dev.cbuf, Cam_Dev.c_phyaddr);
		memset(Cam_Dev.cbuf, 0, t_size);
		Cam_Dev.cbuf_size = t_size;
	}	
	if (Cam_Dev.PrevMode)
	{
		if (Cam_Dev.p_format == CAM_RGB16B) 
			t_size = daon * 2; /*  4byte per two pixel*/
		else 
		{
			t_size = daon * 4; /* 4byte per one pixel */
		}
		t_size = t_size * Cam_Dev.p_pp_num;
		Cam_Dev.pbuf = consistent_alloc(GFP_KERNEL | GFP_DMA, t_size, &Cam_Dev.p_phyaddr);
		if (!Cam_Dev.pbuf) { 
			printk(KERN_ERR"CAMERA:Failed to request RGB MEM\n");
			return -ENOMEM;
		}
		memset(Cam_Dev.pbuf, 0, t_size);
		Cam_Dev.pbuf_size = t_size;
	}

	return 0;
}

static int cam_dma_free()
{
	if(Cam_Dev.CodecMode)
	{
		consistent_free(Cam_Dev.cbuf, Cam_Dev.cbuf_size, Cam_Dev.c_phyaddr);
		Cam_Dev.cbuf = NULL;
	}
	if (Cam_Dev.PrevMode)
	{
		consistent_free(Cam_Dev.pbuf, Cam_Dev.pbuf_size, Cam_Dev.p_phyaddr);
		Cam_Dev.pbuf = NULL;
	}

	return 0;
}
/* Image Capture Enable Regiser */
#define	CAMIF_CAP_ON         (1<<31)
#define CAMIF_CAP_CODEC_ON   (1<<30)
#define CAMIF_CAP_PREVIEW_ON (1<<29)int camif_capture_start(){	u32 n_cmd = 0;		/* Next Command */	int i;	switch(Cam_Dev.exec) {		case CAMIF_BOTH_DMA_ON:			Cam_Dev.regs->codec.scaler.main_control |= (1<<15);			Cam_Dev.regs->prev.scaler.main_control |= (1<<15);			n_cmd = CAMIF_CAP_PREVIEW_ON|CAMIF_CAP_CODEC_ON;			break;		case CAMIF_DMA_ON:			Cam_Dev.status = PREPARE;			Cam_Dev.regs->source_format |= (1<<31);			Cam_Dev.regs->global_control |= (1<<31);			for (i=0;i<=100000000;i++);			Cam_Dev.regs->global_control &= ~(1<<31);			cam_interface_init();			Cam_Dev.regs->source_format &= ~(1<<31);			if (Cam_Dev.CodecMode) {				Cam_Dev.regs->codec.scaler.main_control |= (1<<15);				n_cmd = CAMIF_CAP_CODEC_ON;			}else {				Cam_Dev.regs->prev.scaler.main_control |= (1<<15);				n_cmd = CAMIF_CAP_PREVIEW_ON;			}			/* wait until Sync Time expires */			/* First settting, to wait VSYNC fall  */			/* By VESA spec,in 640x480 @60Hz 			   MAX Delay Time is around 64us which "while" has.*/ 			while(fld_v(Cam_Dev.regs->codec.status, 28, 1));			break;		default:			break;	}	Cam_Dev.regs->window_offset |= (1<<30);	Cam_Dev.regs->window_offset |= (0xf<<12);	Cam_Dev.regs->window_offset &= ~(1<<30);	Cam_Dev.regs->window_offset &= ~(0xf<<12);		Cam_Dev.regs->image_capture = n_cmd|CAMIF_CAP_ON;	return 0;}int camif_capture_stop()
{
	u32 n_cmd = Cam_Dev.regs->image_capture;	/* Next Command */

	switch(Cam_Dev.exec) {
		case CAMIF_BOTH_DMA_OFF:
			Cam_Dev.regs->codec.scaler.main_control &= ~(1<<15);			Cam_Dev.regs->prev.scaler.main_control &= ~(1<<15);
			n_cmd = 0;
			break;
		case CAMIF_DMA_OFF_L_IRQ: /* fall thru */
		case CAMIF_DMA_OFF:
			if (Cam_Dev.CodecMode) {
				Cam_Dev.regs->codec.scaler.main_control &= ~(1<<15);
				n_cmd &= ~CAMIF_CAP_CODEC_ON;
				if (!(n_cmd & CAMIF_CAP_PREVIEW_ON))
					n_cmd = 0;
			}else {
				Cam_Dev.regs->prev.scaler.main_control &= ~(1<<15);
				n_cmd &= ~CAMIF_CAP_PREVIEW_ON;
				if (!(n_cmd & CAMIF_CAP_CODEC_ON))
					n_cmd = 0;
			}
			break;
		default:
			printk("Unexpected \n");
	}
	Cam_Dev.regs->image_capture = n_cmd;
	if(Cam_Dev.exec == CAMIF_DMA_OFF_L_IRQ) { /* Last IRQ  */
		if (Cam_Dev.CodecMode) 
			Cam_Dev.regs->codec.dma_control |= (1<<2);
		else 
			Cam_Dev.regs->prev.dma_control |= (1<<2);
	} 
	return 0;
}/* LastIRQEn is autoclear */
void camif_last_irq_en()
{
	if(Cam_Dev.exec == CAMIF_BOTH_DMA_ON) {
		Cam_Dev.regs->codec.dma_control |= (1<<2);
		Cam_Dev.regs->prev.dma_control |= (1<<2);
	}
	else {
		if (Cam_Dev.CodecMode) 
			Cam_Dev.regs->codec.dma_control |= (1<<2);
		else 
			Cam_Dev.regs->prev.dma_control |= (1<<2);
	}
}/////////////////////////////////////////////clock setting////////////////////////////void ChangeUPllValue(int mdiv,int pdiv,int sdiv)
{
    UPLLCON = (mdiv<<12) | (pdiv<<4) | sdiv;
}void SetCAMClockDivider(int divn) 
{
	CAMDIVN = (CAMDIVN & ~(0xf))|(1<<4)|(divn); // CAMCLK is divided..
}int camif_clock_init()
{
	CLKCON |= CLKCON_CAMIF;
	ChangeUPllValue(60, 4, 1);
	CLKDIVN |= DIVN_UPLL;	/* For USB */
	SetCAMClockDivider(1);
	return 0;
}///////////////////////////////////////////GPIO setting///////////////////////////////static int camif_gpio_init(void)
{
	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);
   	return 0;
}/////////////////////////////////////////////file operation///////////////////////////ssize_t cam_read(struct file *filp, char *buf, size_t count, loff_t *f_pos){	printk("camera reading...(0x%x)\n", Cam_Dev.cbuf);	Cam_Dev.exec = CAMIF_DMA_ON;	camif_capture_start();	interruptible_sleep_on(&Cam_Dev.wq);	if (Cam_Dev.status==FINISH) printk("Capture completed!\n");	Cam_Dev.exec = CAMIF_DMA_OFF;	camif_capture_stop();	if (copy_to_user(buf, Cam_Dev.cbuf, count))		return -EFAULT;	printk("camera read completed!\n");	return count;}///////////////////////////////////////////module initialization///////////////////////////
int init_module(void)
{
	int result,i;
	result = register_chrdev(Cam_Dev.major, "video", &cam_fops);	if (result<0) {		printk("camif: can't get major %d\n",CAM_MAJOR);		return result;	}	if (Cam_Dev.major==0)		Cam_Dev.major = result;	camif_gpio_init();	camif_clock_init();
	Cam_Dev.regs = (cam_interface_regs *)io_p2v(CAM_BASE_ADD);
	sema_init(&Cam_Dev.sem, 1);
	init_waitqueue_head(&Cam_Dev.wq);
	cam_request_irq();
	cam_dma_malloc();
	cam_interface_init();	printk("Camera interface initialization completed!\n");	/*	printk("checking register value(0x%x):\n",Cam_Dev.regs);	printk("0x%x:0x%x\n",&(Cam_Dev.regs->source_format), Cam_Dev.regs->source_format);	printk("0x%x:0x%x\n",&(Cam_Dev.regs->window_offset), Cam_Dev.regs->window_offset);	printk("0x%x:0x%x\n",&(Cam_Dev.regs->global_control), Cam_Dev.regs->global_control);	for (i=0;i<4;i++)		printk("0x%x:0x%x\n",&(Cam_Dev.regs->codec.Y.sa[i]), Cam_Dev.regs->codec.Y.sa[i]);	for (i=0;i<4;i++)		printk("0x%x:0x%x\n",&(Cam_Dev.regs->codec.Cb.sa[i]), Cam_Dev.regs->codec.Cb.sa[i]);	for (i=0;i<4;i++)		printk("0x%x:0x%x\n",&(Cam_Dev.regs->codec.Cr.sa[i]), Cam_Dev.regs->codec.Cr.sa[i]);	printk("0x%x:0x%x\n",&(Cam_Dev.regs->codec.target_format), Cam_Dev.regs->codec.target_format);	printk("0x%x:0x%x\n",&(Cam_Dev.regs->codec.dma_control), Cam_Dev.regs->codec.dma_control);	printk("0x%x:0x%x\n",&(Cam_Dev.regs->codec.scaler.main_control), Cam_Dev.regs->codec.scaler.main_control);	printk("0x%x:0x%x\n",&(Cam_Dev.regs->codec.status), Cam_Dev.regs->codec.status);	printk("0x%x:0x%x\n",&(Cam_Dev.regs->image_capture), Cam_Dev.regs->image_capture);	*/
	return 0;
}

void cleanup_module(void)
{
	//iounmap(Cam_Dev.regs);
	cam_release_irq();
	cam_dma_free();	unregister_chrdev(Cam_Dev.major, "video");
}

⌨️ 快捷键说明

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