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

📄 pxa_ov_camera.c

📁 ov2640驱动开发
💻 C
📖 第 1 页 / 共 4 页
字号:
	// set capture format
	ret = ovcamera_set_capture_format(p_ovcam_ctx);
	if (ret)
	{
		ovcamprint("ovcamera_init ( -8 ) \n");		
		goto camera_init_err;
	}
	
	// set frame rate
	ci_set_frame_rate(p_ovcam_ctx->frame_rate);
	
	return 0;

camera_init_err:
	ovcamera_deinit(p_ovcam_ctx);
	return -1; 
}

static int ovcamera_deinit ( p_ovcamera_context_t p_ovcam_ctx )
{
	int ret;

	// deinit sensor
	ret = p_ovcam_ctx->camera_functions->deinit(p_ovcam_ctx);  
	
	// capture interface deinit
	ci_deinit();
	
	return ret;
}

///////////////////////////////////////////////////////////////////////////////////////////
//Configure Quick Capture Interface accoding to current setting
///////////////////////////////////////////////////////////////////////////////////////////
static int ovcamera_set_capture_format(p_ovcamera_context_t p_ovcam_ctx)
{
	int ret;
	unsigned int frame_size;
	unsigned int block_number = 0;
	CI_IMAGE_FORMAT ci_input_format, ci_output_format;
	CI_MP_TIMING timing;

	ovcamprint("ovcamera_set_capture_format( + ) \n");
	
	if (p_ovcam_ctx->cf.in >  CAMERA_IMAGE_FORMAT_MAX ||
		p_ovcam_ctx->cf.out > CAMERA_IMAGE_FORMAT_MAX )
	{
		ovcamprint("ovcamera_set_capture_format( -0 ) \n");
		return STATUS_WRONG_PARAMETER;
	}
	ci_input_format = FORMAT_MAPPINGS[p_ovcam_ctx->cf.in];
	ci_output_format = FORMAT_MAPPINGS[p_ovcam_ctx->cf.out];
	if (ci_input_format == CI_INVALID_FORMAT || ci_output_format == CI_INVALID_FORMAT)
	{
		ovcamprint("ovcamera_set_capture_format( -1 ) \n");
		return STATUS_WRONG_PARAMETER;
	}
	ci_set_image_format(ci_input_format, ci_output_format);
	
	if(ci_input_format == CI_JPEG)
	{
		ovcamprint("ovcamera_set_capture_format( +JPEG ) \n");
		timing.BFW = timing.BLW = 0;      
		ci_configure_mp(1023,2047, &timing);		
	}
	else
	{
		timing.BFW = timing.BLW = 0;       
		ci_configure_mp(p_ovcam_ctx->vw.width-1, p_ovcam_ctx->vw.height-1, &timing);
	}

	ret = p_ovcam_ctx->camera_functions->capture_set_format(p_ovcam_ctx);
	if (ret) 
	{ 
		ovcamprint("ovcamera_set_capture_format( -2 ) \n");
		return ret;
	}

	switch(p_ovcam_ctx->cf.out) 
	{
	case CAMERA_IMAGE_FORMAT_RGB565:
		frame_size = p_ovcam_ctx->vw.width * p_ovcam_ctx->vw.height * 2;
		p_ovcam_ctx->fifo0_transfer_size = frame_size;
		p_ovcam_ctx->fifo1_transfer_size = 0;
		p_ovcam_ctx->fifo2_transfer_size = 0;
		break;
        case CAMERA_IMAGE_FORMAT_YCBCR422_PACKED:
                frame_size = p_ovcam_ctx->vw.width * p_ovcam_ctx->vw.height * 2;
	        p_ovcam_ctx->fifo0_transfer_size = frame_size;
        	p_ovcam_ctx->fifo1_transfer_size = 0;
        	p_ovcam_ctx->fifo2_transfer_size = 0;
        	break;
        case CAMERA_IMAGE_FORMAT_YCBCR422_PLANAR:
        	frame_size = p_ovcam_ctx->vw.width * p_ovcam_ctx->vw.height * 2;
        	p_ovcam_ctx->fifo0_transfer_size = frame_size / 2;
        	p_ovcam_ctx->fifo1_transfer_size = frame_size / 4;
        	p_ovcam_ctx->fifo2_transfer_size = frame_size / 4;
        	break;
        case CAMERA_IMAGE_FORMAT_RGB666_PLANAR:
        	frame_size = p_ovcam_ctx->vw.width * p_ovcam_ctx->vw.height * 4;
        	p_ovcam_ctx->fifo0_transfer_size = frame_size;
        	p_ovcam_ctx->fifo1_transfer_size = 0;
        	p_ovcam_ctx->fifo2_transfer_size = 0;
        	break;
        case CAMERA_IMAGE_FORMAT_RGB666_PACKED:
        	frame_size = p_ovcam_ctx->vw.width * p_ovcam_ctx->vw.height * 3;
        	p_ovcam_ctx->fifo0_transfer_size = frame_size;
        	p_ovcam_ctx->fifo1_transfer_size = 0;
        	p_ovcam_ctx->fifo2_transfer_size = 0;
        	break;
        case CAMERA_IMAGE_FORMAT_RGB888_PLANAR:
        	frame_size = p_ovcam_ctx->vw.width * p_ovcam_ctx->vw.height * 4;
        	p_ovcam_ctx->fifo0_transfer_size = frame_size;
        	p_ovcam_ctx->fifo1_transfer_size = 0;
        	p_ovcam_ctx->fifo2_transfer_size = 0;
        	break;
        case CAMERA_IMAGE_FORMAT_JPEG:
        	frame_size = p_ovcam_ctx->vw.width * p_ovcam_ctx->vw.height ; //compression ration > 2:1
        	p_ovcam_ctx->fifo0_transfer_size = frame_size;
        	p_ovcam_ctx->fifo1_transfer_size = 0;
        	p_ovcam_ctx->fifo2_transfer_size = 0;
        	break;
        default:
        	return STATUS_WRONG_PARAMETER;
        	break;
    }
	p_ovcam_ctx->block_size = frame_size;
	block_number = p_ovcam_ctx->ui_buffer_size / frame_size;
	p_ovcam_ctx->block_number = block_number > MAX_BLOCK_NUM ? MAX_BLOCK_NUM : block_number;
	p_ovcam_ctx->block_header = p_ovcam_ctx->block_tail = 0;

	// generate dma descriptor chain
	ret = update_dma_chain(p_ovcam_ctx);
	if (ret)
	{
	 	ovcamprint("ovcamera_set_capture_format( -3 ) \n");
 	      	return -1;
	}
        
	ovcamprint("ovcamera_set_capture_format( - ) \n");
	return 0;
}

