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

📄 s3c2440camif.c

📁 ov9650的驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
#include <linux/module.h>#include <linux/delay.h>#include <linux/errno.h>#include <linux/fs.h>#include <linux/kernel.h>#include <linux/slab.h>#include <linux/mm.h>#include <linux/ioport.h>#include <linux/init.h>#include <linux/sched.h>#include <linux/clk.h>#include <linux/random.h>#include <linux/version.h>#include <linux/videodev2.h>#include <linux/dma-mapping.h>#ifdef CONFIG_VIDEO_V4L1_COMPAT#include <linux/videodev.h>#endif#include <linux/interrupt.h>#include <media/video-buf.h>#include <media/v4l2-common.h>#include <linux/highmem.h>#include <asm/io.h>#include <asm/memory.h>#include <asm/arch/regs-gpio.h>#include <asm/arch/regs-gpioj.h>#include <asm/arch/regs-clock.h>#include <asm/arch-s3c2410/map.h>#include "s3c2440camif.h"/* module params. */static int video_nr = -1;module_param(video_nr, int, 0);MODULE_PARM_DESC(video_nr, "minor device number for s3c2440 camif");/* debug print macro. */#undef PDEBUG#ifdef CONFIG_S3C2440_CAMIF_DBG	#ifdef __KERNEL__	     /* in kernel space */		#define PDEBUG(fmt, args...) printk( KERN_ALERT"%s_%d: "fmt, __FILE__, __LINE__, ## args)	#else	     /* in user space */		#define PDEBUG(fmt, args...) fprintf(stderr, "%s_%d: "fmt, __FILE__, __LINE__, ## args)	#endif#else	#define PDEBUG(fmt, args...)#endif/* hardware & driver name, version etc. */#define CARD_NAME		"s3c2440-camif"#define DRIVER_NAME		"s3c2440-camif"#define DRIVER_VERSION	KERNEL_VERSION(0,1,1)unsigned long camif_base_addr;/* camera device(s) */static LIST_HEAD(camif_devlist);/* image buffer for previewing. */struct s3c2440camif_buffer img_buff[] ={	{		.state = CAMIF_BUFF_INVALID,		.img_size = 0,		.order = 0,		.virt_base = (unsigned long)NULL,		.phy_base = (unsigned long)NULL	},	{		.state = CAMIF_BUFF_INVALID,		.img_size = 0,		.order = 0,		.virt_base = (unsigned long)NULL,		.phy_base = (unsigned long)NULL	},	{		.state = CAMIF_BUFF_INVALID,		.img_size = 0,		.order = 0,		.virt_base = (unsigned long)NULL,		.phy_base = (unsigned long)NULL	},	{		.state = CAMIF_BUFF_INVALID,		.img_size = 0,		.order = 0,		.virt_base = (unsigned long)NULL,		.phy_base = (unsigned long)NULL	}};/* * struct s3c2440camif_format formats[] */static struct s3c2440camif_format formats[] = {	{		.description = "RGB 5-6-5",		.pixelformat = V4L2_PIX_FMT_RGB565,		.depth = 16,	},	{		.description = "RGB 8-8-8",		.pixelformat = V4L2_PIX_FMT_RGB24,		.depth = 32,	},	{		.description = "YCbCr 4:2:0",		.pixelformat = V4L2_PIX_FMT_YUV420,		.depth = 12,	},	{		.description = "YCbCr 4:2:2",		.pixelformat = V4L2_PIX_FMT_YUYV,		.depth = 16,	},};static struct v4l2_queryctrl g_ctrls[] ={	{		.id = 0,		.type = V4L2_CTRL_TYPE_INTEGER,		.name = "Horizontal Window Offset",		.minimum = 0,		.maximum = 632,		.step = 8,		.default_value = 0	},	{		.id = 1,		.type = V4L2_CTRL_TYPE_INTEGER,		.name = "Virtal Window Offset",		.minimum = 0,		.maximum = 504,		.step = 8,		.default_value = 0	}};/* software reset camera interface. */static void __inline__ soft_reset_camif(void){	u32 cigctrl;	cigctrl = (1<<31)|(1<<29);	iowrite32(cigctrl, S3C244X_CIGCTRL);	mdelay(10);	cigctrl = (1<<29);	iowrite32(cigctrl, S3C244X_CIGCTRL);	mdelay(10);	PDEBUG("%s() done.\n", __FUNCTION__);}/* software reset camera interface. */static void __inline__ hw_reset_camif(void){	u32 cigctrl;	cigctrl = (1<<30)|(1<<29);	iowrite32(cigctrl, S3C244X_CIGCTRL);	mdelay(10);	cigctrl = (1<<29);	iowrite32(cigctrl, S3C244X_CIGCTRL);	mdelay(10);	PDEBUG("%s() done.\n", __FUNCTION__);}/* switch camif from preview path to codec path. */static void __inline__ camif_p2c(struct s3c2440camif_dev * pdev){	/* 1. stop preview. */	{		u32 ciprscctrl;		ciprscctrl = ioread32(S3C244X_CIPRSCCTRL);		ciprscctrl &= ~(1<<15);	// stop preview scaler.		iowrite32(ciprscctrl, S3C244X_CIPRSCCTRL);	}	/* 2. soft-reset camif */	soft_reset_camif();	/* 3. clear all overflow. */	{		u32 ciwdofst;		ciwdofst = ioread32(S3C244X_CIWDOFST);		ciwdofst |= (1<<30)|(1<<15)|(1<<14)|(1<<13)|(1<<12);		iowrite32(ciwdofst, S3C244X_CIWDOFST);		ciwdofst &= ~((1<<30)|(1<<15)|(1<<14)|(1<<13)|(1<<12));		iowrite32(ciwdofst, S3C244X_CIWDOFST);	}}/* switch camif from codec path to preview path. */static void __inline__ camif_c2p(struct s3c2440camif_dev * pdev){	/* 1. stop codec. */	{		u32 cicoscctrl;		cicoscctrl = ioread32(S3C244X_CICOSCCTRL);		cicoscctrl &= ~(1<<15);	// stop preview scaler.		iowrite32(cicoscctrl, S3C244X_CICOSCCTRL);	}	/* 2. soft-reset camif. */	soft_reset_camif();	/* 3. clear all overflow. */	{		u32 ciwdofst;		ciwdofst = ioread32(S3C244X_CIWDOFST);		ciwdofst |= (1<<30)|(1<<15)|(1<<14)|(1<<13)|(1<<12);		iowrite32(ciwdofst, S3C244X_CIWDOFST);		ciwdofst &= ~((1<<30)|(1<<15)|(1<<14)|(1<<13)|(1<<12));		iowrite32(ciwdofst, S3C244X_CIWDOFST);	}}/* calculate main burst size and remained burst size. */static void __inline__ calc_burst_size(u32 pixperword,u32 hSize, u32 *mainBurstSize, u32 *remainedBurstSize){	u32 tmp;	tmp = (hSize/pixperword)%16;	switch(tmp)	{	case 0:		*mainBurstSize = 16;		*remainedBurstSize = 16;		break;	case 4:		*mainBurstSize = 16;		*remainedBurstSize = 4;		break;	case 8:		*mainBurstSize=16;		*remainedBurstSize = 8;		break;	default: 		tmp=(hSize/pixperword)%8;		switch(tmp)		{		case 0:			*mainBurstSize = 8;			*remainedBurstSize = 8;			break;		case 4:			*mainBurstSize = 8;			*remainedBurstSize = 4;		default:			*mainBurstSize = 4;			tmp = (hSize/pixperword)%4;			*remainedBurstSize = (tmp)?tmp:4;			break;		}		break;	}}/* calculate prescaler ratio and shift. */static void __inline__ calc_prescaler_ratio_shift(u32 SrcSize, u32 DstSize, u32 *ratio, u32 *shift){	if(SrcSize>=64*DstSize)	{		PDEBUG("Error: out of the prescaler range: SrcSize/DstSize = %d(< 64)\n", SrcSize/DstSize);		BUG();	}	else if(SrcSize>=32*DstSize)	{		*ratio=32;		*shift=5;	}	else if(SrcSize>=16*DstSize)	{		*ratio=16;		*shift=4;	}	else if(SrcSize>=8*DstSize)	{		*ratio=8;		*shift=3;	}	else if(SrcSize>=4*DstSize)	{		*ratio=4;		*shift=2;	}	else if(SrcSize>=2*DstSize)	{		*ratio=2;		*shift=1;	}	else	{		*ratio=1;		*shift=0;	}    	}/* update CISRCFMT only. */static void __inline__ update_source_fmt_regs(struct s3c2440camif_dev * pdev){	u32 cisrcfmt;	cisrcfmt = (1<<31)					// ITU-R BT.601 YCbCr 8-bit mode				|(0<<30)				// CB,Cr value offset cntrol for YCbCr				|(pdev->srcHsize<<16)	// source image width//				|(0<<14)				// input order is YCbYCr//				|(1<<14)				// input order is YCrYCb				|(2<<14)				// input order is CbYCrY//				|(3<<14)				// input order is CrYCbY				|(pdev->srcVsize<<0);	// source image height	iowrite32(cisrcfmt, S3C244X_CISRCFMT);}/* update registers: *	PREVIEW path: *		CIPRCLRSA1 ~ CIPRCLRSA4 *		CIPRTRGFMT *		CIPRCTRL *		CIPRSCCTRL *		CIPRTAREA *	CODEC path: *		CICOYSA1 ~ CICOYSA4 *		CICOCBSA1 ~ CICOCBSA4 *		CICOCRSA1 ~ CICOCRSA4 *		CICOTRGFMT *		CICOCTRL *		CICOTAREA */static void __inline__ update_target_fmt_regs(struct s3c2440camif_dev * pdev){	u32 Ysize, Csize;	u32 cicotrgfmt;	u32 cicoctrl;	u32 ciprtrgfmt;	u32 ciprctrl;	u32 ciprscctrl;	u32 mainBurstSize, remainedBurstSize;	switch (formats[pdev->format].pixelformat)	{	case V4L2_PIX_FMT_RGB565:		/* CIPRCLRSA1 ~ CIPRCLRSA4. */		iowrite32(img_buff[0].phy_base, S3C244X_CIPRCLRSA1);		iowrite32(img_buff[1].phy_base, S3C244X_CIPRCLRSA2);		iowrite32(img_buff[2].phy_base, S3C244X_CIPRCLRSA3);		iowrite32(img_buff[3].phy_base, S3C244X_CIPRCLRSA4);		/* CIPRTRGFMT. */		ciprtrgfmt = (pdev->preTargetHsize<<16)		// horizontal pixel number of target image					 |(0<<14)						// don't mirror or rotation.					 |(pdev->preTargetVsize<<0);	// vertical pixel number of target image		iowrite32(ciprtrgfmt, S3C244X_CIPRTRGFMT);		/* CIPRCTRL. */		calc_burst_size(2, pdev->preTargetHsize, &mainBurstSize, &remainedBurstSize);		PDEBUG("preview main burst leng: %d, remained burst length: %d\n", mainBurstSize, remainedBurstSize);		ciprctrl = (mainBurstSize<<19)|(remainedBurstSize<<14);		iowrite32(ciprctrl, S3C244X_CIPRCTRL);		/* CIPRSCCTRL. */		ciprscctrl = ioread32(S3C244X_CIPRSCCTRL);		ciprscctrl &= 1<<15;	// clear all other info except 'preview scaler start'.		ciprscctrl |= 0<<30;	// 16-bits RGB		iowrite32(ciprscctrl, S3C244X_CIPRSCCTRL);	// 16-bit RGB		/* CIPRTAREA. */		iowrite32(pdev->preTargetHsize * pdev->preTargetVsize, S3C244X_CIPRTAREA);		break;	case V4L2_PIX_FMT_RGB24:		/* CIPRCLRSA1 ~ CIPRCLRSA4. */		iowrite32(img_buff[0].phy_base, S3C244X_CIPRCLRSA1);		iowrite32(img_buff[1].phy_base, S3C244X_CIPRCLRSA2);		iowrite32(img_buff[2].phy_base, S3C244X_CIPRCLRSA3);		iowrite32(img_buff[3].phy_base, S3C244X_CIPRCLRSA4);		/* CIPRTRGFMT. */		ciprtrgfmt = (pdev->preTargetHsize<<16)		// horizontal pixel number of target image					 |(0<<14)						// don't mirror or rotation.					 |(pdev->preTargetVsize<<0);	// vertical pixel number of target image		iowrite32(ciprtrgfmt, S3C244X_CIPRTRGFMT);		/* CIPRCTRL. */		calc_burst_size(1, pdev->preTargetHsize, &mainBurstSize, &remainedBurstSize);		PDEBUG("preview main burst leng: %d, remained burst length: %d", mainBurstSize, remainedBurstSize);		ciprctrl = (mainBurstSize<<19)|(remainedBurstSize<<14);		iowrite32(ciprctrl, S3C244X_CIPRCTRL);		/* CIPRSCCTRL. */		ciprscctrl = ioread32(S3C244X_CIPRSCCTRL);		ciprscctrl &= 1<<15;	// clear all other info except 'preview scaler start'.		ciprscctrl |= 1<<30;	// 24-bits RGB		iowrite32(ciprscctrl, S3C244X_CIPRSCCTRL);	// 16-bit RGB		/* CIPRTAREA. */		iowrite32(pdev->preTargetHsize * pdev->preTargetVsize, S3C244X_CIPRTAREA);		break;	case V4L2_PIX_FMT_YUV420:		/* each pixel has one byte(8-bits) Y-weight. */		Ysize = pdev->coTargetHsize * pdev->coTargetVsize;		Csize = Ysize / 4;	// ?? for YCbCr 4:2:0		iowrite32(img_buff[0].phy_base, S3C244X_CICOYSA1);		iowrite32(img_buff[0].phy_base + Ysize, S3C244X_CICOCBSA1);		iowrite32(img_buff[0].phy_base + Ysize + Csize, S3C244X_CICOCRSA1);		iowrite32(img_buff[1].phy_base, S3C244X_CICOYSA2);		iowrite32(img_buff[1].phy_base + Ysize, S3C244X_CICOCBSA2);		iowrite32(img_buff[1].phy_base + Ysize + Csize, S3C244X_CICOCRSA2);		iowrite32(img_buff[2].phy_base, S3C244X_CICOYSA3);		iowrite32(img_buff[2].phy_base + Ysize, S3C244X_CICOCBSA3);		iowrite32(img_buff[2].phy_base + Ysize + Csize, S3C244X_CICOCRSA3);		iowrite32(img_buff[3].phy_base, S3C244X_CICOYSA4);		iowrite32(img_buff[3].phy_base + Ysize, S3C244X_CICOCBSA4);		iowrite32(img_buff[3].phy_base + Ysize + Csize, S3C244X_CICOCRSA4);		/* CICOTRGFMT. */		cicotrgfmt = (1<<31)	// YCbCr 4:2:2 codec scaler input image format					 |(0<<30)	// YCbCr 4:2:0 codec scaler output image format					 |(pdev->coTargetHsize<<16)	// target image's horizontal pixel number					 |(3<<14)	// normal, 180 degree rotation.					 |(pdev->coTargetVsize<<0);		iowrite32(cicotrgfmt, S3C244X_CICOTRGFMT);		/* CICOCTRL. */		calc_burst_size(4, pdev->coTargetHsize, &mainBurstSize, &remainedBurstSize);		PDEBUG("codec Y main burst leng: %d, remained burst length: %d", mainBurstSize, remainedBurstSize);		cicoctrl = (mainBurstSize<<19)|(remainedBurstSize<<14);		calc_burst_size(8, pdev->coTargetHsize, &mainBurstSize, &remainedBurstSize);		cicoctrl |= (mainBurstSize<<9)|(remainedBurstSize<<4);		iowrite32(cicoctrl, S3C244X_CICOCTRL);		/* CICOTAREA. */		iowrite32(pdev->coTargetHsize * pdev->coTargetVsize, S3C244X_CICOTAREA);		break;	case V4L2_PIX_FMT_YUYV:		/* each pixel has one byte(8-bits) Y-weight. */		Ysize = pdev->coTargetHsize * pdev->coTargetVsize;		Csize = Ysize / 2;	// ?? for YCbCr 4:2:2		iowrite32(img_buff[0].phy_base, S3C244X_CICOYSA1);		iowrite32(img_buff[0].phy_base + Ysize, S3C244X_CICOCBSA1);		iowrite32(img_buff[0].phy_base + Ysize + Csize, S3C244X_CICOCRSA1);		iowrite32(img_buff[1].phy_base, S3C244X_CICOYSA2);		iowrite32(img_buff[1].phy_base + Ysize, S3C244X_CICOCBSA2);		iowrite32(img_buff[1].phy_base + Ysize + Csize, S3C244X_CICOCRSA2);		iowrite32(img_buff[2].phy_base, S3C244X_CICOYSA3);		iowrite32(img_buff[2].phy_base + Ysize, S3C244X_CICOCBSA3);		iowrite32(img_buff[2].phy_base + Ysize + Csize, S3C244X_CICOCRSA3);		iowrite32(img_buff[3].phy_base, S3C244X_CICOYSA4);		iowrite32(img_buff[3].phy_base + Ysize, S3C244X_CICOCBSA4);		iowrite32(img_buff[3].phy_base + Ysize + Csize, S3C244X_CICOCRSA4);		/* CICOTRGFMT. */		cicotrgfmt = (1<<31)	// YCbCr 4:2:2 codec scaler input image format					 |(1<<30)	// YCbCr 4:2:2 codec scaler output image format					 |(pdev->coTargetHsize<<16)	// target image's horizontal pixel number					 |(3<<14)	// normal, 180 degree rotation.					 |(pdev->coTargetVsize<<0);		iowrite32(cicotrgfmt, S3C244X_CICOTRGFMT);		/* CICOCTRL. */		calc_burst_size(4, pdev->coTargetHsize, &mainBurstSize, &remainedBurstSize);		PDEBUG("codec Y main burst leng: %d, remained burst length: %d", mainBurstSize, remainedBurstSize);		cicoctrl = (mainBurstSize<<19)|(remainedBurstSize<<14);		calc_burst_size(8, pdev->coTargetHsize, &mainBurstSize, &remainedBurstSize);		cicoctrl |= (mainBurstSize<<9)|(remainedBurstSize<<4);		iowrite32(cicoctrl, S3C244X_CICOCTRL);		/* CICOTAREA. */		iowrite32(pdev->coTargetHsize * pdev->coTargetVsize, S3C244X_CICOTAREA);		break;	default:		PDEBUG("bug here.");		BUG();		break;	}}/* update CIWDOFST only. */static void __inline__ update_target_wnd_regs(struct s3c2440camif_dev * pdev){	u32 ciwdofst;	u32 winHorOfst, winVerOfst;	winHorOfst = (pdev->srcHsize - pdev->wndHsize)>>1;	winVerOfst = (pdev->srcVsize - pdev->wndVsize)>>1;	winHorOfst &= 0xFFFFFFF8;	winVerOfst &= 0xFFFFFFF8;	if ((winHorOfst == 0)&&(winVerOfst == 0))	{		ciwdofst = 0;	// disable windows offset.	}	else	{		ciwdofst = (1<<31)				// window offset enable					|(1<<30)			// clear the overflow ind flag of input CODEC FIFO Y					|(winHorOfst<<16)	// windows horizontal offset					|(1<<15)			// clear the overflow ind flag of input CODEC FIFO Cb					|(1<<14)			// clear the overflow ind flag of input CODEC FIFO Cr					|(1<<13)			// clear the overflow ind flag of input PREVIEW FIFO Cb					|(1<<12)			// clear the overflow ind flag of input PREVIEW FIFO Cr					|(winVerOfst<<0);	// window vertical offset	}	iowrite32(ciwdofst, S3C244X_CIWDOFST);}/* update registers: *	PREVIEW path: *		CIPRSCPRERATIO *		CIPRSCPREDST *		CIPRSCCTRL *	CODEC path: *		CICOSCPRERATIO *		CICOSCPREDST *		CICOSCCTRL */static void __inline__ update_target_zoom_regs(struct s3c2440camif_dev * pdev){

⌨️ 快捷键说明

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