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

📄 pxa_ov_camera.c

📁 ov2640驱动开发
💻 C
📖 第 1 页 / 共 4 页
字号:
		wake_up_interruptible (&ovcamera_wait_q);
		task_waiting = 0;
	}

	return;
}
void pxa_ci_dma_irq_u(int channel, void *data, struct pt_regs *regs)
{
	return;
}
void pxa_ci_dma_irq_v(int channel, void *data, struct pt_regs *regs)
{
	return;
}

void pxa_ovcamera_irq(int irq, void* dev_id, struct pt_regs *regs)
{
	int cisr;
	static int dma_started=0;
	ovcamera_context_t  *ovcam_ctx = g_ovcamera_context;
	
	disable_irq(IRQ_CAMERA);
	
	cisr = CISR;
	if (cisr & CI_CISR_SOF) //start of frame
	{
        	if(still_image_mode)
        	{
			if( ovcam_ctx->ui_capture_status & CAMERA_STATUS_STILLIMAGE_CAPTURE_IN_PROCESS )
			{
				if( ovcam_ctx->cf.in == CAMERA_IMAGE_FORMAT_JPEG )
        			{
        				if( dma_started)
        				{
						ovcamprint("pxa_ovcamera_irq( ) JPEG END\n");
						dma_transfer_stop(ovcam_ctx);		
						if (task_waiting == 1) 
						{
							ovcamprint("pxa_ovcamera_irq( +1 ) \n");		
							wake_up_interruptible (&ovcamera_wait_q);
							task_waiting = 0;
						}
						else 
						{
							ovcamprint("pxa_ci_dma_irq_y( +2 ) \n");		
							still_image_ready = 1;
						}
						ovcam_ctx->ui_capture_status &=~ CAMERA_STATUS_STILLIMAGE_CAPTURE_IN_PROCESS;
						still_image_mode=0;
						dma_started = 0;
					}
					else if(dma_started ==0)
					{
 						dma_started = 1;
						ovcamprint("pxa_ovcamera_irq( ) JPEG STAT\n");
					}
				}
			}
		}

        	CISR |= CI_CISR_SOF;
    	}
    
	if (cisr & CI_CISR_EOF) //end of frame
	{
        	CISR |= CI_CISR_EOF;  
		dma_started=0;     		
	}
	ci_clear_int_status(0xffffffff);
	enable_irq(IRQ_CAMERA);
}
/*########################################################################################
/
/ API:  Open
/
/########################################################################################*/
static int pxa_ovcamera_open(struct inode *inode, struct file *file)
{
	int ret;
	ovcamera_context_t *ovcam_ctx;
	
	ovcamprint("pxa_ovcamera_open( + ) \n");
	
	init_waitqueue_head(&ovcamera_wait_q);
	
	ovcam_ctx=g_ovcamera_context;
	if(atomic_read(&ovcam_ctx->count))
	{
		ovcamprint("pxa_ovcamera_open( -1 ) \n");
		return -EBUSY;
	}
	
	atomic_inc(&ovcam_ctx->count);
	
	ovcam_ctx->vw.width = WIDTH_DEFAULT;
	ovcam_ctx->vw.height = HEIGHT_DEFAULT;
	ovcam_ctx->cf.in = CAMERA_IMAGE_FORMAT_YCBCR422_PLANAR;
	ovcam_ctx->cf.out = CAMERA_IMAGE_FORMAT_YCBCR422_PLANAR;
	ovcam_ctx->frame_rate = FRAMERATE_DEFAULT;
	
	ovcam_ctx->camera_functions = &camerachip_func;
	
	ovcam_ctx->ui_ost_reg_base	=0;
	ovcam_ctx->ui_gpio_reg_base=0;
	ovcam_ctx->ui_ci_reg_base=0;
	ovcam_ctx->ui_board_reg_base=0;

	ovcam_ctx->p_dmadest_virtual=dma_alloc_writecombine(NULL,MAX_DESCRIPTORS_NUM * sizeof(pxa_dma_desc),
			(void*)&ovcam_ctx->p_dmadest_physical,GFP_KERNEL);

	if (NULL == ovcam_ctx->p_dmadest_virtual)
	{
		ovcamprint("can't alloc mem\n");
		ovcamprint("pxa_ovcamera_open( -1 ) \n");
		goto open_error_0;
	}
	ovcam_ctx->ui_dmadest_size = MAX_DESC_NUM;
#if 0	
	ovcam_ctx->ui_buffer_size = BUFFER_SIZE_DEFAULT;
	ovcam_ctx->p_buffer_virtual = dma_alloc_writecombine(NULL,ovcam_ctx->ui_buffer_size,
			(void*)&ovcam_ctx->p_buffer_physical,GFP_KERNEL);

	if( NULL == ovcam_ctx->p_buffer_virtual )
	{
		ovcamprint("pxa_ovcamera_open( -2 ) \n");
		goto open_error_0;
	}
#endif
	ret = ovcamera_init(ovcam_ctx);
	PM_INC_DEV_USER(PM_DEV_CS);	
	ovcamprint("pxa_ovcamera_open( - ) \n");
	
	return ret;
open_error_0:

	return -1;	
}

