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

📄 s3c2440camif.c

📁 ov9650的驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
	u32 preHratio, preVratio;	u32 Hshift, Vshift;	u32 shfactor;	u32 preDstWidth, preDstHeight;	u32 Hscale, Vscale;	u32 mainHratio, mainVratio;	u32 ciprscpreratio;	u32 ciprscpredst;	u32 ciprscctrl;	u32 cicoscpreratio;	u32 cicoscpredst;	u32 cicoscctrl;	switch (formats[pdev->format].pixelformat)	{	case V4L2_PIX_FMT_RGB565:	case V4L2_PIX_FMT_RGB24:		/* CIPRSCPRERATIO. */		calc_prescaler_ratio_shift(pdev->wndHsize, pdev->preTargetHsize,									&preHratio, &Hshift);		calc_prescaler_ratio_shift(pdev->wndVsize, pdev->preTargetVsize,									&preVratio, &Vshift);		PDEBUG("preHratio = %d, Hshift = %d.\n", preHratio, Hshift);		PDEBUG("preVratiod = %d, Vshift = %d.\n", preVratio, Vshift);		shfactor = 10 - (Hshift + Vshift);		ciprscpreratio = (shfactor<<28)		// shift factor for preview pre-scaler						 |(preHratio<<16)	// horizontal ratio of preview pre-scaler						 |(preVratio<<0);	// vertical ratio of preview pre-scaler		iowrite32(ciprscpreratio, S3C244X_CIPRSCPRERATIO);		/* CIPRSCPREDST. */		preDstWidth = pdev->wndHsize / preHratio;		preDstHeight = pdev->wndVsize / preVratio;		PDEBUG("preDstWidth = %d, preDstHeight = %d\n", preDstWidth, preDstHeight);		PDEBUG("pdev->wndHsize = %d, pdev->wndVsize = %d\n", pdev->wndHsize, pdev->wndVsize);		ciprscpredst = (preDstWidth<<16)	// destination width for preview pre-scaler					   |(preDstHeight<<0);	// destination height for preview pre-scaler		iowrite32(ciprscpredst, S3C244X_CIPRSCPREDST);		/* CIPRSCCTRL. */		Hscale = (pdev->wndHsize >= pdev->preTargetHsize)?0:1;		Vscale = (pdev->wndVsize >= pdev->preTargetVsize)?0:1;		mainHratio = (pdev->wndHsize<<8)/(pdev->preTargetHsize<<Hshift);		mainVratio = (pdev->wndVsize<<8)/(pdev->preTargetVsize<<Vshift);		ciprscctrl = ioread32(S3C244X_CIPRSCCTRL);		ciprscctrl &= (1<<30)|(1<<15);	// keep preview image format (RGB565 or RGB24), and preview scaler start state.		ciprscctrl |= (1<<31)	// this bit should be always 1.					  |(Hscale<<29)		// ???, horizontal scale up/down.					  |(Vscale<<28)		// ???, vertical scale up/down.					  |(mainHratio<<16)	// horizontal scale ratio for preview main-scaler					  |(mainVratio<<0);	// vertical scale ratio for preview main-scaler		iowrite32(ciprscctrl, S3C244X_CIPRSCCTRL);		break;	case V4L2_PIX_FMT_YUV420:	case V4L2_PIX_FMT_YUYV:		/* CICOSCPRERATIO. */		calc_prescaler_ratio_shift(pdev->wndHsize, pdev->coTargetHsize,									&preHratio, &Hshift);		calc_prescaler_ratio_shift(pdev->wndVsize, pdev->coTargetVsize,									&preVratio, &Vshift);		shfactor = 10 - (Hshift + Vshift);		cicoscpreratio = (shfactor<<28)		// shift factor for codec pre-scaler						 |(preHratio<<16)	// horizontal ratio of codec pre-scaler						 |(preVratio<<0);	// vertical ratio of codec pre-scaler		iowrite32(cicoscpreratio, S3C244X_CICOSCPRERATIO);		/* CICOSCPREDST. */		preDstWidth = pdev->wndHsize / preHratio;		preDstHeight = pdev->wndVsize / preVratio;		cicoscpredst = (preDstWidth<<16)	// destination width for codec pre-scaler					   |(preDstHeight<<0);	// destination height for codec pre-scaler		iowrite32(cicoscpredst, S3C244X_CICOSCPREDST);		/* CICOSCCTRL. */		Hscale = (pdev->wndHsize >= pdev->coTargetHsize)?0:1;		Vscale = (pdev->wndVsize >= pdev->coTargetVsize)?0:1;		mainHratio = (pdev->wndHsize<<8)/(pdev->coTargetHsize<<Hshift);		mainVratio = (pdev->wndVsize<<8)/(pdev->coTargetVsize<<Vshift);		cicoscctrl = ioread32(S3C244X_CICOSCCTRL) & (1<<15);	// keep codec scaler start state.		cicoscctrl |= (0<<31)	// not in codec scaler bypass mode.					 |(Hscale<<30)		// ???, horizontal scale up/down.					 |(Vscale<<29)		// ???, vertical scale up/down.					 |(mainHratio<<16)	// horizontal scale ratio for codec main-scaler					 |(mainVratio<<0);	// vertical scale ratio for codec main-scaler		iowrite32(cicoscctrl, S3C244X_CICOSCCTRL);		break;	default:		PDEBUG("bug here.\n");		BUG();		break;	}}/* update camif registers, called only when camif ready, or ISR. */static void __inline__ update_camif_regs(struct s3c2440camif_dev * pdev){	if (!in_irq())	{		if (pdev->state != CAMIF_STATE_READY)		{			PDEBUG("bug here.\n");			BUG();		}		while(1)	// wait until VSYNC is 'L'		{			barrier();			if ((ioread32(S3C244X_CICOSTATUS)&(1<<28)) == 0)				break;		}	}	/* WARNING: don't change the statement sort below!!! */	update_source_fmt_regs(pdev);	update_target_wnd_regs(pdev);	update_target_fmt_regs(pdev);	update_target_zoom_regs(pdev);}/* start image capture. * * param 'stream' means capture pictures streamly or capture only one picture. */static int start_capture(struct s3c2440camif_dev * pdev, int stream){	int ret;	u32 ciwdofst;	u32 ciprscctrl;	u32 cicoscctrl;	u32 ciimgcpt;	if (pdev->state != CAMIF_STATE_READY)	{		PDEBUG("bug here, pdev->state = %d.\n", pdev->state);		BUG();	}	ciwdofst = ioread32(S3C244X_CIWDOFST);	ciwdofst |= (1<<30)		// Clear the overflow indication flag of input CODEC FIFO Y				|(1<<15)	// Clear the overflow indication flag of input CODEC FIFO Cb				|(1<<14)	// Clear the overflow indication flag of input CODEC FIFO Cr				|(1<<13)	// Clear the overflow indication flag of input PREVIEW FIFO Cb				|(1<<12);	// Clear the overflow indication flag of input PREVIEW FIFO Cr	iowrite32(ciwdofst, S3C244X_CIWDOFST);	switch (formats[pdev->format].pixelformat)	{	case V4L2_PIX_FMT_RGB565:	case V4L2_PIX_FMT_RGB24:		ciprscctrl = ioread32(S3C244X_CIPRSCCTRL);		ciprscctrl |= 1<<15;	// preview scaler start		iowrite32(ciprscctrl, S3C244X_CIPRSCCTRL);		spin_lock(&pdev->statelock);		pdev->state = CAMIF_STATE_PREVIEWING;		spin_unlock(&pdev->statelock);		PDEBUG("Now in previewing state!\n");		ciimgcpt = (1<<31)		// camera interface global capture enable				   |(1<<29);	// capture enable for preview scaler.		iowrite32(ciimgcpt, S3C244X_CIIMGCPT);		break;	case V4L2_PIX_FMT_YUV420:	case V4L2_PIX_FMT_YUYV:		cicoscctrl = ioread32(S3C244X_CICOSCCTRL);		cicoscctrl |= 1<<15;	// codec scaler start		iowrite32(cicoscctrl, S3C244X_CICOSCCTRL);		spin_lock(&pdev->statelock);		pdev->state = CAMIF_STATE_CODECING;		spin_unlock(&pdev->statelock);		PDEBUG("Now in codecing state!\n");		ciimgcpt = (1<<31)		// camera interface global capture enable				   |(1<<30);	// capture enable for codec scaler.		iowrite32(ciimgcpt, S3C244X_CIIMGCPT);		break;	default:		PDEBUG("bug here.\n");		BUG();	}//	print_regs();	ret = 0;	if (stream == 0)	{		spin_lock(&pdev->cmdlock);		pdev->cmdcode = CAMIF_CMD_STOP;		spin_unlock(&pdev->cmdlock);		PDEBUG("wait here until capturing stops.\n");		ret = wait_event_interruptible(pdev->cmdqueue, pdev->cmdcode == CAMIF_CMD_NONE);	}	return ret;}/* stop image capture, always called in ISR. *	P-path regs: *		CIPRSCCTRL *		CIPRCTRL *	C-path regs: *		CICOSCCTRL. *		CICOCTRL *	Global regs: *		CIIMGCPT */static void stop_capture(struct s3c2440camif_dev * pdev){	u32 ciprscctrl;	u32 ciprctrl;	u32 cicoscctrl;	u32 cicoctrl;	PDEBUG("now in %s()\n", __FUNCTION__);	spin_lock(&pdev->statelock);	switch(pdev->state)	{	case CAMIF_STATE_PREVIEWING:		/* CIPRCTRL. */		ciprctrl = ioread32(S3C244X_CIPRCTRL);		ciprctrl |= 1<<2;		// enable last IRQ at the end of frame capture.		iowrite32(ciprctrl, S3C244X_CIPRCTRL);		/* CIPRSCCTRL. */		ciprscctrl = ioread32(S3C244X_CIPRSCCTRL);		ciprscctrl &= ~(1<<15);		// clear preview scaler start bit.		iowrite32(ciprscctrl, S3C244X_CIPRSCCTRL);		/* CIIMGCPT. */		iowrite32(0, S3C244X_CIIMGCPT);		pdev->state = CAMIF_STATE_READY;		PDEBUG("previewing stopped!\n");		break;	case CAMIF_STATE_CODECING:		/* CICOCTRL. */		cicoctrl = ioread32(S3C244X_CICOCTRL);		cicoctrl |= 1<<2;		// enable last IRQ at the end of frame capture.		iowrite32(cicoctrl, S3C244X_CICOCTRL);		/* CICOSCCTRL. */		cicoscctrl = ioread32(S3C244X_CICOSCCTRL);		cicoscctrl &= ~(1<<15);		// clear codec scaler start bit.		iowrite32(cicoscctrl, S3C244X_CICOSCCTRL);		/* CIIMGCPT. */		iowrite32(0, S3C244X_CIIMGCPT);		pdev->state = CAMIF_STATE_READY;		PDEBUG("codecing stopped!\n");		break;	default:		PDEBUG("bug here.\n");		PDEBUG("now camif is in state %d\n", pdev->state);		BUG();		break;	}	spin_unlock(&pdev->statelock);}/* update camera interface with the new config. */static void update_camif_config (struct s3c2440camif_fh * fh, u32 cmdcode){	struct s3c2440camif_dev	* pdev;	pdev = fh->dev;	spin_lock(&pdev->statelock);	switch (pdev->state)	{	case CAMIF_STATE_READY:		spin_unlock(&pdev->statelock);	// release state spinlock first.		/* camif is ready, set to regs directly ....  */		PDEBUG("%s(), camif ready, set regs directly.\n", __FUNCTION__);		spin_lock(&pdev->cmdlock);		// lock cmd spinlock		update_camif_regs(fh->dev);		// config the regs directly.		spin_unlock(&pdev->cmdlock);	// release cmd spinlock		PDEBUG("command done!\n");		break;	case CAMIF_STATE_PREVIEWING:		spin_unlock(&pdev->statelock);	// release state spinlock first.		/* camif is previewing image. */		PDEBUG("command in previewing...\n");		disable_irq(IRQ_S3C2440_CAM_P);		// disable cam-preview irq.		spin_lock(&pdev->cmdlock);	// lock cmd spinlock		/* source image format. */		if (cmdcode & CAMIF_CMD_SFMT)		{			// ignore it, nothing to do now.		}		/* target image format. */		if (cmdcode & CAMIF_CMD_TFMT)		{			if ((formats[pdev->format].pixelformat == V4L2_PIX_FMT_RGB565)				||(formats[pdev->format].pixelformat == V4L2_PIX_FMT_RGB24))			{				/* change target image format only. */				pdev->cmdcode |= CAMIF_CMD_TFMT;			}			else if ((formats[pdev->format].pixelformat == V4L2_PIX_FMT_YUV420)				||(formats[pdev->format].pixelformat == V4L2_PIX_FMT_YUYV))			{				/* change target image format, and switch from P-path output to C-path output. */				pdev->cmdcode |= CAMIF_CMD_TFMT|CAMIF_CMD_P2C;			}			else			{				spin_unlock(&pdev->cmdlock);	// unlock cmd spinlock				enable_irq(IRQ_S3C2440_CAM_P);				PDEBUG("bug here.\n");				BUG();			}		}		/* target image window offset. */		if (cmdcode & CAMIF_CMD_WND)		{			pdev->cmdcode |= CAMIF_CMD_WND;		}		/* target image zoomi & zoomout. */		if (cmdcode & CAMIF_CMD_ZOOM)		{			pdev->cmdcode |= CAMIF_CMD_ZOOM;		}		/* stop previewing. */		if (cmdcode & CAMIF_CMD_STOP)		{			pdev->cmdcode |= CAMIF_CMD_STOP;		}		spin_unlock(&pdev->cmdlock);	// unlock cmd spinlock		enable_irq(IRQ_S3C2440_CAM_P);	// enable cam-preview irq.		wait_event(pdev->cmdqueue, (pdev->cmdcode==CAMIF_CMD_NONE));	// wait until the ISR completes command.		PDEBUG("command done!");		break;	case CAMIF_STATE_CODECING:		spin_unlock(&pdev->statelock);	// release state spinlock first.		/* camif is previewing image. */		PDEBUG("command in codecing...\n");		disable_irq(IRQ_S3C2440_CAM_C);		// disable cam-codec irq.		spin_lock(&pdev->cmdlock);			// lock cmd spinlock		/* source image format. */		if (cmdcode & CAMIF_CMD_SFMT)		{			// ignore it, nothing to do now.		}		/* target image format. */		if (cmdcode & CAMIF_CMD_TFMT)		{			if ((formats[pdev->format].pixelformat == V4L2_PIX_FMT_RGB565)				||(formats[pdev->format].pixelformat == V4L2_PIX_FMT_RGB24))			{				/* change target image format only. */				pdev->cmdcode |= CAMIF_CMD_TFMT;			}			else if ((formats[pdev->format].pixelformat == V4L2_PIX_FMT_YUV420)				||(formats[pdev->format].pixelformat == V4L2_PIX_FMT_YUYV))			{				/* change target image format, and switch from P-path output to C-path output. */				pdev->cmdcode |= CAMIF_CMD_TFMT|CAMIF_CMD_P2C;			}			else			{				spin_unlock(&pdev->cmdlock);	// unlock cmd spinlock				enable_irq(IRQ_S3C2440_CAM_C);	// enable cam-codec irq.				PDEBUG("bug here.\n");				BUG();			}		}		/* target image window offset. */		if (cmdcode & CAMIF_CMD_WND)		{			pdev->cmdcode |= CAMIF_CMD_WND;		}		/* target image zoomi & zoomout. */		if (cmdcode & CAMIF_CMD_ZOOM)		{			pdev->cmdcode |= CAMIF_CMD_ZOOM;		}		/* stop previewing. */		if (cmdcode & CAMIF_CMD_STOP)		{			pdev->cmdcode |= CAMIF_CMD_STOP;		}		spin_unlock(&pdev->cmdlock);	// unlock cmd spinlock		enable_irq(IRQ_S3C2440_CAM_C);	// enable cam-codec irq.		wait_event(pdev->cmdqueue, (pdev->cmdcode==CAMIF_CMD_NONE));	// wait until the ISR completes command.		PDEBUG("command done!");		break;	default:		spin_unlock(&pdev->statelock);// release state spinlock first.		PDEBUG("bug here.\n");		BUG();		break;	}}/* config camif when master-open camera.*/static void init_camif_config(struct s3c2440camif_fh * fh){	struct s3c2440camif_dev	* pdev;	if (fh->master == 0)	{		PDEBUG("bug here!\n");		BUG();	}	pdev = fh->dev;	pdev->c_format = 2;	// FIXME, C-path default format, see formats[] for detail.	pdev->p_format = 0;	// FIXME, P-path default format, see formats[] for detail.	pdev->input = 0;	// FIXME, the default input image format, see inputs[] for detail.	/* the source image size (input from external camera). */	pdev->srcHsize = 1280;	// FIXME, the OV9650's horizontal output pixels.	pdev->srcVsize = 1024;	// FIXME, the OV9650's verical output pixels.	/* the windowed image size. */	pdev->wndHsize = 1280;	pdev->wndVsize = 1024;	/* codec-path target(output) image size. */	pdev->coTargetHsize = pdev->wndHsize;	pdev->coTargetVsize = pdev->wndVsize;	/* preview-path target(preview) image size. */	pdev->preTargetHsize = 240;	pdev->preTargetVsize = 256;	update_camif_config(fh, (u32)-1);}static void __inline__ invalid_image_buffer(void){	img_buff[0].state = CAMIF_BUFF_INVALID;	img_buff[1].state = CAMIF_BUFF_INVALID;	img_buff[2].state = CAMIF_BUFF_INVALID;	img_buff[3].state = CAMIF_BUFF_INVALID;}/* init image buffer (only when the camif is first open). */static int __inline__ init_image_buffer(void){	int size1, size2;	unsigned long size;	unsigned int order;	if ((img_buff[0].virt_base != (unsigned long)NULL)		||(img_buff[1].virt_base != (unsigned long)NULL)		||(img_buff[2].virt_base != (unsigned long)NULL)		||(img_buff[3].virt_base != (unsigned long)NULL))	{		PDEBUG("bug here.");		BUG();	}	/* size1 is the max image size of codec path. */	size1 = MAX_C_WIDTH * MAX_C_HEIGHT * formats[3].depth / 8;	/* size2 is the max image size of preview path. */	size2 = MAX_P_WIDTH * MAX_P_HEIGHT * formats[1].depth / 8;	size = (size1 > size2)?size1:size2;	PDEBUG("each image buffer is %dKBytes.\n", (int)(size/1024));	order = get_order(size);	img_buff[0].order = order;	img_buff[0].virt_base = __get_free_pages(GFP_KERNEL|GFP_DMA, img_buff[0].order);	if (img_buff[0].virt_base == (unsigned long)NULL)	{		PDEBUG("__get_free_pages() for img_buff[0] fail!\n");		goto error0;	}	img_buff[0].phy_base = img_buff[0].virt_base - PAGE_OFFSET + PHYS_OFFSET;	// the DMA address.	img_buff[1].order = order;	img_buff[1].virt_base = __get_free_pages(GFP_KERNEL|GFP_DMA, img_buff[1].order);	if (img_buff[1].virt_base == (unsigned long)NULL)	{		PDEBUG("__get_free_pages() for img_buff[1] fail!\n");		goto error1;	}	img_buff[1].phy_base = img_buff[1].virt_base - PAGE_OFFSET + PHYS_OFFSET;	// the DMA address.	img_buff[2].order = order;	img_buff[2].virt_base = __get_free_pages(GFP_KERNEL|GFP_DMA, img_buff[2].order);	if (img_buff[2].virt_base == (unsigned long)NULL)	{		PDEBUG("__get_free_pages() for img_buff[2] fail!\n");		goto error2;	}	img_buff[2].phy_base = img_buff[2].virt_base - PAGE_OFFSET + PHYS_OFFSET;	// the DMA address.	img_buff[3].order = order;	img_buff[3].virt_base = __get_free_pages(GFP_KERNEL|GFP_DMA, img_buff[3].order);	if (img_buff[3].virt_base == (unsigned long)NULL)	{		PDEBUG("__get_free_pages() for img_buff[3] fail!\n");		goto error3;	}	img_buff[3].phy_base = img_buff[3].virt_base - PAGE_OFFSET + PHYS_OFFSET;	// the DMA address.	PDEBUG("get pages for img_buff[0..3] done.\n");	invalid_image_buffer();

⌨️ 快捷键说明

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