static int ovcamera_video_capture_start(p_ovcamera_context_t p_ovcam_ctx, unsigned int block_id)
{
	int ret;
	ovcamprint("ovcamera_video_capture_start( + ) \n");
			
	// init buffer status & capture
	p_ovcam_ctx->block_header = p_ovcam_ctx->block_tail = block_id; 
	p_ovcam_ctx->ui_capture_status = CAMERA_STATUS_VIDEO_CAPTURE_IN_PROCESS;
	ret = capture_start( p_ovcam_ctx, block_id, 0 );

	ovcamprint("ovcamera_video_capture_start( - ) \n");
	return ret;
}

static int ovcamera_video_capture_stop(p_ovcamera_context_t p_ovcam_ctx)
{
	int ret;

	ovcamprint("ovcamera_video_capture_stop( ) \n");		

	ret = p_ovcam_ctx->camera_functions->capture_stop( p_ovcam_ctx);

	dma_transfer_stop( p_ovcam_ctx);

	if ( !( p_ovcam_ctx->ui_capture_status & CAMERA_STATUS_RING_BUFFER_FULL) )
		 p_ovcam_ctx->ui_capture_status &= ~CAMERA_STATUS_VIDEO_CAPTURE_IN_PROCESS;
	return ret;
}

static int ovcamera_stillimage_capture(p_ovcamera_context_t p_ovcam_ctx, unsigned int block_id)
{
	int ret;
	ovcamprint("ovcamera_video_capture_start( + ) \n");
		
	// init buffer status & capture
	p_ovcam_ctx->block_header = p_ovcam_ctx->block_tail = block_id; 
	p_ovcam_ctx->ui_capture_status = CAMERA_STATUS_STILLIMAGE_CAPTURE_IN_PROCESS;
	ret = capture_start( p_ovcam_ctx, block_id, 1 );

	ovcamprint("ovcamera_video_capture_start( - ) \n");
	return ret;
}