static void pxa_ovcamera_close(struct inode *inode, struct file *file)
{
	ovcamera_context_t *ovcam_ctx = g_ovcamera_context;

	ovcamprint("pxa_ovcamera_close ( )\n");
	atomic_dec(&ovcam_ctx->count);
	ovcamera_deinit(ovcam_ctx);
    if (ovcam_ctx->p_dmadest_virtual)
        dma_free_writecombine (NULL, MAX_DESCRIPTORS_NUM * sizeof (pxa_dma_desc),
			ovcam_ctx->p_dmadest_virtual,
                (int)ovcam_ctx->p_dmadest_physical);
#if 0
    if (ovcam_ctx->p_buffer_virtual)
        dma_free_writecombine (NULL,ovcam_ctx->ui_buffer_size,
			ovcam_ctx->p_buffer_virtual,
                (int)ovcam_ctx->p_buffer_physical);
#endif

    PM_DEC_DEV_USER(PM_DEV_CS);
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//API     -      Read
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static long pxa_ovcamera_read(struct file *file, char __user *buf,
			 size_t count, loff_t *ppos)
{
	ovcamera_context_t *ovcam_ctx = g_ovcamera_context;
	int offset = 0;
	
	if ((still_image_mode == 1) && (still_image_ready == 1)) 
	{
 	       if (copy_to_user(buf, ovcam_ctx->p_buffer_virtual + offset, ovcam_ctx->block_size))
    	         	return -EFAULT;
		still_image_ready = 0;
		still_image_mode = 0;
		ovcamprint("pxa_ovcamera_read( - 0 ) \n");		
		return ovcam_ctx->block_size;
	}

	if (first_video_frame == 1) 
	{
		first_video_frame = 0;
	}
	else if (still_image_mode == 0)
	{
		ovcam_ctx->block_tail = (ovcam_ctx->block_tail + 1) % ovcam_ctx->block_number;
	}
	
	offset = ovcam_ctx->block_tail * ovcam_ctx->block_size;
	
	if (ovcam_ctx->block_header == ovcam_ctx->block_tail)  
	{
		task_waiting = 1;
		interruptible_sleep_on (&ovcamera_wait_q);
 	}
	
	if (copy_to_user(buf, ovcam_ctx->p_buffer_virtual + offset, ovcam_ctx->block_size))
	{
		ovcamprint("pxa_ovcamera_read( - 2) \n");		
		return -EFAULT;
	}

	return ovcam_ctx->block_size;
}

static unsigned int pxa_ovcamera_poll(struct file *file, poll_table *wait)
{

	return POLLIN|POLLRDNORM;
}

static int pxa_ovcamera_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long param)
{
	switch (cmd) {
		case VIDIOCGCAP:  
		{
			return pxa_ovcamera_VIDIOCGCAP(g_ovcamera_context,param);
		}
		case VIDIOCGWIN:
		{
			return pxa_ovcamera_VIDIOCGWIN(g_ovcamera_context,param);
		}
		case VIDIOCSWIN:
		{			
			return pxa_ovcamera_VIDIOCSWIN(g_ovcamera_context,param);
		}
		case VIDIOCSPICT:
		{
			return pxa_ovcamera_VIDIOCSPICT(g_ovcamera_context,param);
		}
		case VIDIOCGPICT:
		{
			return pxa_ovcamera_VIDIOCGPICT(g_ovcamera_context,param);
		}
		case VIDIOCCAPTURE:
		{
			return pxa_ovcamera_VIDIOCCAPTURE(g_ovcamera_context,param);
		}
		case VIDIOCGMBUF:
		{
			return pxa_ovcamera_VIDIOCGMBUF(g_ovcamera_context,param);
		}
		case WCAM_VIDIOCSCAMREG:
		{
			return pxa_ovcamera_WCAM_VIDIOCSCAMREG(g_ovcamera_context,param);
		}
		case WCAM_VIDIOCGCAMREG:
		{
			return pxa_ovcamera_WCAM_VIDIOCGCAMREG(g_ovcamera_context,param);
		}
		case WCAM_VIDIOCSINFOR:
		{
			return pxa_ovcamera_WCAM_VIDIOCSINFOR(g_ovcamera_context,param);
		}
		case WCAM_VIDIOCGINFOR:
		{
			return pxa_ovcamera_WCAM_VIDIOCGINFOR(g_ovcamera_context,param);
		}
		case WCAM_VIDIOCCAMERACHIP:
		{		
			return pxa_ovcamera_WCAM_VIDIOCCAMERACHIP(g_ovcamera_context,param);
		}
		default:
		{
			return 0;
		}
	}	
	
	return 0;
}

