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

📄 mx27_v4l2_capture.c

📁 freescale mx27 的TVP5150的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	case VIDIOC_S_FBUF:{			struct v4l2_framebuffer *fb = arg;			cam->v4l2_fb.flags = fb->flags;			cam->v4l2_fb.fmt.pixelformat = fb->fmt.pixelformat;			break;		}	case VIDIOC_G_PARM:{			struct v4l2_streamparm *parm = arg;			if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {				pr_debug("VIDIOC_G_PARM invalid type\n");				retval = -EINVAL;				break;			}			parm->parm.capture = cam->streamparm.parm.capture;			break;		}	case VIDIOC_S_PARM:{			struct v4l2_streamparm *parm = arg;			retval = mxc_v4l2_s_param(cam, parm);			break;		}		/* linux v4l2 bug, kernel c0485619 user c0405619 */	case VIDIOC_ENUMSTD:{			struct v4l2_standard *e = arg;			*e = cam->standard;			pr_debug("VIDIOC_ENUMSTD call\n");			retval = 0;			break;		}	case VIDIOC_G_STD:{			v4l2_std_id *e = arg;			*e = cam->standard.id;			break;		}	case VIDIOC_S_STD:{			break;		}	case VIDIOC_ENUMOUTPUT:		{			struct v4l2_output *output = arg;			if (output->index >= num_registered_fb) {				retval = -EINVAL;				break;			}			strncpy(output->name,				registered_fb[output->index]->fix.id, 31);			output->type = V4L2_OUTPUT_TYPE_ANALOG;			output->audioset = 0;			output->modulator = 0;			output->std = V4L2_STD_UNKNOWN;			break;		}	case VIDIOC_G_OUTPUT:		{			int *p_output_num = arg;			*p_output_num = cam->output;			break;		}	case VIDIOC_S_OUTPUT:		{			int *p_output_num = arg;			if (*p_output_num >= num_registered_fb) {				retval = -EINVAL;				break;			}			cam->output = *p_output_num;			break;		}	case VIDIOC_G_INPUT:		{			int *p_input_index = arg;			retval = mxc_get_video_input(cam);			if (0 == retval)				*p_input_index = 1;			else				*p_input_index = -ENODEV;			break;		}	case VIDIOC_ENUM_FMT:	case VIDIOC_TRY_FMT:	case VIDIOC_QUERYCTRL:	case VIDIOC_ENUMINPUT:	case VIDIOC_S_INPUT:	case VIDIOC_G_TUNER:	case VIDIOC_S_TUNER:	case VIDIOC_G_FREQUENCY:	case VIDIOC_S_FREQUENCY:	default:		retval = -EINVAL;		break;	}	up(&cam->busy_lock);	return retval;}/* * V4L interface - ioctl function * * @return  None */static intmxc_v4l_ioctl(struct inode *inode, struct file *file,	      unsigned int cmd, unsigned long arg){	return video_usercopy(inode, file, cmd, arg, mxc_v4l_do_ioctl);}/*! * V4L interface - mmap function * * @param file        structure file * * * @param vma         structure vm_area_struct * * * @return status     0 Success, EINTR busy lock error, ENOBUFS remap_page error */static int mxc_mmap(struct file *file, struct vm_area_struct *vma){	struct video_device *dev = video_devdata(file);	unsigned long size;	int res = 0;	cam_data *cam = dev->priv;	pr_debug("pgoff=0x%lx, start=0x%lx, end=0x%lx\n",		 vma->vm_pgoff, vma->vm_start, vma->vm_end);	/* make this _really_ smp-safe */	if (down_interruptible(&cam->busy_lock))		return -EINTR;	size = vma->vm_end - vma->vm_start;	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);	if (remap_pfn_range(vma, vma->vm_start,			    vma->vm_pgoff, size, vma->vm_page_prot)) {		pr_debug("mxc_mmap: remap_pfn_range failed\n");		res = -ENOBUFS;		goto mxc_mmap_exit;	}	vma->vm_flags &= ~VM_IO;	/* using shared anonymous pages */      mxc_mmap_exit:	up(&cam->busy_lock);	return res;}/*! * V4L interface - poll function * * @param file       structure file * * * @param wait       structure poll_table * * * @return  status   POLLIN | POLLRDNORM */static unsigned int mxc_poll(struct file *file, poll_table * wait){	struct video_device *dev = video_devdata(file);	cam_data *cam = dev->priv;	wait_queue_head_t *queue = NULL;	int res = POLLIN | POLLRDNORM;	if (down_interruptible(&cam->busy_lock))		return -EINTR;	queue = &cam->enc_queue;	poll_wait(file, queue, wait);	up(&cam->busy_lock);	return res;}static structfile_operations mxc_v4l_fops = {	.owner = THIS_MODULE,	.open = mxc_v4l_open,	.release = mxc_v4l_close,	.read = mxc_v4l_read,	.ioctl = mxc_v4l_ioctl,	.mmap = mxc_mmap,	.poll = mxc_poll,};static struct video_device mxc_v4l_template = {	.owner = THIS_MODULE,	.name = "Mxc Camera",	.type = 0,	.type2 = VID_TYPE_CAPTURE,	.hardware = 0,	.fops = &mxc_v4l_fops,	.release = video_device_release,};static void camera_platform_release(struct device *device){}/*! Device Definition for Mt9v111 devices */static struct platform_device mxc_v4l2_devices = {	.name = "mxc_v4l2",	.dev = {		.release = camera_platform_release,		},	.id = 0,};extern struct camera_sensor camera_sensor_if;/*!* Camera V4l2 callback function.** @return status*/static void camera_callback(u32 mask, void *dev){	struct mxc_v4l_frame *done_frame;	struct mxc_v4l_frame *ready_frame;	cam_data *cam = (cam_data *) dev;	if (cam == NULL)		return;	if (mask == 1) {		cam->overflow = 1;	}	if (list_empty(&cam->working_q)) {		if (empty_wq_cnt == 0) {			printk(KERN_ERR "camera_callback: working queue empty %d\n",empty_wq_cnt);		}		empty_wq_cnt++;	    if (list_empty(&cam->ready_q)) {			cam->skip_frame++;		} else {			ready_frame =			    list_entry(cam->ready_q.next, struct mxc_v4l_frame,				       queue);			list_del(cam->ready_q.next);			list_add_tail(&ready_frame->queue, &cam->working_q);			cam->enc_update_eba(ready_frame->paddress,					    &cam->ping_pong_csi);		}		return;	}	done_frame =	    list_entry(cam->working_q.next, struct mxc_v4l_frame, queue);	if (done_frame->buffer.flags & V4L2_BUF_FLAG_QUEUED) {		done_frame->buffer.flags |= V4L2_BUF_FLAG_DONE;		done_frame->buffer.flags &= ~V4L2_BUF_FLAG_QUEUED;		if (list_empty(&cam->ready_q)) {			cam->skip_frame++;		} else {			ready_frame =			    list_entry(cam->ready_q.next, struct mxc_v4l_frame,				       queue);			list_del(cam->ready_q.next);			list_add_tail(&ready_frame->queue, &cam->working_q);			cam->enc_update_eba(ready_frame->paddress,					    &cam->ping_pong_csi);		}		/* Added to the done queue */		list_del(cam->working_q.next);		list_add_tail(&done_frame->queue, &cam->done_q);		/* Wake up the queue */		cam->enc_counter++;		wake_up_interruptible(&cam->enc_queue);	} else {		printk(KERN_ERR "camera_callback :buffer not queued\n");	}}/*! * initialize cam_data structure * * @param cam      structure cam_data * * * @return status  0 Success */static void init_camera_struct(cam_data * cam){	int i;	/* Default everything to 0 */	memset(cam, 0, sizeof(cam_data));	init_MUTEX(&cam->param_lock);	init_MUTEX(&cam->busy_lock);	cam->video_dev = video_device_alloc();	if (cam->video_dev == NULL)		return;	*(cam->video_dev) = mxc_v4l_template;	video_set_drvdata(cam->video_dev, cam);	dev_set_drvdata(&mxc_v4l2_devices.dev, (void *)cam);	cam->video_dev->minor = -1;	for (i = 0; i < FRAME_NUM; i++) {		cam->frame[i].width = 0;		cam->frame[i].height = 0;		cam->frame[i].paddress = 0;	}	init_waitqueue_head(&cam->enc_queue);	init_waitqueue_head(&cam->still_queue);	/* setup cropping */	cam->crop_bounds.left = 0;	cam->crop_bounds.width = 704;	cam->crop_bounds.top = 0;	cam->crop_bounds.height = 576;	cam->crop_current = cam->crop_defrect = cam->crop_bounds;	cam->streamparm.parm.capture.capturemode = 0;	cam->standard.index = 0;	cam->standard.id = V4L2_STD_UNKNOWN;	cam->standard.frameperiod.denominator = 30;	cam->standard.frameperiod.numerator = 1;	cam->standard.framelines = 480;	cam->streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;	cam->streamparm.parm.capture.timeperframe = cam->standard.frameperiod;	cam->streamparm.parm.capture.capability = V4L2_CAP_TIMEPERFRAME;	cam->overlay_on = false;	cam->capture_on = false;	cam->skip_frame = 0;	cam->v4l2_fb.capability = V4L2_FBUF_CAP_EXTERNOVERLAY;	cam->v4l2_fb.flags = V4L2_FBUF_FLAG_PRIMARY;	cam->v2f.fmt.pix.sizeimage = 352 * 288 * 3 / 2;	cam->v2f.fmt.pix.bytesperline = 288 * 3 / 2;	cam->v2f.fmt.pix.width = 288;	cam->v2f.fmt.pix.height = 352;	cam->v2f.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420;	cam->win.w.width = 160;	cam->win.w.height = 160;	cam->win.w.left = 0;	cam->win.w.top = 0;	cam->cam_sensor = &camera_sensor_if;	cam->enc_callback = camera_callback;	init_waitqueue_head(&cam->power_queue);	cam->int_lock = SPIN_LOCK_UNLOCKED;	spin_lock_init(&cam->int_lock);}extern void gpio_sensor_active(void);extern void gpio_sensor_inactive(void);/*! * camera_power function *    Turn Sensor power On/Off * * @param       cameraOn      true to turn camera on, otherwise shut down * * @return status */static u8 camera_power(bool cameraOn){	if (cameraOn == true) {		gpio_sensor_active();		csi_enable_mclk(csi_mclk_flag_backup, true, true);	} else {		csi_mclk_flag_backup = csi_read_mclk_flag();		csi_enable_mclk(csi_mclk_flag_backup, false, false);		gpio_sensor_inactive();	}	return 0;}/*! * This function is called to put the sensor in a low power state. Refer to the * document driver-model/driver.txt in the kernel source tree for more * information. * * @param   pdev  the device structure used to give information on which I2C *                to suspend * @param   state the power state the device is entering * * @return  The function returns 0 on success and -1 on failure. */static int mxc_v4l2_suspend(struct platform_device *pdev, pm_message_t state){	cam_data *cam = platform_get_drvdata(pdev);	if (cam == NULL) {		return -1;	}	cam->low_power = true;	if (cam->overlay_on == true)		stop_preview(cam);	if ((cam->capture_on == true) && cam->enc_disable) {		cam->enc_disable(cam);	}	camera_power(false);	return 0;}/*! * This function is called to bring the sensor back from a low power state.Refer * to the document driver-model/driver.txt in the kernel source tree for more * information. * * @param   pdev  the device structure * * @return  The function returns 0 on success and -1 on failure */static int mxc_v4l2_resume(struct platform_device *pdev){	cam_data *cam = platform_get_drvdata(pdev);	if (cam == NULL) {		return -1;	}	cam->low_power = false;	wake_up_interruptible(&cam->power_queue);	if (cam->overlay_on == true)		start_preview(cam);	if (cam->capture_on == true)		mxc_streamon(cam);	camera_power(true);	return 0;}/*! * This structure contains pointers to the power management callback functions. */static struct platform_driver mxc_v4l2_driver = {	.driver = {		   .name = "mxc_v4l2",		   .owner = THIS_MODULE,		   .bus = &platform_bus_type,		   },	.probe = NULL,	.remove = NULL,	.suspend = mxc_v4l2_suspend,	.resume = mxc_v4l2_resume,	.shutdown = NULL,};/*! * Entry point for the V4L2 * * @return  Error code indicating success or failure */static __init int camera_init(void){	u8 err = 0;	cam_data *cam;	if ((g_cam = cam = kmalloc(sizeof(cam_data), GFP_KERNEL)) == NULL) {		pr_debug("failed to mxc_v4l_register_camera\n");		return -1;	}	init_camera_struct(cam);	/* Register the I2C device */	err = platform_device_register(&mxc_v4l2_devices);	if (err != 0) {		pr_debug("camera_init: platform_device_register failed.\n");		video_device_release(cam->video_dev);		kfree(cam);		g_cam = NULL;	}	/* Register the device driver structure. */	err = platform_driver_register(&mxc_v4l2_driver);	if (err != 0) {		platform_device_unregister(&mxc_v4l2_devices);		pr_debug("camera_init: driver_register failed.\n");		video_device_release(cam->video_dev);		kfree(cam);		g_cam = NULL;		return err;	}	/* register v4l device */	if (video_register_device(cam->video_dev, VFL_TYPE_GRABBER, video_nr)	    == -1) {		platform_driver_unregister(&mxc_v4l2_driver);		platform_device_unregister(&mxc_v4l2_devices);		video_device_release(cam->video_dev);		kfree(cam);		g_cam = NULL;		pr_debug("video_register_device failed\n");		return -1;	}	return err;}/*! * Exit and cleanup for the V4L2 * */static void __exit camera_exit(void){	pr_debug("unregistering video\n");	video_unregister_device(g_cam->video_dev);	platform_driver_unregister(&mxc_v4l2_driver);	platform_device_unregister(&mxc_v4l2_devices);	if (g_cam->open_count) {		pr_debug("camera open -- setting ops to NULL\n");	} else {		pr_debug("freeing camera\n");		mxc_free_frame_buf(g_cam);		kfree(g_cam);		g_cam = NULL;	}}module_init(camera_init);module_exit(camera_exit);module_param(video_nr, int, -1);MODULE_AUTHOR("Freescale Semiconductor, Inc.");MODULE_DESCRIPTION("V4L2 capture driver for Mxc based cameras");MODULE_LICENSE("GPL");MODULE_SUPPORTED_DEVICE("video");

⌨️ 快捷键说明

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