static int pxa_ovcamera_VIDIOCGCAP(p_ovcamera_context_t p_ovcam_ctx,void* param)
{
	struct video_capability vc;
	strcpy(vc.name,"OmniVsion Camera Driver for OV2640");
			
	vc.maxwidth= 1600;
	vc.maxheight= 1200;
	vc.minwidth =8;
	vc.minheight =8;
			
	if(copy_to_user(param,&vc,sizeof(struct video_capability)))
		return -EFAULT;
		
	return 0;
}

static int pxa_ovcamera_VIDIOCGWIN(p_ovcamera_context_t p_ovcam_ctx,void* param)
{
	struct video_window vw;

	vw.width= p_ovcam_ctx->vw.width; 
	vw.height= p_ovcam_ctx->vw.height;
			
	if(copy_to_user(param,&vw,sizeof(struct video_window)))
		return -EFAULT;

	return 0;
}

static int pxa_ovcamera_VIDIOCSWIN(p_ovcamera_context_t p_ovcam_ctx,void* param)
{
	struct video_window vw;
		
	if(copy_from_user(&vw,param,sizeof(struct video_window))) 
	{
		ovcamprint("parameter error 0 ");
		return -EFAULT;
	}
			
	if(vw.width > 1600 || vw.height > 1200 || vw.width < 8 || vw.height < 8) 
	{
		ovcamprint("parameter error 1");
		return -EFAULT;
	}
	
	p_ovcam_ctx->vw.width = (vw.width + 7) / 8;
	p_ovcam_ctx->vw.width *=8;
	
	p_ovcam_ctx->vw.height = (vw.height + 7) / 8;
	p_ovcam_ctx->vw.height *=8;
		
	return ovcamera_set_capture_format(p_ovcam_ctx);
}

static int pxa_ovcamera_VIDIOCSPICT(p_ovcamera_context_t p_ovcam_ctx,void* param)
{
	struct video_picture vp;
	if(copy_to_user(&vp,param,sizeof(struct video_picture)))
		return -EFAULT;
	
	return 0;
}

static int pxa_ovcamera_VIDIOCGPICT(p_ovcamera_context_t p_ovcam_ctx,void* param)
{
	struct video_picture vp;
	if(copy_from_user(&vp,param,sizeof(struct video_picture)))
		 return -EFAULT;
				
	return 0;
}

static int pxa_ovcamera_VIDIOCCAPTURE(p_ovcamera_context_t p_ovcam_ctx,void* param)
{
	int stream_flag=(int)param;
	
	ovcamprint("pxa_ovcamera_VIDIOCCAPTURE ( + ) ");
			
	if( 0 < stream_flag ) // Still image mode
	{ 
		ovcamprint("pxa_ovcamera_VIDIOCCAPTURE ( +1 ) ");
		
		ovcamera_set_int_mask( p_ovcam_ctx,0x3f9 | 0x0400 );
		p_ovcam_ctx->block_header = 0;
		p_ovcam_ctx->block_tail = 0;
		
		still_image_mode = 1;			
		ovcamera_stillimage_capture ( p_ovcam_ctx,0 );
	}
	else if(0 == stream_flag )  //start video mode
	{
		ovcamprint("pxa_ovcamera_VIDIOCCAPTURE ( +2 ) ");

		ovcamera_set_int_mask ( p_ovcam_ctx,0x3f9 | 0x0400 );
		p_ovcam_ctx->block_header = 0;
		p_ovcam_ctx->block_tail = 0;
		
		still_image_mode = 0;
		first_video_frame = 1;
		
		ovcamera_video_capture_start ( p_ovcam_ctx,0 );
	}
	else if( -1 == stream_flag )  //stop video mode
	{
		ovcamprint("pxa_ovcamera_VIDIOCCAPTURE ( +3 ) ");
			
		ovcamera_video_capture_stop ( p_ovcam_ctx );
	}
	else
	{
		ovcamprint("pxa_ovcamera_VIDIOCCAPTURE ( +0 ) ");
	}	

	ovcamprint("pxa_ovcamera_VIDIOCCAPTURE ( - ) ");

	return 0;
}

static int pxa_ovcamera_VIDIOCGMBUF(p_ovcamera_context_t p_ovcam_ctx,void* param)
{
	struct video_mbuf vm;
	int i;
			
	memset(&vm,0,sizeof(vm));
	vm.size = 256;
	vm.frames = 3;
	for(i = 0; i < vm.frames; i++)
		vm.offsets[i] = p_ovcam_ctx->page_aligned_block_size*i;

	if(copy_to_user((void*)param,(void*)&vm,sizeof(struct video_mbuf)))
		return -EFAULT;

	return 0;
}