static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr)
{
	unsigned long ret = 0UL;
	pmd_t *pmd;
	pte_t *ptep, pte;
	                                                                                             
	if (!pgd_none(*pgd)) 
	{
		pmd = pmd_offset(pgd, adr);
		if (!pmd_none(*pmd)) 
		{
			ptep = pte_offset(pmd, adr);
			pte = *ptep;
			if (pte_present(pte)) 
			{
				ret = (unsigned long) page_address(pte_page(pte));
				ret |= (adr & (PAGE_SIZE-1));
			}
		}
	}
	return ret;
}

static inline unsigned long kvirt_to_pa(unsigned long adr)
{
	unsigned long va, kva, ret;
                                                                                                                         
	va = VMALLOC_VMADDR(adr);
	kva = uvirt_to_kva(pgd_offset_k(va), va);
	ret = __pa(kva);
	return ret;
}

static int pxa_ovcamera_mmap(struct file* file, struct vm_area_struct *vma)
{
	unsigned long start = (unsigned long)vma->vm_start;
	unsigned long end = (unsigned long)vma->vm_end;
	unsigned long size  = end-start;
	unsigned long page, pos;
	ovcamera_context_t *ovcam_ctx = g_ovcamera_context;

	pos = (unsigned long)ovcam_ctx->p_buffer_virtual;
	page = (unsigned long)(ovcam_ctx->p_buffer_physical) >> 12;
	
	if (remap_pfn_range(vma,start, page, size,vma->vm_page_prot ))
	{
	        return -EFAULT;
	}
	return 0;
}

static int pxa_ovcamera_video_init(struct video_device *dev)
{
	int ret=-1;

	ovcamprint("pxa_ovcamera_video_init() ......\n");

	g_ovcamera_context=kmalloc(sizeof(struct ovcamera_context_s),GFP_KERNEL);
	if ( !g_ovcamera_context) 
	{
		ovcamprint("allocate buffer for camera context \n");
	}	
	else
	{
		memset(g_ovcamera_context, 0, sizeof(struct ovcamera_context_s));
		ret = 0;
	}
#if 1
	g_ovcamera_context->ui_buffer_size = BUFFER_SIZE_DEFAULT;
	g_ovcamera_context->p_buffer_virtual = dma_alloc_writecombine(NULL,g_ovcamera_context->ui_buffer_size,
			(void*)&g_ovcamera_context->p_buffer_physical,GFP_KERNEL);
	
	if( NULL == g_ovcamera_context->p_buffer_virtual )                                                                                           {
		ovcamprint("video_init( -2 ) mem not enough \n");
		ret = -ENOMEM;
	}

#endif	
	atomic_set(&g_ovcamera_context->count,0);

	return ret;
}
static void pxa_camera_release(struct video_device *dev)
{
}

static int pxa_camera_suspend()
{
	return 0;
}
static int pxa_camera_resume()
{
	DRCMR68 = ci_dma_y | DRCMR_MAPVLD;
	DRCMR69 = ci_dma_u | DRCMR_MAPVLD;
	DRCMR70 = ci_dma_v | DRCMR_MAPVLD;    
	return 0;
}

int pxa_camera_pm_switch(unsigned int flag)
{
	if(flag==0){
		pxa_camera_suspend();          
	}else{
		pxa_camera_resume();           
	}
	return PM_SW_READY;   
}
static pm_reg_dev_t pm_dev={"CAMERA PM DEV",PM_DEV_CS,0, pxa_camera_pm_switch};


