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

📄 v4l2.c

📁 pxa270下的摄像头mtd91111的驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
                if (dev->camif->snapshot (dev->id,                    dev->capture_buffer_phys, dev->capture_size) == 0) {			dev->capture_started = 1;			dev->capture_completed = 0;		}	} else {		dev->capture_started = 1;		dev->capture_completed = 0;	}}/*  Start an image stream */static voidcapture_stream_start (struct capture_device *dev){	capture_begin (dev);	if (!dev->ready_to_capture)		return;	/*  Set up stream_capture_buffer to point to the buffer to  */	/*  capture the next frame into  */	dev->stream_capture_buffer = dev->capture_buffer;	if (dev->camera && dev->input == 0) {		/* Start the camera h/w. It will call us back		   on image completion.*/		if (dev->camif->start_streaming (dev->id,                                        dev->capture_buffer_phys,						 dev->capture_size) == 0) {			dev->capture_started = 1;			dev->capture_completed = 0;		}	} else {		dev->capture_started = 1;		dev->capture_completed = 0;	}}/* *      STREAMING CAPTURE *//* 1 = success; 0 = failed */static intcapture_queuebuffer (struct capture_device *dev, struct v4l2_buffer *vidbuf){	int i = vidbuf->index;	struct stream_buffer *buf = NULL;	if (!dev->stream_buffers_mapped) {		dbg("QBUF no buffers mapped\n");		return 0;	}	if (vidbuf->type != V4L2_BUF_TYPE_CAPTURE) {		dbg("QBUF wrong type\n");		return 0;	}	if (i < 0 || i >= MAX_CAPTURE_BUFFERS	    || !dev->stream_buf[i].requested) {		dbg("QBUF buffer index %d is out of range\n", i);		return 0;	}	buf = &dev->stream_buf[i];	if (!(buf->vidbuf.flags & V4L2_BUF_FLAG_MAPPED)) {		dbg("QBUF buffer %d is not mapped\n", i);		return 0;	}	if ((buf->vidbuf.flags & V4L2_BUF_FLAG_QUEUED)) {		dbg("QBUF buffer %d is already queued\n", i);		return 0;	}	buf->vidbuf.flags &= ~V4L2_BUF_FLAG_DONE;	v4l2_q_add_tail (&dev->stream_q_capture, &buf->qnode);	buf->vidbuf.flags |= V4L2_BUF_FLAG_QUEUED;	return 1;}static int			/* 1 = got a buffer; 0 = no buffers */capture_dequeuebuffer (struct capture_device *dev, struct v4l2_buffer *buf){	struct stream_buffer *newbuf;	if (buf->type != V4L2_BUF_TYPE_CAPTURE) {		dbg("DQBUF wrong buffer type\n");		return 0;	}	newbuf = v4l2_q_del_head (&dev->stream_q_done);	if (newbuf == NULL) {		dbg("DQBUF nothing on done queue\n");		return 0;	}	newbuf->vidbuf.flags &= ~V4L2_BUF_FLAG_QUEUED;	*buf = newbuf->vidbuf;	return 1;}static intcapture_streamon (struct capture_device *dev, __u32 type){	struct stream_buffer *buf;	ENTRY ();	if (type != V4L2_BUF_TYPE_CAPTURE) {		dbg("STREAMON wrong buffer type\n");		EXIT();		return 0;	}	if (dev->streaming) {		EXIT();		return 1;	}	capture_abort (dev); /* cancel any capture that might be in progress */	/*  -2 is a magic number that triggers start-of-stream logic in */	/*    capture_interrupt()  */	dev->stream_last_frame = -2;	dev->perf.frames = 0;	dev->perf.framesdropped = 0;	dev->perf.bytesout = 0;        	/*  Can't capture frames faster than the video input  */	if (dev->capture.timeperframe < dev->videc.frame_period)		dev->capture.timeperframe = dev->videc.frame_period;	/*  Move any leftover DONE buffers to the free pool */	while ((buf = v4l2_q_del_head (&dev->stream_q_done)))		buf->vidbuf.flags &= ~V4L2_BUF_FLAG_QUEUED;	/*  Kick off the machine in continuous capture mode */	dev->streaming = 1;	capture_stream_start (dev);	EXIT();	return 1;}static voidcapture_streamoff (struct capture_device *dev, __u32 type){	ENTRY();	if (!dev->streaming) {		EXIT();		return;	}	if (type != V4L2_BUF_TYPE_CAPTURE) {		err("STREAMOFF wrong buffer type\n");		EXIT();		return;	}	capture_abort (dev);	dev->streaming = 0;	/* Note: should really delay this till next capture */	dev->perf.frames = 0;	dev->perf.framesdropped = 0;	dev->perf.bytesout = 0;	EXIT();}/* * Convert raw camera image directly into framebuffer (used by * preview mode). Returns length of data or negative for error. */static intcapture_display_image (struct capture_device *dev, __u8 * capture_buffer){	if (!dev->capture_started) {		/* If we get here is probably because the PREVIEW		   mode was turned off just prior to the interrupt		   routines completing the last image. We don't		   want anymore images. Just return.*/		dbg ("capture not started??\n");		return 0;	}	if (dev->camera) {		int dest_stride;		if (!dev->fbinfo_valid) {			err ("preview set but no valid fb info\n");			return -EINVAL;		}		dest_stride = (dev->fbvar.xres_virtual *			       dev->fbvar.bits_per_pixel) / 8;		dev->camif->convert_image (dev->id,                                        (u8 *) capture_buffer,					(u8 *) phys_to_virt (dev->fbfix.								 smem_start),					    0, dest_stride, &dev->clientfmt);	}	++dev->perf.frames;	dev->perf.bytesout += dev->clientfmt.sizeimage;	return dev->clientfmt.sizeimage;}/* * Convert the next frame. * Returns length of data or negative for error. */static intcapture_convert_image (struct capture_device *dev,		       __u8 * capture_buffer,		       __u8 * output_buffer, int output_is_user){	if (!dev->capture_started) {		/* If we get here is probably because the PREVIEW		   mode was turned off just prior to the interrupt		   routines completing the last image. We don't		   want anymore images. Just return.*/		dbg ("capture not started??\n");		return 0;	}	if (dev->camera) {		int dest_stride;		dest_stride = (dev->clientfmt.width *			       dev->clientfmt.depth) / 8;		dev->camif->convert_image (dev->id,                                            (u8 *) capture_buffer,					    (void *) output_buffer,					    output_is_user,					    dest_stride, &dev->clientfmt);	}	++dev->perf.frames;	dev->perf.bytesout += dev->clientfmt.sizeimage;	return dev->clientfmt.sizeimage;}/*  The hardware has issued the interrupt signal, do any post-capture *  processing that may be necessary. *  [This function is called indirectly through the immediate task queue; *  it executes at elevated IRQL, but it is interruptible. (It's a b.h.)] */static voidcapture_interrupt (void *v){	struct capture_device *dev = (struct capture_device *) v;	struct stream_buffer *buf;	int len;	stamp_t timestamp_rough;	unsigned long raw_frame_num;	unsigned long next_raw_frame_to_keep;	unsigned long stream_frame_num;	stamp_t temp64;	if (!dev->capture_started || dev->capture_completed)		return;	if (!dev->streaming)		dev->capture_completed = 1;	if (dev->capture_buffer == NULL) {		err ("Can't process the interrupt\n");		return;	}	if (!dev->streaming) {		dev->time_acquired = current_time_ms ();		if (dev->preview) {			capture_display_image (dev, dev->capture_buffer);			dev->capture_started = 0;			capture_grab_frame (dev); /* Start another capture.*/		}		wake_up_interruptible (&dev->new_video_frame);		return;	}	/*  Only get here in streaming mode  */	if (dev->stream_last_frame == -2) {		/* First frame of the stream  */		v4l2_masterclock_gettime (&dev->stream_begin);		dev->stream_last_frame = -1;	}	if (dev->stream_capture_buffer == NULL) {		dbg ("stream_capture_buffer is NULL!\n");		return;	}	buf = v4l2_q_peek_head (&dev->stream_q_capture);	if (buf == NULL) {		/*		 * No available buffers. Skip this frame. This is not an		 * error, it's a normal way to throttle the capture rate		 */		return;	}	/*  Compute current stream time  */	v4l2_masterclock_gettime (&timestamp_rough);	/*  We do computations on a relative timestamp (since beginning  */	/*  of stream), then add 'dev->stream_begin' back in later       */	timestamp_rough -= dev->stream_begin;	/*  Capture rate control  */	if (dev->videc.frame_period == 0) {		/* Sanity check to avoid divide-by-zero  */		err ("videc.frame_period == 0 -- divide by 0\n");		dev->videc.frame_period = 333667;	        dev->capture.timeperframe= 333667; 	}	raw_frame_num =		v4l2_timestamp_divide (timestamp_rough,				       dev->videc.frame_period);	temp64 = (stamp_t) dev->capture.timeperframe *		(dev->stream_last_frame + 1)		+ (dev->videc.frame_period >> 1);	next_raw_frame_to_keep =		v4l2_math_div6432 ((u64) temp64, dev->videc.frame_period,				   NULL);	if (raw_frame_num < next_raw_frame_to_keep) {		/* Not time yet, don't keep this frame */		return;	}        /*  Want this frame  */	len = capture_convert_image (dev, dev->stream_capture_buffer,				     buf->vaddress, 0);	if (len <= 0) {		/* Frame no good, skip it. */		dbg ("frame no good\n");		return;	}	/*  Fill in the buffer information fields  */	buf->vidbuf.bytesused = len;	buf->vidbuf.flags |= V4L2_BUF_FLAG_DONE | V4L2_BUF_FLAG_KEYFRAME;	stream_frame_num = v4l2_timestamp_correct (&timestamp_rough,						   dev->capture.timeperframe);		/* Returned timestamp should be absolute system time  */	buf->vidbuf.timestamp = timestamp_rough + dev->stream_begin;	buf->vidbuf.sequence = stream_frame_num;	if (stream_frame_num > dev->stream_last_frame + 1) {		/* We have missed one or more frames  */		dev->perf.framesdropped +=			(stream_frame_num - (dev->stream_last_frame + 1));	}	dev->stream_last_frame = stream_frame_num;	/*  Move buffer to done queue  */	buf = v4l2_q_del_head (&dev->stream_q_capture);	v4l2_q_add_tail (&dev->stream_q_done, &buf->qnode);	/*  A new frame is ready!  */	wake_up_interruptible (&dev->new_video_frame);}/* * This is the callback from the Camera Interface, when * a new image has been captured by the camif h/w. This * is called at interrupt time, so just mark a bh and do * nothing more. */static voidcamif_capture_callback (void *data){	struct capture_device *dev = (struct capture_device *) data;	dev->tqnode_dpc.routine = capture_interrupt;	dev->tqnode_dpc.data = dev;	queue_task (&dev->tqnode_dpc, &tq_immediate);	mark_bh (IMMEDIATE_BH);}/*  Read captured data into a user buffer. *  Return: negative = error *          0        = keep waiting *          positive = count of bytes read successfully */static longcapture_read (struct capture_device *dev,	      __u8 * user_buffer, int user_buffer_size){	int len = user_buffer_size;	unsigned long now;	if (!dev->capture_completed) {		/* No interrupt has occurred yet, or DMA didn't finish.  */		dbg("No data ready.\n");		if (!dev->capture_started) {			capture_grab_frame (dev);		}		return 0;	/* caller should keep waiting */	}	now = current_time_ms ();	if (now - dev->time_acquired > MAX_FRAME_AGE) {		/* Frame in buffer is stale, get a new one */		dbg("Stale frame, re-acquiring.\n");		dev->capture_started = 0;		capture_grab_frame (dev);		return 0;	/* caller should keep waiting */	}	len = capture_convert_image (dev, dev->capture_buffer,				     user_buffer, 1);	dev->capture_started = 0;	capture_grab_frame (dev);	return len;}/*  Stop capturing and free all resources used for capture. */static voidcapture_close (struct capture_device *dev){	ENTRY();	if (dev->streaming)		capture_streamoff (dev, V4L2_BUF_TYPE_CAPTURE);	capture_abort (dev);	dev->ready_to_capture = 0;	if (dev->capture_dma_list)		free_page ((unsigned long) dev->capture_dma_list);	dev->capture_dma_list = 0;	DeallocateBuffer (dev);	dev->capture_buffer = NULL;	dev->capture_buffer_size = 0;	EXIT();}/* * *      P O W E R   M A N A G E M E N T * */#if 1   /* power management */static voidmx2ads_camera_suspend(void){	int i;	capture_pwm.suspended = 1;	for (i = 0; i < CAMIF_CHANNELS_NUM; i++) {		if (capture[i].open_count || capture[i].preview) {			capture_close (&capture[i]);			capture[i].camif->close (i);		}	}}static voidmx2ads_camera_resume(void){	/*	* Resume is getting called in an interrupt context and	* resume requires waiting on queues etc. to power	* up the camera. So we can't resume here. So we have to	* use a kernel thread for resume requests (PITA).	*/	up(&capture_pwm.resume_wait);}#ifdef CONFIG_PMstatic struct pm_dev *mx2ads_image_pmdev;static intmx2ads_image_pm_callback(struct pm_dev *pmdev, pm_request_t rqst, void *data){	switch (rqst) {	case PM_SUSPEND:		mx2ads_camera_suspend();		break;	case PM_RESUME:		mx2ads_camera_resume();		break;	}	return 0;}#endif /* CONFIG_PM*/#include <linux/device.h>#include <linux/dpm.h>#ifdef CONFIG_DPMstatic struct constraints mx2cam_constraints = {	.count = 1,	.param = {{DPM_MD_HCLK, 0, 0}},	/*to be initialized at module init time */	.asserted = 1,};#endifextern void mx21_ldm_bus_register(struct device *device,                          struct device_driver *driver);extern void mx21_ldm_bus_unregister(struct device *device,                          struct device_driver *driver);static intmx2ads_camera_dpm_suspend(struct device *dev, u32 state, u32 level){	switch (level) {	case SUSPEND_POWER_DOWN:		mx2ads_camera_suspend();		break;	}	return 0;}static intmx2ads_camera_dpm_resume(struct device *dev, u32 level){	switch (level) {	case RESUME_POWER_ON:		mx2ads_camera_resume();		break;	}	return 0;}static struct device_driver mx2ads_camera_driver_ldm = {	.name       = "mx2ads-cam",	.suspend    = mx2ads_camera_dpm_suspend,	.resume     = mx2ads_camera_dpm_resume,};static struct device mx2ads_camera_device_ldm = {	.name           = "MX2ADS Camera",	.bus_id         = "camera",	.driver         = &mx2ads_camera_driver_ldm,	.power_state    = DPM_POWER_ON,#ifdef CONFIG_DPM	.constraints = &mx2cam_constraints,#endif};static intresume_thread(void *data){        int i;	daemonize();	reparent_to_init();	strcpy(current->comm, "camera_resume");		for (;;) {		down(&capture_pwm.resume_wait);		if (capture_pwm.resume_thread_exit)			break;		for (i = 0; i < CAMIF_CHANNELS_NUM; i++) {			if (capture[i].open_count || capture[i].preview) {				capture[i].camif->open(i);				capture_abort (&capture[i]);				capture_new_format (&capture[i]);				if (capture[i].streaming)					capture_stream_start (&capture[i]);				else if (capture[i].preview)					capture_grab_frame (&capture[i]);			}		}		capture_pwm.suspended = 0;	}		complete_and_exit(&capture_pwm.resume_thread_sync, 0);	return 0;}#endif   /* power management *//* *

⌨️ 快捷键说明

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