static int pxa_ovcamera_WCAM_VIDIOCSCAMREG(p_ovcamera_context_t p_ovcam_ctx,void* param)
{
	int ret;
	camerachip_protocol_t cp;

	if(copy_from_user(&cp,param,sizeof(camerachip_protocol_t)))
	{
		ovcamprint("parameter error 0 ");
		return -EFAULT;
	}
	cp.cmd = OVCAMCHIP_CMD_REG_SET;
	ret = p_ovcam_ctx->camera_functions->command(p_ovcam_ctx, cp.cmd, (void*)&cp);
	if(copy_to_user((void*)param,(void*)&cp,sizeof(camerachip_protocol_t)))
	{
		return -EFAULT;
	}
	return ret;
}

static int pxa_ovcamera_WCAM_VIDIOCGCAMREG(p_ovcamera_context_t p_ovcam_ctx,void* param)
{
	int ret;
	camerachip_protocol_t cp;

	if(copy_from_user(&cp,param,sizeof(camerachip_protocol_t)))
	{
		ovcamprint("parameter error 0 ");
		return -EFAULT;
	}
	
	cp.cmd = OVCAMCHIP_CMD_REG_GET;
	ret = p_ovcam_ctx->camera_functions->command(p_ovcam_ctx, cp.cmd, (void*)&cp);

	if(copy_to_user((void*)param,(void*)&cp,sizeof(camerachip_protocol_t)))
	{
		return -EFAULT;
	}
	return ret;
}

static int pxa_ovcamera_WCAM_VIDIOCSINFOR(p_ovcamera_context_t p_ovcam_ctx,void* param)
{
	int ret;
	struct capture_format cf;
	if (copy_from_user(&cf, param, sizeof(struct capture_format))) 
	{
		return -EFAULT;
	}
	p_ovcam_ctx->cf = cf;
		
	ret = ovcamera_set_capture_format ( p_ovcam_ctx );
	return ret;
}

static int pxa_ovcamera_WCAM_VIDIOCGINFOR(p_ovcamera_context_t p_ovcam_ctx,void* param)
{
	struct capture_format cf;
	
        if (copy_from_user(&cf, param, sizeof(int) * 2)) 
	{
		return -EFAULT;
	}
		
	cf.out = ci_get_reg_value (cf.in);
	if (copy_to_user(param, &cf, sizeof(int) * 2)) 
	{
		return -EFAULT;
	}
	
	return 0;
}

static int pxa_ovcamera_WCAM_VIDIOCCAMERACHIP(p_ovcamera_context_t p_ovcam_ctx,void* param)
{
	int ret;
	camerachip_protocol_t cp;
	
        if (copy_from_user(&cp, param, sizeof(camerachip_protocol_t))) 
	{
		return -EFAULT;
	}

	ret = p_ovcam_ctx->camera_functions->command(p_ovcam_ctx,cp.cmd, (void*)&cp);
		
	if(copy_to_user((void*)param,(void*)&cp,sizeof(camerachip_protocol_t)))
	{
		return -EFAULT;
	}
	
	return ret;
}

void pxa_dma_repeat(ovcamera_context_t  *ovcam_ctx)
{
	pxa_dma_desc *cnt_head, *cnt_tail; 
	int cnt_block;

	cnt_block = (ovcam_ctx->block_header + 1) % ovcam_ctx->block_number;
// FIFO0
	(pxa_dma_desc *)cnt_head = (pxa_dma_desc *)ovcam_ctx->fifo0_descriptors_virtual + cnt_block * ovcam_ctx->fifo0_num_descriptors;
	cnt_tail = cnt_head + ovcam_ctx->fifo0_num_descriptors - 1;
	cnt_tail->ddadr = cnt_head->ddadr - sizeof(pxa_dma_desc);
// FIFO1
	if (ovcam_ctx->fifo1_transfer_size) 
	{
		cnt_head = (pxa_dma_desc *)ovcam_ctx->fifo1_descriptors_virtual + cnt_block * ovcam_ctx->fifo1_num_descriptors;
		cnt_tail = cnt_head + ovcam_ctx->fifo1_num_descriptors - 1;
		cnt_tail->ddadr = cnt_head->ddadr - sizeof(pxa_dma_desc);
	}
// FIFO2
	if (ovcam_ctx->fifo2_transfer_size) 
	{
		cnt_head = (pxa_dma_desc *)ovcam_ctx->fifo2_descriptors_virtual + cnt_block * ovcam_ctx->fifo2_num_descriptors;
		cnt_tail = cnt_head + ovcam_ctx->fifo2_num_descriptors - 1;
		cnt_tail->ddadr = cnt_head->ddadr - sizeof(pxa_dma_desc);
	}
	return;
}