static struct file_operations fops= {
	owner: 	THIS_MODULE,
	open:	pxa_ovcamera_open,
	release:pxa_ovcamera_close,
	read:	pxa_ovcamera_read,
	poll:	pxa_ovcamera_poll,
	ioctl:	pxa_ovcamera_ioctl,
	mmap:	pxa_ovcamera_mmap,
};
static struct video_device ovcam = {
	.owner		=	 THIS_MODULE,
	.name		=	"PXA Camera",
	.type		=	VID_TYPE_CAPTURE,
	.hardware	=	VID_HARDWARE_OVCAMERA,      /* FIXME */
	.fops		=	&fops,
	.release	=	pxa_camera_release,
	//initialize:		pxa_camera_video_init,
	.minor		=	-1,
};

static int __init pxa_ovcamera_init(void)
{
	ovcamprint("pxa_ovcamer_init() ......\n");
	
	if(request_irq(IRQ_CAMERA,pxa_ovcamera_irq,0,"OmniVsion Camera",&ovcam))
	{
		ovcamprint("Register camera irq failed\n");
		goto init_error_0;
	}


	ci_dma_y = -1;
	ci_dma_u = -1;
	ci_dma_v = -1;
	
	ci_dma_y = pxa_request_dma("CI_Y",DMA_PRIO_MEDIUM,pxa_ci_dma_irq_y,&ovcam)	;
	if(ci_dma_y < 0) {
		ovcamprint("Register DMA for Y channel failed\n");
		goto init_error_1;
	}
	
	ci_dma_u = pxa_request_dma("CI_Cb",DMA_PRIO_MEDIUM,pxa_ci_dma_irq_u,&ovcam)	;
	if(ci_dma_u < 0) {
		ovcamprint("Register DMA for U channel failed\n");
		goto init_error_1;
	}

	ci_dma_v = pxa_request_dma("CI_Cr",DMA_PRIO_MEDIUM,pxa_ci_dma_irq_v,&ovcam)	;
	if(ci_dma_v < 0) {
		ovcamprint("Register DMA for V channel failed\n");
		goto init_error_1;
	}

	DRCMR68 = ci_dma_y | DRCMR_MAPVLD;
	DRCMR69 = ci_dma_u | DRCMR_MAPVLD;
	DRCMR70 = ci_dma_v | DRCMR_MAPVLD;

	if(video_register_device(&ovcam,VFL_TYPE_GRABBER,-1)<0) //jhy minor
	{
		ovcamprint("ov camera device register failed\n");
		goto init_error_1;
	} 
	else 
	{
		PM_REGISTER_DEVICE(&pm_dev);
		ovcamprint("ov camera driver initialization is ok \n");
	}
	if(pxa_ovcamera_video_init(&ovcam)<0){
		goto init_error_1;
	}

	return 0;
init_error_1:
	if (0 <= ci_dma_y)
		pxa_free_dma(ci_dma_y);
	if (0 <= ci_dma_u)
		pxa_free_dma(ci_dma_u);
	if (0 <= ci_dma_v)
		pxa_free_dma(ci_dma_v);

	free_irq(IRQ_CAMERA, &ovcam);

init_error_0:
	return -EIO;
}

static void __exit pxa_ovcamera_exit(void)
{
	ovcamera_context_t *ovcam_ctx;
	ovcam_ctx = g_ovcamera_context;
#if 1 
	if (ovcam_ctx->p_buffer_virtual)
		 dma_free_writecombine (NULL,ovcam_ctx->ui_buffer_size,
				 ovcam_ctx->p_buffer_virtual,
				 (int)ovcam_ctx->p_buffer_physical);
#endif
	if(ovcam_ctx->dma_channels[0]) 
	{
		pxa_free_dma(ovcam_ctx->dma_channels[0]);
		ovcam_ctx->dma_channels[0] = 0;
	}
	
	if(ovcam_ctx->dma_channels[1]) 
	{
		pxa_free_dma(ovcam_ctx->dma_channels[1]);
		ovcam_ctx->dma_channels[1] = 0;
	}

	if(ovcam_ctx->dma_channels[2]) 
	{
		pxa_free_dma(ovcam_ctx->dma_channels[2]);
		ovcam_ctx->dma_channels[2] = 0;
	}

	free_irq(IRQ_CAMERA,&ovcam);
	
	kfree(g_ovcamera_context);
	
	video_unregister_device(&ovcam);
	PM_UNREGISTER_DEVICE(&pm_dev);
	ovcamprint("camera driver exit\n");
	return;
}

module_init(pxa_ovcamera_init);
module_exit(pxa_ovcamera_exit);

MODULE_DESCRIPTION("Bulverde Camera Interface driver");
MODULE_LICENSE("GPL");
EXPORT_NO_SYMBOLS;

⌨️ 快捷键说明

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