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

📄 v4l2.c

📁 pxa270下的摄像头mtd91111的驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
	if (dev->camera && dev->input == 0) {		// Start the camera h/w. It will call us back		// on image completion.		if (dev->camif->snapshot (dev->capture_buffer,					  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->capture_buffer,						 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->camera->convert_image ((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->camera->convert_image ((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;	}	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 * */#ifdef CONFIG_CEE /* MVL-CEE */#include <linux/device.h>static int omap_camera_dpm_suspend(struct device *dev, u32 state, u32 level);static int omap_camera_dpm_resume(struct device *dev, u32 level);static struct device_driver omap_camera_driver_ldm = {	name:"omap-camera",	devclass:NULL,	probe:NULL,	suspend:omap_camera_dpm_suspend,	resume:omap_camera_dpm_resume,	remove:NULL,};static struct device omap_camera_device_ldm = {	name:"OMAP Camera",	bus_id:"Camera",	driver:NULL,	power_state:DPM_POWER_ON,};static voidomap_camera_ldm_register(struct capture_device *dev){	extern void mpu_public_driver_register(struct device_driver *driver);	extern void mpu_public_device_register(struct device *device);	omap_camera_device_ldm.platform_data = (void *) dev;	mpu_public_driver_register(&omap_camera_driver_ldm);	mpu_public_device_register(&omap_camera_device_ldm);}static voidomap_camera_ldm_unregister(struct capture_device *dev){	extern void mpu_public_driver_unregister(struct device_driver *driver);	extern void mpu_public_device_unregister(struct device *device);	mpu_public_driver_unregister(&omap_camera_driver_ldm);	mpu_public_device_unregister(&omap_camera_device_ldm);}static intomap_camera_dpm_suspend(struct device *dev, u32 state, u32 level){	struct capture_device *cdev =		(struct capture_device *)dev->platform_data;		switch (level) {	case SUSPEND_NOTIFY:		cdev->suspended = 1;		break;	case SUSPEND_POWER_DOWN:		cdev->suspended = 1;		if (cdev->open_count || cdev->preview) {			capture_abort(cdev);			cdev->camif->close();		}		break;	}	return 0;}static intresume_thread(void *data){	struct capture_device *dev = (struct capture_device *)data;	daemonize();	reparent_to_init();	strcpy(current->comm, "camera_resume");	complete(&dev->resume_thread_sync);		for (;;) {		wait_event(dev->resume_wq, dev->resume_request);		if (dev->resume_thread_exit)			break;		if (dev->open_count || dev->preview) {			dev->camif->open();			if (dev->streaming)				capture_stream_start (dev);			else if (dev->preview)				capture_grab_frame (dev);		}		dev->resume_request = dev->suspended = 0;		wake_up(&dev->suspend_wq);	}		complete_and_exit(&dev->resume_thread_sync, 0);	return 0;}static intomap_camera_dpm_resume(struct device *dev, u32 level){	struct capture_device *cdev =		(struct capture_device *)dev->platform_data;	switch (level) {	case RESUME_POWER_ON:		/*		 * Resume is getting called in an interrupt context on		 * OMAP, 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).		 */		cdev->resume_request = 1;		wake_up(&cdev->resume_wq);		break;	}	return 0;

⌨️ 快捷键说明

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