void pxa_dma_continue(ovcamera_context_t *ovcam_ctx)
{
	pxa_dma_desc *cnt_head, *cnt_tail; 
	pxa_dma_desc *next_head;
	int cnt_block, next_block;
	
	cnt_block = ovcam_ctx->block_header;
	next_block = (cnt_block + 1) % ovcam_ctx->block_number;
// FIFO0	
	cnt_head = (pxa_dma_desc *)ovcam_ctx->fifo0_descriptors_virtual + cnt_block * ovcam_ctx->fifo0_num_descriptors;
	cnt_tail = cnt_head + ovcam_ctx->fifo0_num_descriptors - 1;
	next_head = (pxa_dma_desc *)ovcam_ctx->fifo0_descriptors_virtual + next_block * ovcam_ctx->fifo0_num_descriptors;
	cnt_tail->ddadr = next_head->ddadr - sizeof(pxa_dma_desc);
// FIFO1
	if (ovcam_ctx->fifo1_transfer_size) 
	{
		cnt_head = (pxa_dma_desc *)ovcam_ctx->fifo1_descriptors_virtual + cnt_block * ovcam_ctx->fifo1_num_descriptors;
		cnt_tail = cnt_head + ovcam_ctx->fifo1_num_descriptors - 1;
		next_head = (pxa_dma_desc *)ovcam_ctx->fifo1_descriptors_virtual + next_block * ovcam_ctx->fifo1_num_descriptors;
		cnt_tail->ddadr = next_head->ddadr - sizeof(pxa_dma_desc);
	}
// FIFO2
	if (ovcam_ctx->fifo2_transfer_size) 
	{
		cnt_head = (pxa_dma_desc *)ovcam_ctx->fifo2_descriptors_virtual + cnt_block * ovcam_ctx->fifo2_num_descriptors;
		cnt_tail = cnt_head + ovcam_ctx->fifo2_num_descriptors - 1;
		next_head = (pxa_dma_desc *)ovcam_ctx->fifo2_descriptors_virtual + next_block * ovcam_ctx->fifo2_num_descriptors;
		cnt_tail->ddadr = next_head->ddadr - sizeof(pxa_dma_desc);
	}
	return;
}

void pxa_ci_dma_irq_y(int channel, void *data, struct pt_regs *regs)
{
	int dcsr;
	static int dma_repeated=0;
	ovcamera_context_t  *ovcam_ctx = g_ovcamera_context;

	dcsr = DCSR(channel);
	DCSR(channel) = dcsr & ~DCSR_STOPIRQEN;
	
	if (still_image_mode == 1) 
	{
		if (task_waiting == 1) 
		{
			wake_up_interruptible (&ovcamera_wait_q);
			task_waiting = 0;
		}
		else 
		{
			still_image_ready = 1;
		}		
	} 
	else 	if (dma_repeated == 0 
		&& (ovcam_ctx->block_tail == ((ovcam_ctx->block_header + 2) % ovcam_ctx->block_number)))  
	{
		dma_repeated = 1;
		pxa_dma_repeat(ovcam_ctx);
		ovcam_ctx->block_header = (ovcam_ctx->block_header + 1) % ovcam_ctx->block_number;
	}
	else if (dma_repeated == 1 && 
		(ovcam_ctx->block_tail != ((ovcam_ctx->block_header + 1) % ovcam_ctx->block_number))
			&& (ovcam_ctx->block_tail != ((ovcam_ctx->block_header + 2) % ovcam_ctx->block_number)))  
	{
		pxa_dma_continue(ovcam_ctx);
		dma_repeated = 0;
	}
	
	else if (dma_repeated == 0) 
	{
		ovcam_ctx->block_header = (ovcam_ctx->block_header + 1) % ovcam_ctx->block_number;
	}

	if (task_waiting == 1 && !(ovcam_ctx->block_header == ovcam_ctx->block_tail)) 
	{

⌨️ 快捷键说明

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