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

📄 s3c2440_ov7620.c

📁 三星s3c2440 ARM9芯片在linux下的摄像头驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
	}#endif#if DEBUG_WORK_STANDALONE	CAPTURE_PORT_A();#endif}static void cam_to_rgb32_sw(int frame, struct s3c2440_camif_cfg_t *cfg){	int i;	for (i = 0; i < cfg->dst_y; i++)		yuv_convert_rgb32(yuv_buf[frame].buf + i * cfg->dst_x,				yuv_buf[frame].buf + cfg->dst_x*cfg->dst_y 					+ (i/2) * cfg->dst_x / 2,				yuv_buf[frame].buf + cfg->dst_x*cfg->dst_y/2*3 					+ (i/2) * cfg->dst_x / 2,				rgb_buf[frame].buf + i * cfg->dst_x * 4,				cfg->dst_x);	frame_to_user = frame;#if DEBUG_WORK_STANDALONE	CAPTURE_PORT_A();#endif}static void cam_to_yuv420(int frame, struct s3c2440_camif_cfg_t *cfg){	int i;	/* Y */	memcpy(rgb_buf[frame].buf, yuv_buf[frame].buf, cfg->dst_x * cfg->dst_y);	/* U */	for (i = 0; i < cfg->dst_y * 2; i++)		memcpy(			rgb_buf[frame].buf + cfg->dst_x * cfg->dst_y + i * cfg->dst_x / 2			, yuv_buf[frame].buf + cfg->dst_x * cfg->dst_y + (i/2) * cfg->dst_x / 2			, cfg->dst_x / 2);	/* V */	for (i = 0; i < cfg->dst_y * 2; i++)		memcpy(			rgb_buf[frame].buf + cfg->dst_x * cfg->dst_y / 2 * 3 + i * cfg->dst_x / 2			, yuv_buf[frame].buf + cfg->dst_x * cfg->dst_y / 2 * 3 + (i/2) * cfg->dst_x / 2			, cfg->dst_x / 2);	frame_to_user = frame;#if DEBUG_WORK_STANDALONE	CAPTURE_PORT_A();#endif}static void s3c2440_camif_config(struct s3c2440_camif_cfg_t *cfg){	int i;	unsigned long adist, awidth;	unsigned long hratio, vratio;	int mburst, rburst;//	unsigned long frame_offset_yuv = PAGE_ALIGN(YUV_TUPLE_SIZE);//	unsigned long frame_offset_rgb = PAGE_ALIGN(RGB_TUPLE_SIZE);	for (i = 0; i < 4; i++) {		yuv_buf[i].buf = camif_yuv_buf;		yuv_buf[i].phys_addr = (unsigned int)camif_yuv_buf_dma;		DPRINTK("yuv_buf[%d] : virt=0x%08lx, phys = 0x%08lx\n",				i, (unsigned long)yuv_buf[i].buf, (unsigned long)yuv_buf[i].phys_addr);		rgb_buf[i].buf = camif_rgb_buf;		rgb_buf[i].phys_addr = (unsigned int)camif_rgb_buf_dma;		DPRINTK("rgb_buf[%d] : virt=0x%08lx, phys = 0x%08lx\n",				i, (unsigned long)rgb_buf[i].buf, (unsigned long)rgb_buf[i].phys_addr);		CAM_STAY(i) = yuv_buf[i].phys_addr;		DPRINTK2("STAY%d  = 0x%08x\n", i, yuv_buf[i].phys_addr);		CAM_STACB(i) = yuv_buf[i].phys_addr + cfg->dst_x*cfg->dst_y;		DPRINTK2("STACB%d = 0x%08x\n", i, yuv_buf[i].phys_addr + cfg->dst_x*cfg->dst_y);		CAM_STACR(i) = yuv_buf[i].phys_addr + cfg->dst_x*cfg->dst_y / 2 * 3;		DPRINTK2("STACR%d = 0x%08x\n", i, yuv_buf[i].phys_addr + cfg->dst_x*cfg->dst_y / 2 * 3);	}	CAM_ASIZE = CAM_SIZE_H(cfg->dst_x) | CAM_SIZE_V(cfg->dst_y);#if 1	mburst = 4;	rburst = (cfg->dst_x / 4) % mburst;#endif#if 1	rburst = rburst ? rburst : mburst;#endif#if 0	mburst = 16;        rburst = ((cfg->dst_x / 4) + mburst) % mburst;#endif	CAM_AYBURST = CAM_BURST_M(mburst) | CAM_BURST_R(rburst);	DPRINTK2("YBURST = %d,%d = 0x%08lx\n", mburst, rburst			, CAM_BURST_M(mburst) | CAM_BURST_R(rburst));#if 1	mburst = 4;	rburst = (cfg->dst_x / 2 / 4) % mburst;#endif#if 1	rburst = rburst ? rburst : mburst;#endif	CAM_ACBBURST = CAM_BURST_M(mburst) | CAM_BURST_R(rburst);	CAM_ACRBURST = CAM_BURST_M(mburst) | CAM_BURST_R(rburst);	DPRINTK2("CBBURST = %d,%d = 0x%08lx\n", mburst, rburst			, CAM_BURST_M(mburst) | CAM_BURST_R(rburst));	/*	 * Adist =  ( MemoryBusClk/CameraClk ) * 3 * Width	 * CameraClk = UPLL / [(CAMCLK_DIV + 1) * 2]	 * 					by SW.LEE	 */	adist = ( s3c2440_get_bus_clk(GET_HCLK) * 3 * cfg->src_x )		/ get_camera_clk();	awidth = adist;	CAM_ADISTWIDTH = CAM_DISTWIDTH_D(adist) | CAM_DISTWIDTH_W(awidth);	DPRINTK2("HCLK = %ld, pixel_clock = %ld, adist = %ld\n"			, s3c2440_get_bus_clk(GET_HCLK)			,  get_camera_clk()			, adist		);			DPRINTK2("CAM_ADISTWIDTH = 0x%08lx\n"			, CAM_DISTWIDTH_D(adist) | CAM_DISTWIDTH_W(awidth));	hratio = (cfg->src_x * 4096) / cfg->dst_x;	vratio = (cfg->src_y * 4096) / cfg->dst_y;	CAM_YRATIO = CAM_RATIO_H(hratio) | CAM_RATIO_V(vratio);	DPRINTK2("YRATIO = %ld,%ld = 0x%08lx\n", hratio, vratio			, CAM_RATIO_H(hratio) | CAM_RATIO_V(vratio));	hratio = ((cfg->src_x/2) * 4096) / (cfg->dst_x/2);	vratio = (cfg->src_y * 4096) / (cfg->dst_y/2);		CAM_CRATIO = CAM_RATIO_H(hratio) | CAM_RATIO_V(vratio);	DPRINTK2("CRATIO = %ld,%ld = 0x%08lx\n", hratio, vratio			, CAM_RATIO_H(hratio) | CAM_RATIO_V(vratio));	CAM_YORIGINAL = CAM_ORIGINAL_H(cfg->src_x) | CAM_ORIGINAL_V(cfg->src_y);	DPRINTK2("YORIGINAL = 0x%08lx\n", 			CAM_ORIGINAL_H(cfg->src_x) | CAM_ORIGINAL_V(cfg->src_y));	CAM_CORIGINAL = CAM_ORIGINAL_H((cfg->src_x/2)) | CAM_ORIGINAL_V(cfg->src_y);	DPRINTK2("CORIGINAL = 0x%08lx\n", 			CAM_ORIGINAL_H((cfg->src_x/2)) | CAM_ORIGINAL_V(cfg->src_y));	switch (cfg->dst_type) {		case CAMIF_TYPE_RGB16 : 			cfg->camif_frame_handler = cam_to_rgb16_sw;			break;		case CAMIF_TYPE_RGB32 :			cfg->camif_frame_handler = cam_to_rgb32_sw;			break;		case CAMIF_TYPE_YUV420 :			cfg->camif_frame_handler = cam_to_yuv420;			break;			panic("unknown destination type.\n");	}	if (!cfg->camif_frame_handler)		panic("unknown dst_type.\n");}static void s3c2440_cam_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);}/*  * $\> SW.LEE *  * OV7620_CLK is 12Mhz or 24Mhz * * CAMCLK = OV7620_CLK; * CAMCLK_DIV =  UPLL / ( CAMCLK * 2)  - 1 ;  */ void inline s3c2440_camif_init(void){	unsigned int upll, uclk, camclk,camclk_div;	camclk = get_camera_clk();	CLKCON |= CLKCON_CAMIF;/* Supposed that you must set UPLL at first */	UPLLCON = FInsrt(0x38, fPLL_MDIV) | FInsrt(0x02, fPLL_PDIV)	                                | FInsrt(0x02, fPLL_SDIV);	upll = s3c2440_get_bus_clk(GET_UPLL);	uclk = (CLKDIVN & DIVN_UPLL_EN) ? upll/2 : upll;	printk("CAMERA : UPLL %08d  UCLK %08d CAMCLK %08d \n",upll, uclk, camclk);	camclk_div = upll /( camclk * 2) -1 ;	CAMDIVN = CAMCLK_SET_DIV | (camclk_div & 0xf ) ;}void inline s3c2440_camif_deinit(void){	CLKCON &= ~CLKCON_CAMIF;	CAM_CTRL = 0;	mdelay(5);}static void cam_s_task_handler(void * data){	struct s3c2440_camif_cfg_t *cfg = (struct s3c2440_camif_cfg_t *)data;		int frame = (CAM_STAT_FRAME(CAM_RDSTAT) ); // + 3) % 4;//	CAM_CTRL &= ~(1<<18);	DPRINTK("frame = %d\n", frame);	cfg->camif_frame_handler(frame, cfg);#if MORE_STABLE_BUT_SLOW	DPRINTK2("wait for stable\n");	interruptible_sleep_on_timeout(&cam_wait, 8);	DPRINTK2("wait done\n");	if (signal_pending(current)) 		goto out;	memcpy(camif_user_buf, rgb_buf[frame_to_user].buf, USER_TUPLE_SIZE);out:#endif	wake_up_interruptible(&camdev_wait);	UNSET_CAM(CAM_CAPTURING);}static void s3c2440_camif_isr_s(int irq, void *dev_id, struct pt_regs *regs){	schedule_task(&cam_s_task);}/*************** end of CAMIF ******************//*********** start of device interface *********/static int camdev_open_count = 0;int inline cam_init(void){	enable_irq(IRQ_CAM_S);	return 0;}void inline cam_deinit(void){	disable_irq(IRQ_CAM_S);}int inline cam_setparam(struct s3c2440_camif_cfg_t *param){	s3c2440_camif_cfg.dst_x = param->dst_x;	s3c2440_camif_cfg.dst_y = param->dst_y;	s3c2440_camif_cfg.dst_type = param->dst_type;	/*	 * ToDo	 *  lock & unlock	 */	if ( 1 == camdev_open_count)		s3c2440_camif_config(&s3c2440_camif_cfg);	return 0;}static int cam_open(struct inode *inode, struct file *file){	DPRINTK("open_count = %d\n", camdev_open_count);	/*	 * ToDo	 * lock & unlock 	 */	if (0 == camdev_open_count) {		if (cam_init() < 0)			return -EIO;		SET_CAM(CAM_OPENED);	}	camdev_open_count ++;	return 0;}static int cam_release(struct inode *inode, struct file *file){	camdev_open_count --;	/*	 * ToDo	 * lock & unlock 	 */	if (!camdev_open_count) {		disable_irq(IRQ_CAM_S);		flush_scheduled_tasks();		cam_deinit();		UNSET_CAM(CAM_CAPTURING);		UNSET_CAM(CAM_OPENED);	}		return 0;}static ssize_t cam_read(struct file *f, char *buf, size_t count, loff_t *pos){	size_t end;	if (IS_CAM(CAM_CAPTURING)) {		interruptible_sleep_on(&camdev_wait);		if (signal_pending(current)) {			return -EIO;		}	}#if 0	if (!(f->f_flags & O_NONBLOCK)) {		return -EPERM;						}#endif#if MORE_STABLE_BUT_SLOW	end = min_t(size_t, USER_TUPLE_SIZE, count);	if (copy_to_user(buf, camif_user_buf, end))		return -EFAULT;#else	end = min_t(size_t, RGB_TUPLE_SIZE, count);	if (copy_to_user(buf, rgb_buf[frame_to_user].buf, end))		return -EFAULT;#endif	return end;}static ssize_t cam_write(struct file *f, const char *b, size_t c, loff_t *pos){	if (IS_CAM(CAM_CAPTURING)) {		printk("already capturing...\n");		return c;	}	SET_CAM(CAM_CAPTURING);	CAPTURE_PORT_A();	return c;}static int cam_ioctl(struct inode *inode, struct file *file, 		unsigned int cmd, unsigned long arg){	struct s3c2440_camif_cfg_t tmp_caminfo;	int ret = 0;	switch(cmd) {		case 0x10:			if (copy_from_user(&tmp_caminfo, (struct s3c2440_camif_cfg_t*)arg, 					sizeof(struct s3c2440_camif_cfg_t)))				return -EFAULT;			ret = cam_setparam(&tmp_caminfo);			break;		default:			return -EINVAL;	}	return ret;}static struct file_operations cam_fops = {	owner  :  THIS_MODULE,	llseek :  no_llseek,	open   :  cam_open,	read   :  cam_read,	write  :  cam_write,	ioctl  :  cam_ioctl,	release : cam_release,};static struct miscdevice cam_dev = {	minor :  MISC_DYNAMIC_MINOR,	name  :  "cam",	fops  :  &cam_fops};/************* end of device interface *********/int __init init_s3c2440_ov7620(void){	int ret = 0;	printk("Starting S3C2440 Camera \n");	DPRINTK("camif_dst_x = %d, camif_dst_y = %d\n", camif_dst_x, camif_dst_y);	camif_yuv_buf = consistent_alloc(GFP_KERNEL, YUV_IMG_BUF_SIZE, &camif_yuv_buf_dma);	if (!camif_yuv_buf) printk(" Faile YUV_IMG_BUF \n");	camif_rgb_buf = consistent_alloc(GFP_KERNEL, RGB_IMG_BUF_SIZE, &camif_rgb_buf_dma);	if (!camif_rgb_buf) printk(" Faile RGB_IMG_BUF \n");#if MORE_STABLE_BUT_SLOW	camif_user_buf = (unsigned char *)vmalloc(USER_TUPLE_SIZE);#endif	if (!camif_yuv_buf || !camif_rgb_buf #if MORE_STABLE_BUT_SLOW					|| !camif_user_buf#endif	) {		printk(" CAMERA Memory allocation failed \n");		ret = -ENOMEM;		goto mem_err;	}	memset(camif_yuv_buf, 0, YUV_IMG_BUF_SIZE);	memset(camif_rgb_buf, 0, RGB_IMG_BUF_SIZE);	init_yuvtable();	INIT_TQUEUE(&cam_s_task, cam_s_task_handler, (void*)&s3c2440_camif_cfg);	s3c2440_cam_gpio_init();	s3c2440_camif_init();	/* default config */	s3c2440_camif_cfg.src_x = CAM_SRC_X;	s3c2440_camif_cfg.src_y = CAM_SRC_Y;	s3c2440_camif_cfg.dst_x = camif_dst_x;	s3c2440_camif_cfg.dst_y = camif_dst_y;	s3c2440_camif_cfg.dst_type = CAMIF_DEFAULT_FMT;	s3c2440_camif_config(&s3c2440_camif_cfg);	ov7620_init();	if ((ret != check_ov7620()))		if ((ret = check_ov7620()))			goto err_not_det;	ov7620_config();	printk("OV7620 [0x12] = 0x%02x\n", ov7620_sccb_receivebyte(0x12));	if ((ret = request_irq(IRQ_CAM_S, s3c2440_camif_isr_s, SA_INTERRUPT,			"CAM_S", NULL))) {		printk("request_irq(CAM_S) failed.\n");		goto err_irq_s;	}	disable_irq(IRQ_CAM_S);	flush_scheduled_tasks();#if DEBUG_WORK_STANDALONE	/* capture A port */	enable_irq(IRQ_CAM_S);	CAPTURE_PORT_A();#else	misc_register(&cam_dev);#endif	return 0;err_irq_s:	free_irq(IRQ_CAM_S, NULL);err_not_det:	ov7620_deinit();	s3c2440_camif_deinit();mem_err:	if (camif_yuv_buf)		consistent_free(camif_yuv_buf, YUV_IMG_BUF_SIZE , camif_yuv_buf_dma);	if (camif_rgb_buf)		consistent_free(camif_rgb_buf, RGB_IMG_BUF_SIZE , camif_rgb_buf_dma);	return ret;}void __exit exit_s3c2440_ov7620(void){	disable_irq(IRQ_CAM_S);	flush_scheduled_tasks();	s3c2440_camif_deinit();	free_irq(IRQ_CAM_S, NULL);	ov7620_deinit();	DPRINTK(" CAMEAR: Free Consistent Memory \n");	if (camif_yuv_buf)		consistent_free(camif_yuv_buf, YUV_IMG_BUF_SIZE , camif_yuv_buf_dma);	if (camif_rgb_buf)		consistent_free(camif_rgb_buf, RGB_IMG_BUF_SIZE , camif_rgb_buf_dma);#if MORE_STABLE_BUT_SLOW	if (camif_user_buf)		vfree(camif_user_buf);#endif#if DEBUG_WORK_STANDALONE	/* do nothing */#else	misc_deregister(&cam_dev);#endif}module_init(init_s3c2440_ov7620);module_exit(exit_s3c2440_ov7620);MODULE_PARM(camif_dst_x, "i");MODULE_PARM_DESC(camif_dst_x, "S3C2440 CAMIF, width of destination image");MODULE_PARM(camif_dst_y, "i");MODULE_PARM_DESC(camif_dst_y, "S3C2440 CAMIF, height of destination image");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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