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

📄 s3c2440camif.c

📁 ov9650的驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
 */static int camif_open(struct inode *inode, struct file *file){	int minor;	struct s3c2440camif_dev *h,*pdev;	struct s3c2440camif_fh *fh;	struct list_head *list;	int ret;	pdev = NULL;	minor = iminor(inode);	PDEBUG("pid %d[%s] tries to open the camera.\n", current->pid, current->comm);	/* find device. */	list_for_each(list,&camif_devlist)	{		h = list_entry(list, struct s3c2440camif_dev, devlist);		if (h->vfd->minor == minor)		{			pdev  = h;			break;		}	}	if (NULL == pdev)	{		PDEBUG("no video device, minor = %d\n", minor);		return -ENODEV;	}	fh = kzalloc(sizeof(*fh),GFP_KERNEL); // alloc memory for filehandle	if (NULL == fh)	{		PDEBUG("kernel memory alloc fail!\n");		return -ENOMEM;	}	fh->dev = pdev;	/* maybe this is a master open, maybe not. */	if (mutex_trylock(&pdev->mfhlock) != 0)	{		fh->master = 1;		PDEBUG("PID[%d:%s], this is a master open!\n", current->pid, current->comm);		pdev->state = CAMIF_STATE_READY;		PDEBUG("camera state is now READY!\n");		init_camif_config(fh);		PDEBUG("camera device is now initialized!\n");	}	else	{		PDEBUG("PID[%d:%s], this is a slave open!\n", current->pid, current->comm);		fh->master = 0;	}	/* maybe this is the first open, maybe not. */	mutex_lock(&pdev->rcmutex);	pdev->rc++;	if (pdev->rc == 1)		// if this the first open....	{		ret = init_image_buffer();	// init image buffer.		if (ret < 0)		{			PDEBUG("init image buffer fail!\n");			goto error1;		}		PDEBUG("image buffer init successfully!\n");		request_irq(IRQ_S3C2440_CAM_C, on_camif_irq_c, IRQF_DISABLED, "CAM_C", pdev);	// setup ISRs		if (ret < 0)		{			PDEBUG("init image buffer fail!\n");			goto error2;		}		PDEBUG("IRQ_S3C2440_CAM_C setup successfully!\n");		request_irq(IRQ_S3C2440_CAM_P, on_camif_irq_p, IRQF_DISABLED, "CAM_P", pdev);		if (ret < 0)		{			PDEBUG("init image buffer fail!\n");			goto error3;		}		PDEBUG("IRQ_S3C2440_CAM_P setup successfully!\n");		clk_enable(pdev->clk);		// and enable camif clock.		PDEBUG("camera interface clock enabled!\n");		soft_reset_camif();		PDEBUG("soft reset camif done!!\n");	}	mutex_unlock(&pdev->rcmutex);	file->private_data = fh;	fh->dev  = pdev;	PDEBUG("pid %d[%s] open the camera sucessfully.\n", current->pid, current->comm);	return 0;error3:	free_irq(IRQ_S3C2440_CAM_C, pdev);error2:	free_image_buffer();error1:	kfree(fh);	return ret;}/* * camif_read() */static ssize_t camif_read(struct file *file, char __user *data, size_t count, loff_t *ppos){	int i;	struct s3c2440camif_fh * fh;	struct s3c2440camif_dev * pdev;	ssize_t size;	struct v4l2_format fmt;	fh = file->private_data;	pdev = fh->dev;	PDEBUG("pid %d[%s] is trying to read frame data from camif..\n", current->pid, current->comm);	fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;	vidioc_g_fmt_cap(file, fh, &fmt);	size = fmt.fmt.pix.sizeimage;	PDEBUG("each frame size is %dKBytes.\n", size/1024);	if (start_capture(pdev, 0) != 0)	{		PDEBUG("read action wakeuped by a asynchronous signal!\n");		return -ERESTARTSYS;	}	disable_irq(IRQ_S3C2440_CAM_C);	disable_irq(IRQ_S3C2440_CAM_P);	for (i = 0; i < 4; i++)	{		if (img_buff[i].state != CAMIF_BUFF_INVALID)		{			copy_to_user(data, (void *)img_buff[i].virt_base, (count<size)?count:size);			img_buff[i].state = CAMIF_BUFF_INVALID;		}	}	enable_irq(IRQ_S3C2440_CAM_P);	enable_irq(IRQ_S3C2440_CAM_C);#if 0	for (i = 0; i < 240 * 100; i++)	{		((unsigned short *)img_buff[0].base)[i] = 0xF800;	}	for (i = 240*100; i < 2* 240 * 100; i+=1)	{		((unsigned short *)img_buff[0].base)[i] = 0x07E0;	}	for (i = 240*100*2; i < 240 * 320; i+=1)	{		((unsigned short *)img_buff[0].base)[i] = 0x001F;	}	copy_to_user(data, (void *)img_buff[0].base, size);#endif	PDEBUG("pid %d[%s] read %d bytes from camera\n", current->pid, current->comm, (count<size)?count:size);	return size;}/* * camif_poll() */static unsigned int camif_poll(struct file *file, struct poll_table_struct *wait){	struct s3c2440camif_fh * fh;	fh = file->private_data;	PDEBUG("%s(): not implement now!\n", __FUNCTION__);	BUG();		return -ENOENT;}/* * camif_release() */static int camif_release(struct inode *inode, struct file *file){	int minor;	struct s3c2440camif_fh	* fh;	struct s3c2440camif_dev * pdev;	minor = iminor(inode);	fh = file->private_data;	pdev = fh->dev;	PDEBUG("pid %d[%s] tries to close camera.\n", current->pid, current->comm);	if (fh->master != 0)	{		PDEBUG("master file handle close, release the device master file handle lock!\n");		mutex_unlock(&pdev->mfhlock);	}	/* maybe this is the latest close, maybe not. */	mutex_lock(&pdev->rcmutex);	pdev->rc--;	if (pdev->rc == 0)	// latest close,	{//		stop_capture(pdev);		// stop capturing...		PDEBUG("capturing stopped!\n");		clk_disable(pdev->clk);				// stop camif clock		PDEBUG("camif clock stopped!\n");		free_irq(IRQ_S3C2440_CAM_P, pdev);	// free camif IRQs		PDEBUG("IRQ_S3C2440_CAM_P freed!\n");		free_irq(IRQ_S3C2440_CAM_C, pdev);		PDEBUG("IRQ_S3C2440_CAM_C freed!\n");		free_image_buffer();	// and free image buffer		PDEBUG("image buffer freed.\n");	}	mutex_unlock(&pdev->rcmutex);	PDEBUG("pid %d[%s] close camera successfully.\n", current->pid, current->comm);	return 0;}/* * camif_mmap() */static int camif_mmap(struct file *file, struct vm_area_struct * vma){	int ret;	struct s3c2440camif_fh * fh;	fh = file->private_data;	(void)ret;	PDEBUG("now in %s(), vma=0x%08lx\n",__FUNCTION__, (unsigned long)vma);	PDEBUG("%s(): not implement now!\n", __FUNCTION__);	BUG();	return -ENOENT;}/* * the key methods/attributes for this video device. */static struct file_operations camif_fops ={	.owner		= THIS_MODULE,	.open		= camif_open,	.release	= camif_release,	.read		= camif_read,	.poll		= camif_poll,	.ioctl		= video_ioctl2, /* V4L2 ioctl handler */	.mmap		= camif_mmap,	.llseek		= no_llseek,};/* * camif_dev_release() */static void camif_dev_release (struct video_device *vfd){	PDEBUG("now in %s()!\n", __FUNCTION__);}/* * the inner structure to register to videodev layer. */static struct video_device camif_dev ={	.name		= "s3c2440 camif",	.type		= VID_TYPE_CAPTURE|VID_TYPE_SCALES|VID_TYPE_SUBCAPTURE,	.hardware	= 0,	.fops		= &camif_fops,	.minor		= -1,	.release    = camif_dev_release,	.vidioc_querycap      = vidioc_querycap,	.vidioc_enum_fmt_cap  = vidioc_enum_fmt_cap,	.vidioc_g_fmt_cap     = vidioc_g_fmt_cap,	.vidioc_s_fmt_cap     = vidioc_s_fmt_cap,	.vidioc_queryctrl = vidioc_queryctrl,	.vidioc_g_ctrl = vidioc_g_ctrl,	.vidioc_s_ctrl = vidioc_s_ctrl,#ifdef CONFIG_VIDEO_V4L1_COMPAT	.vidiocgmbuf          = vidiocgmbuf,#endif};static struct s3c2440camif_dev camera;#if 1int __init sccb_init(void);void __exit sccb_cleanup(void);int __init ov9650_init(void);void __exit ov9650_cleanup(void);#endif/* * camif_init() */static int __init camif_init(void){	int ret;	struct s3c2440camif_dev * pdev;	struct clk * camif_upll_clk;	printk(KERN_ALERT"initializing s3c2440 camera interface......\n");	pdev = &camera;	pdev->vfd = &camif_dev;	/* set gpio-j to camera mode. */	PDEBUG("set GPIO-J to camera mode.\n");	PDEBUG("GPJCON=0x%08x\n", __raw_readl(S3C24XX_GPIO_BASE(S3C2440_GPJ0)));	s3c2410_gpio_cfgpin(S3C2440_GPJ0, S3C2440_GPJ0_CAMDATA0);	s3c2410_gpio_cfgpin(S3C2440_GPJ1, S3C2440_GPJ1_CAMDATA1);	s3c2410_gpio_cfgpin(S3C2440_GPJ2, S3C2440_GPJ2_CAMDATA2);	s3c2410_gpio_cfgpin(S3C2440_GPJ3, S3C2440_GPJ3_CAMDATA3);	s3c2410_gpio_cfgpin(S3C2440_GPJ4, S3C2440_GPJ4_CAMDATA4);	s3c2410_gpio_cfgpin(S3C2440_GPJ5, S3C2440_GPJ5_CAMDATA5);	s3c2410_gpio_cfgpin(S3C2440_GPJ6, S3C2440_GPJ6_CAMDATA6);	s3c2410_gpio_cfgpin(S3C2440_GPJ7, S3C2440_GPJ7_CAMDATA7);	s3c2410_gpio_cfgpin(S3C2440_GPJ8, S3C2440_GPJ8_CAMPCLK);	s3c2410_gpio_cfgpin(S3C2440_GPJ9, S3C2440_GPJ9_CAMVSYNC);	s3c2410_gpio_cfgpin(S3C2440_GPJ10, S3C2440_GPJ10_CAMHREF);	s3c2410_gpio_cfgpin(S3C2440_GPJ11, S3C2440_GPJ11_CAMCLKOUT);	s3c2410_gpio_cfgpin(S3C2440_GPJ12, S3C2440_GPJ12_CAMRESET);	PDEBUG("GPJCON=0x%08x\n", __raw_readl(S3C24XX_GPIO_BASE(S3C2440_GPJ0)));	/* init camera's virtual memory. */	PDEBUG("request camera virtual memory region.\n");	if (!request_mem_region((unsigned long)S3C2440_PA_CAMIF, S3C2440_SZ_CAMIF, DRIVER_NAME))	{		PDEBUG("can't request virtual memory region for camera!\n");		ret = -EBUSY;		goto error1;	}	/* remap the virtual memory. */	PDEBUG("remap camera virtual memory region.\n");	camif_base_addr = (unsigned long)ioremap_nocache((unsigned long)S3C2440_PA_CAMIF, S3C2440_SZ_CAMIF);	if (camif_base_addr == (unsigned long)NULL)	{		PDEBUG("can't remap virtual memory region for camera!\n");		ret = -EBUSY;		goto error2;	}	PDEBUG("camif_base_addr = 0x%08x\n", (unsigned)camif_base_addr);	/* init camera clock. */	PDEBUG("initialize camera clock.\n");	pdev->clk = clk_get(NULL, "camif");	if (IS_ERR(pdev->clk))	{		PDEBUG("can't get system clock for camera!\n");		ret = -ENOENT;		goto error3;	}	clk_enable(pdev->clk);	camif_upll_clk = clk_get(NULL, "camif-upll");	if (IS_ERR(camif_upll_clk))	{		PDEBUG("can't get UPLL clock for camera!\n");	}	clk_set_rate(camif_upll_clk, 24000000);	mdelay(100);	/* init reference counter and its mutex. */	mutex_init(&pdev->rcmutex);	pdev->rc = 0;	/* init master file handle mutex. */	mutex_init(&pdev->mfhlock);	/* init image input source. */	pdev->input = 0;	/* init camif state and its lock. */	pdev->state = CAMIF_STATE_FREE;	spin_lock_init(&pdev->statelock);	/* init command code, command lock and the command wait queue. */	pdev->cmdcode = CAMIF_CMD_NONE;	spin_lock_init(&pdev->cmdlock);	init_waitqueue_head(&pdev->cmdqueue);	/* add to device chain. */	list_add_tail(&pdev->devlist, &camif_devlist);	/* register to videodev layer. */	camif_dev.minor = video_nr;	if (video_register_device(&camif_dev, VFL_TYPE_GRABBER, camif_dev.minor) != 0)	{		PDEBUG("register video device to videodev layer fail!\n");		ret = -EBUSY;		goto error4;	}	PDEBUG("register video device to videodev layer successfully!\n");	printk(KERN_ALERT"s3c2440 camif init done!\n");		sccb_init();	ov9650_init();	return 0;error4:	mutex_destroy(&pdev->mfhlock);	mutex_destroy(&pdev->rcmutex);	clk_put(pdev->clk);error3:	iounmap((void *)camif_base_addr);error2:	release_mem_region((unsigned long)S3C2440_PA_CAMIF, S3C2440_SZ_CAMIF);	error1:	return ret;}/* * camif_cleanup() */static void __exit camif_cleanup(void){	struct s3c2440camif_dev *pdev;	ov9650_cleanup();	sccb_cleanup();	pdev = &camera;	PDEBUG("removing s3c2440 camera interface......\n");	video_unregister_device(pdev->vfd);	PDEBUG("unregister camif device successfully!\n");	mutex_destroy(&pdev->mfhlock);	mutex_destroy(&pdev->rcmutex);	clk_put(pdev->clk);	iounmap((void *)camif_base_addr);	release_mem_region((unsigned long)S3C2440_PA_CAMIF, S3C2440_SZ_CAMIF);	printk(KERN_ALERT"s3c2440camif: module removed!\n");}static LIST_HEAD(input_devlist);int s3c2440_camif_register_camhw (struct s3c2440camif_hw * camifhw){	if (camifhw == NULL)	{		PDEBUG("bug here.\n");		BUG();	}	list_add_tail(&camifhw->devlist, &input_devlist);	hw_reset_camif();	if (camifhw->init != NULL)	{		camifhw->init();	}	return 0;}EXPORT_SYMBOL(s3c2440_camif_register_camhw);void s3c2440_camif_unregister_camhw (struct s3c2440camif_hw * camifhw){	if (camifhw == NULL)	{		PDEBUG("bug here.\n");		BUG();	}	if (camifhw->cleanup != NULL)	{		camifhw->cleanup();	}	list_del(&camifhw->devlist);}EXPORT_SYMBOL(s3c2440_camif_unregister_camhw);#if 0static void print_regs(void){	PDEBUG("S3C244X_CISRCFMT		 = 0x%08x\n", ioread32(S3C244X_CISRCFMT));	PDEBUG("S3C244X_CIWDOFST		 = 0x%08x\n", ioread32(S3C244X_CIWDOFST));	PDEBUG("S3C244X_CIGCTRL			 = 0x%08x\n", ioread32(S3C244X_CIGCTRL));	PDEBUG("S3C244X_CICOYSA1		 = 0x%08x\n", ioread32(S3C244X_CICOYSA1));	PDEBUG("S3C244X_CICOYSA2		 = 0x%08x\n", ioread32(S3C244X_CICOYSA2));	PDEBUG("S3C244X_CICOYSA3		 = 0x%08x\n", ioread32(S3C244X_CICOYSA3));	PDEBUG("S3C244X_CICOYSA4		 = 0x%08x\n", ioread32(S3C244X_CICOYSA4));	PDEBUG("S3C244X_CICOCBSA1		 = 0x%08x\n", ioread32(S3C244X_CICOCBSA1));	PDEBUG("S3C244X_CICOCBSA2		 = 0x%08x\n", ioread32(S3C244X_CICOCBSA2));	PDEBUG("S3C244X_CICOCBSA3		 = 0x%08x\n", ioread32(S3C244X_CICOCBSA3));	PDEBUG("S3C244X_CICOCBSA4		 = 0x%08x\n", ioread32(S3C244X_CICOCBSA4));	PDEBUG("S3C244X_CICOCRSA1		 = 0x%08x\n", ioread32(S3C244X_CICOCRSA1));	PDEBUG("S3C244X_CICOCRSA2		 = 0x%08x\n", ioread32(S3C244X_CICOCRSA2));	PDEBUG("S3C244X_CICOCRSA3		 = 0x%08x\n", ioread32(S3C244X_CICOCRSA3));	PDEBUG("S3C244X_CICOCRSA4		 = 0x%08x\n", ioread32(S3C244X_CICOCRSA4));	PDEBUG("S3C244X_CICOTRGFMT		 = 0x%08x\n", ioread32(S3C244X_CICOTRGFMT));	PDEBUG("S3C244X_CICOCTRL		 = 0x%08x\n", ioread32(S3C244X_CICOCTRL));	PDEBUG("S3C244X_CICOSCPRERATIO   = 0x%08x\n", ioread32(S3C244X_CICOSCPRERATIO));	PDEBUG("S3C244X_CICOSCPREDST	 = 0x%08x\n", ioread32(S3C244X_CICOSCPREDST));	PDEBUG("S3C244X_CICOSCCTRL		 = 0x%08x\n", ioread32(S3C244X_CICOSCCTRL));	PDEBUG("S3C244X_CICOTAREA		 = 0x%08x\n", ioread32(S3C244X_CICOTAREA));	PDEBUG("S3C244X_CICOSTATUS		 = 0x%08x\n", ioread32(S3C244X_CICOSTATUS));	PDEBUG("S3C244X_CIPRCLRSA1		 = 0x%08x\n", ioread32(S3C244X_CIPRCLRSA1));	PDEBUG("S3C244X_CIPRCLRSA2		 = 0x%08x\n", ioread32(S3C244X_CIPRCLRSA2));	PDEBUG("S3C244X_CIPRCLRSA3		 = 0x%08x\n", ioread32(S3C244X_CIPRCLRSA3));	PDEBUG("S3C244X_CIPRCLRSA4		 = 0x%08x\n", ioread32(S3C244X_CIPRCLRSA4));	PDEBUG("S3C244X_CIPRTRGFMT		 = 0x%08x\n", ioread32(S3C244X_CIPRTRGFMT));	PDEBUG("S3C244X_CIPRCTRL		 = 0x%08x\n", ioread32(S3C244X_CIPRCTRL));	PDEBUG("S3C244X_CIPRSCPRERATIO   = 0x%08x\n", ioread32(S3C244X_CIPRSCPRERATIO));	PDEBUG("S3C244X_CIPRSCPREDST	 = 0x%08x\n", ioread32(S3C244X_CIPRSCPREDST));	PDEBUG("S3C244X_CIPRSCCTRL		 = 0x%08x\n", ioread32(S3C244X_CIPRSCCTRL));	PDEBUG("S3C244X_CIPRTAREA		 = 0x%08x\n", ioread32(S3C244X_CIPRTAREA));	PDEBUG("S3C244X_CIPRSTATUS		 = 0x%08x\n", ioread32(S3C244X_CIPRSTATUS));	PDEBUG("S3C244X_CIIMGCPT		 = 0x%08x\n", ioread32(S3C244X_CIIMGCPT));}#endifMODULE_DESCRIPTION("v4l2 driver module for s3c2440 camera interface");MODULE_AUTHOR("sunxq [baobaoba520@yahoo.com.cn]");MODULE_LICENSE("GPL");module_init(camif_init);module_exit(camif_cleanup);

⌨️ 快捷键说明

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