原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://blog.youkuaiyun.com/piaozhiye
V4L2简介
Davinci V4L2视频采集驱动其是根据V4L2采集驱动来编写的,想要熟悉其驱动流程,也就比先要了解V4L2德的一些相关知识。我们这里只了解它的采集部分
V4L2(video for linux) 可以支持多种设备,它可以有以下5种接口:
1、视频采集接口(video capture interface):这种应用的设备可以是高频头或者摄像头.V4L2的最初设计就是应用于这种功能的.下面也是着重讲解这种应用;
2、视频输出接口(video output interface):可以驱动计算机的外围视频图像设备——像可以输出电视信号格式的设备;
3、直接传输视频接口(video overlay interface):它的主要工作是把从视频采集设备采集过来的信号直接输出到输出设备之上,而不用经过系统的CPU;
4、视频间隔消隐信号接口(VBI interface):它可以使应用可以访问传输消隐期的视频信号;
5、收音机接口(radio interface):可用来处理从AM或FM高频头设备接收来的音频流;
V4L2驱动的主要功能是使程序有发现设备的能力和操作设备.它主要是用过一系列的回调函数来实现这些功能.像设置高频头的频率,帧频,视频压缩格式和图像像参数等等.
关于它的采集流程可以查看http://blog.youkuaiyun.com/piaozhiye/article/details/7537419这里我就不罗嗦了。
模块注册与注销
3290 module_init(vpif_init);
3291 module_exit(vpif_cleanup);
另外向其他模块提供了两个导出函数,提供给视频设备注册和注销。
3286 EXPORT_SYMBOL(vpif_register_decoder);
3287 EXPORT_SYMBOL(vpif_unregister_decoder);
vpif_init VPIF采集接口的初始化工作
主要是分配缓冲,检查设备类型,分配内存给channel objects,建立VBI处理的工作队列,注册vpif_driver,注册_vpif_device,申请request_irq,引脚复用的设置。在注册的时候会使用vpif_driver 的probe来进行注册,注册一些相关的ioctrol等。
具体如下:
2979 /* vpif_init : This function registers device and driver to
2980 * the kernel, requests irq handler and allocates memory
2981 * for channel objects
2982 */
2983 static __init int vpif_init(void)
2984 {
2985 int free_irq_no_index;
2986 int err = 0, i, j;
2987 int free_channel_objects_index;
2988 int free_buffer_channel_index;
2989 int free_buffer_index;
2990 u8 *addr;
2991 u32 size;
2992
2993 /* Default number of buffers should be 3 */
2994 if ((channel0_numbuffers > 0) &&
2995 (channel0_numbuffers < config_params.min_numbuffers))
2996 channel0_numbuffers = config_params.min_numbuffers;
2997 if ((channel1_numbuffers > 0) &&
2998 (channel1_numbuffers < config_params.min_numbuffers))
2999 channel1_numbuffers = config_params.min_numbuffers;
3000
3001 /* Set buffer size to min buffers size if invalid buffer size is
3002 * given */
3003 if (channel0_bufsize < config_params.min_bufsize[VPIF_CHANNEL0_VIDEO])
3004 channel0_bufsize =
3005 config_params.min_bufsize[VPIF_CHANNEL0_VIDEO];
3006 if (channel1_bufsize < config_params.min_bufsize[VPIF_CHANNEL1_VIDEO])
3007 channel1_bufsize =
3008 config_params.min_bufsize[VPIF_CHANNEL1_VIDEO];
3009
3010 config_params.numbuffers[VPIF_CHANNEL0_VIDEO] = channel0_numbuffers;
3011 config_params.numbuffers[VPIF_CHANNEL1_VIDEO] = channel1_numbuffers;
3012 if (channel0_numbuffers) {
3013 config_params.channel_bufsize[VPIF_CHANNEL0_VIDEO]
3014 = channel0_bufsize;
3015 }
3016 if (channel1_numbuffers) {
3017 config_params.channel_bufsize[VPIF_CHANNEL1_VIDEO]
3018 = channel1_bufsize;
3019 }
3020
3021 /* Check the correct value of device_type */
3022 if ((device_type > config_params.max_device_type) || (device_type < 0)) {
3023 config_params.device_type = 0;
3024 } else {
3025 config_params.device_type = device_type;
3026 }
3027 /* Allocate memory for six channel objects */
3028 for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) {
3029 vpif_obj.dev[i] =
3030 kmalloc(sizeof(struct channel_obj), GFP_KERNEL);
3031 /* If memory allocation fails, return error */
3032 if (!vpif_obj.dev[i]) {
3033 free_channel_objects_index = i;
3034 goto vpif_init_free_channel_objects;
3035 err = -ENOMEM;
3036 }
3037 }
3038 free_channel_objects_index = VPIF_CAPTURE_MAX_DEVICES;
3039
3040 /* Allocate memory for buffers */
3041 for (i = 0; i < VPIF_CAPTURE_NUM_CHANNELS; i++) {
3042 size = config_params.channel_bufsize[i];
3043 for (j = 0; j < config_params.numbuffers[i]; j++) {
3044 addr = (u8 *) vpif_alloc_buffer(size);
3045 if (!addr) {
3046 free_buffer_channel_index = i;
3047 free_buffer_index = j;
3048 err = -ENOMEM;
3049 goto vpif_init_free_buffers;
3050 }
3051 vpif_obj.dev[i]->common[VPIF_VIDEO_INDEX].fbuffers[j] =
3052 addr;
3053 }
3054 }
3055 free_buffer_channel_index = VPIF_CAPTURE_NUM_CHANNELS;
3056 free_buffer_index = config_params.numbuffers[i - 1];
3057
3058 /* Create the workqueue */
3059 vbi_workqueue = create_singlethread_workqueue("vbi");
3060 if (!vbi_workqueue) {
3061 err = -ENOMEM;
3062 goto vpif_init_free_buffers;
3063 }
3064
3065 /* Register driver to the kernel */
3066 err = driver_register(&vpif_driver);
3067 if (0 != err) {
3068 goto vpif_init_free_buffers;
3069 }
3070 /* register device as a platform device to the kernel */
3071 err = platform_device_register(&_vpif_device);
3072 if (0 != err) {
3073 goto vpif_init_unregister_vpif_driver;
3074 }
3075 for (j = 0; j < VPIF_CAPTURE_NUM_CHANNELS; j++) {
3076 err =
3077 request_irq(vpif_get_irq_number(j),
3078 vpif_channel_isr, SA_INTERRUPT,
3079 "DM646x_Capture",
3080 (void *)(&(vpif_obj.dev[j]->channel_id)));
3081 if (0 != err) {
3082 if (j == 0) {
3083 goto vpif_init_unregister_vpif_device;
3084 } else {
3085 free_irq_no_index = j;
3086 goto vpif_init_free_irq;
3087 }
3088 }
3089 }
3090 free_irq_no_index = VPIF_CAPTURE_NUM_CHANNELS;
3091
3092 /*err = request_irq(4, vpif_err_isr, SA_INTERRUPT, "DM646x_Capture_err",*/
3093 /*(void *)NULL);*/
3094 /*if (0 != err)*/
3095 /*{*/
3096 /*printk("request error interrupt is err!\n");*/
3097 /*return err;*/
3098 /*}*/
3099
3100 /*//initialize error interrupt register.*/
3101 /*init_int_err();*/
3102
3103 /* Set the pinmux settings */
3104 set_vpif_pinmux();
3105 set_vpif_capture_pinmux();
3106
3107 return 0;
3108
3109 vpif_init_free_irq:
3110 for (j = 0; j < free_irq_no_index; j++) {
3111 free_irq(vpif_get_irq_number(j),
3112 (void *)(&(vpif_obj.dev[j]->channel_id)));
3113 }
3114 vpif_init_unregister_vpif_device:
3115 platform_device_unregister(&_vpif_device);
3116
3117 vpif_init_unregister_vpif_driver:
3118 driver_unregister(&vpif_driver);
3119
3120 vpif_init_free_buffers:
3121 for (i = 0; i < free_buffer_channel_index; i++) {
3122 for (j = 0; j < config_params.numbuffers[i]; j++) {
3123 addr = vpif_obj.dev[i]->common[VPIF_VIDEO_INDEX].
3124 fbuffers[j];
3125 if (addr) {
3126 vpif_free_buffer((unsigned long)addr,
3127 config_params.
3128 channel_bufsize[i]
3129 );
3130 vpif_obj.dev[i]->common[VPIF_VIDEO_INDEX].
3131 fbuffers[j] = NULL;
3132 }
3133 }
3134 }
3135 for (j = 0; j < free_buffer_index; j++) {
3136 addr =
3137 vpif_obj.dev[free_buffer_channel_index]->
3138 common[VPIF_VIDEO_INDEX].fbuffers[j];
3139 if (addr) {
3140 vpif_free_buffer((unsigned long)addr,
3141 config_params.channel_bufsize[i]);
3142 vpif_obj.dev[free_buffer_channel_index]->
3143 common[VPIF_VIDEO_INDEX].fbuffers[j]
3144 = NULL;
3145 }
3146 }
3147
3148 vpif_init_free_channel_objects:
3149 for (j = 0; j < free_channel_objects_index; j++) {
3150 if (vpif_obj.dev[i]) {
3151 kfree(vpif_obj.dev[j]);
3152 vpif_obj.dev[i] = NULL;
3153 }
3154 }
3155 return err;
3156 }
其中的一些关键结构:
vpif_driver
2950 static struct device_driver vpif_driver = {
2951 .name = "vpif capture",
2952 .bus = &platform_bus_type,
2953 .probe = vpif_probe,
2954 .remove = vpif_remove,
2955 };
2956 static struct platform_device _vpif_device = {
2957 .name = "vpif capture",
2958 .id = 1,
2959 .dev = {
2960 .release = vpif_platform_release,
2961 }
2962 };
vpif_probe
用video_device_alloc(); 给video_device *vfd 分配内存,并初始化,然后channel->video_dev 指向vfd,初始化channel objects,最后使用video_register_device注册video_dev。
具体如下:
2816 /* vpif_probe : This function creates device entries by register
2817 * itself to the V4L2 driver and initializes fields of each
2818 * channel objects */
2819 static __init int vpif_probe(struct device *device)
2820 {
2821 struct common_obj *common = NULL;
2822 int i, j = 0, k, err = 0, index = 0;
2823 struct video_device *vfd = NULL;
2824 struct channel_obj *channel = NULL;
2825 struct video_obj *vid_ch = NULL;
2826 vpif_dev = device;
2827
2828 for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) {
2829 /* Get the pointer to the channel object */
2830 channel = vpif_obj.dev[i];
2831 /* Allocate memory for video device */
2832 vfd = video_device_alloc();
2833 if (ISNULL(vfd)) {
2834 for (j = 0; j < i; j++) {
2835 video_device_release(vpif_obj.dev[j]->
2836 video_dev);
2837 }
2838 return -ENOMEM;
2839 }
2840
2841 /* Initialize field of video device */
2842 *vfd = vpif_video_template;
2843 vfd->dev = device;
2844 vfd->release = video_device_release;
2845 snprintf(vfd->name, sizeof(vfd->name),
2846 "DM646x_VPIFCapture_DRIVER_V%d.%d.%d",
2847 (VPIF_CAPTURE_VERSION_CODE >> 16) & 0xff,
2848 (VPIF_CAPTURE_VERSION_CODE >> 8) & 0xff,
2849 (VPIF_CAPTURE_VERSION_CODE) & 0xff);
2850 /* Set video_dev to the video device */
2851 channel->video_dev = vfd;
2852 }
2853
2854 for (j = 0; j < VPIF_CAPTURE_MAX_DEVICES; j++) {
2855 channel = vpif_obj.dev[j];
2856 channel->usrs = 0;
2857 for (k = VPIF_VIDEO_INDEX; k <= VPIF_HBI_INDEX; k++) {
2858 common = &(channel->common[k]);
2859 common->io_usrs = 0;
2860 common->started = 0;
2861 spin_lock_init(&common->irqlock);
2862 init_MUTEX(&common->lock);
2863 common->numbuffers = 0;
2864 common->set_addr = NULL;
2865 common->ytop_off = common->ybtm_off = 0;
2866 common->ctop_off = common->cbtm_off = 0;
2867 common->curFrm = common->nextFrm = NULL;
2868 memset(&common->fmt, 0, sizeof(struct v4l2_format));
2869 }
2870 channel->video.std = 0;
2871 channel->initialized = 0;
2872 channel->channel_id = j;
2873
2874 common = &(channel->common[VPIF_VIDEO_INDEX]);
2875 vid_ch = &(channel->video);
2876 /* Initialize field of the channel objects */
2877 channel->usrs = common->io_usrs = vid_ch->std = 0;
2878 common->started = channel->initialized = 0;
2879 channel->channel_id = j;
2880 common->numbuffers =
2881 config_params.numbuffers[channel->channel_id];
2882
2883 channel->numdecoders = 0;
2884 channel->current_decoder = 0;
2885 for (index = 0; index < VPIF_CAPTURE_NUM_DECODERS; index++) {
2886 channel->decoder[index] = NULL;
2887 }
2888
2889 memset(&(channel->vpifparams), 0, sizeof(struct vpif_params));
2890 /* Initialize prio member of channel object */
2891 v4l2_prio_init(&channel->prio);
2892
2893 /* Set the tasklet handler in the tasklet struct */
2894 channel->vbi.vbi_tasklet.func = vbi_work_handler;
2895 /* Set Timer counter */
2896 channel->vbi.timer_counter = VPIF_TIMER_COUNT;
2897 /* Initialize the work structure */
2898 INIT_WORK(&vbi_work[channel->channel_id],
2899 (void (*)(void *))vbi_work_handler, (void *)channel);
2900 /* register video device */
2901 dev_dbg(vpif_dev, "trying to register vpif device.\n");
2902 dev_dbg(vpif_dev, "channel=%x,channel->video_dev=%x\n",
2903 (int)channel, (int)&channel->video_dev);
2904 channel->common[VPIF_VIDEO_INDEX].fmt.type =
2905 V4L2_BUF_TYPE_VIDEO_OUTPUT;
2906 channel->common[VPIF_VBI_INDEX].fmt.type =
2907 V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
2908 channel->common[VPIF_HBI_INDEX].fmt.type =
2909 V4L2_BUF_TYPE_HBI_CAPTURE;
2910 err = video_register_device(channel->video_dev,
2911 VFL_TYPE_GRABBER, vpif_nr[j]);
2912 if (err)
2913 goto probe_out;
2914 }
2915 return 0;
2916
2917 probe_out:
2918 for (k = 0; k < j; k++) {
2919 /* Get the pointer to the channel object */
2920 channel = vpif_obj.dev[k];
2921 /* Unregister video device */
2922 video_unregister_device(channel->video_dev);
2923 /* Release video device */
2924 video_device_release(channel->video_dev);
2925 channel->video_dev = NULL;
2926 }
2927 dev_dbg(vpif_dev, "</vpif_probe>\n");
2928 return err;
2929 }
struct video_device *vfd = vpif_video_template;
vfd = vpif_video_template;是V4L2里面的video_device结构,
在drivers/media/video/davinci/davinci_capture.c 中
2809 static struct video_device vpif_video_template = {
2810 .name = "vpif",
2811 .type = VID_TYPE_CAPTURE,
2812 .hardware = 0,
2813 .fops = &vpif_fops,.minor = -1,
2814 };
2801 static struct file_operations vpif_fops = {
2802 .owner = THIS_MODULE,
2803 .open = vpif_open,//打开设备做一些初始化工作
2804 .release = vpif_release, //释放资源
2805 .ioctl = vpif_ioctl,//控制命令包括V4L2的命令和自定义的命令
2806 .mmap = vpif_mmap,//映射内核空间内存到用户空间
2807 .poll = vpif_poll
2808 };
vpif_ioctl的一些控制命令
vpif_ioctl封装了一些自定义的命了和V4L2的命令,其中V4L2的命令主要在vpif_doioctl实现。
/* If the case is for querying capabilities */
case VIDIOC_QUERYCAP:
/* If the case is for enumerating inputs */
case VIDIOC_ENUMINPUT:
/* If the case is for getting input */
case VIDIOC_G_INPUT:
/* If the case is for setting input */
case VIDIOC_S_INPUT:
/* If the case is for enumerating standards */
case VIDIOC_ENUMSTD:
/* If the case is for querying standards */
case VIDIOC_QUERYSTD:
/* If the case is for getting standard */
case VIDIOC_G_STD:
/* If the case is for setting standard */
case VIDIOC_S_STD:
/* If the case is for enumerating formats */
case VIDIOC_ENUM_FMT:
/* If the case is for getting formats */
case VIDIOC_G_FMT:
/* If the case is for setting formats */
case VIDIOC_S_FMT:
/* If the case is for trying formats */
case VIDIOC_TRY_FMT:
/* If the case is for querying controls */
case VIDIOC_QUERYCTRL:
/* If the case is for getting controls value */
case VIDIOC_G_CTRL:
/* If the case is for getting controls value */
case VIDIOC_S_CTRL:
/* If the case is for getting decoder parameters */
case VPIF_CMD_G_DECODER_PARAMS:
/* If the case is for setting decoder parameters */
case VPIF_CMD_S_DECODER_PARAMS:
/* If the case is for requesting buffer allocation */
case VIDIOC_REQBUFS:
/* If the case is for en-queing buffer in the buffer
* queue */
case VIDIOC_QBUF:
/* If the case is for de-queing buffer from the buffer queue */
case VIDIOC_DQBUF:
/* If the case is for querying information about
* buffer for memory mapping io */
case VIDIOC_QUERYBUF:
/* If the case is starting streaming */
case VIDIOC_STREAMON:
/* If the case is for stopping streaming */
case VIDIOC_STREAMOFF:
/* If the case is for setting VPIF parameters */
case VPIF_S_VPIF_PARAMS:
/* If the case is for getting VPIF Parameters */
case VPIF_G_VPIF_PARAMS:
/* If the case is for getting TVP5146 parameters */
case VPFE_CMD_CONFIG_TVP5146:
/* If the case is for setting mt9t001 parameters */
case VPFE_S_MT9T001_PARAMS:
/* If the case is for setting mt9t001 parameters */
case VPFE_G_MT9T001_PARAMS:
case VIDIOC_S_PRIORITY:
case VIDIOC_G_PRIORITY:
/* If the case is for getting sliced vbi capabilites */
case VIDIOC_G_SLICED_VBI_CAP:
/* If the case if for getting cropping parameters */
case VIDIOC_CROPCAP:
case VPIF_RESYNC:
case VPIF_RESET:
例如使用VIDIOC_ENUMSTD查询标准的时候,大概流程是这样的
1、首先判断是芯片驱动std_ops和dec->std_ops->enumstd是否有完成,如果没有完成则返回失败。
2、判断index是否是合法的
3、最后使用dec->std_ops->enumstd(std, dec),这个会函数直接调用芯片驱动的的xxx_enumstd函数(如sii9013_enumstd)。
具体代码如下:
1377 /* If the case is for enumerating standards */
1378 case VIDIOC_ENUMSTD:
1379 {
1380 struct v4l2_standard *std = (struct v4l2_standard *)arg;
1381 struct video_obj *vid_ch = &(channel->video);
1382 int index = std->index, dec_idx;
1383 dev_dbg(vpif_dev, "VIDIOC_ENUMSTD\n");
1384
1385
1386 /* Call enumstd function of decoder device */
1387 if (ISNULL(dec->std_ops)
1388 || ISNULL(dec->std_ops->enumstd)) {
1389 dev_err(vpif_dev, "vpif_doioctl:No enumstd\n");
1390 return -EINVAL;
1391 }
1392 if (index >= vid_ch->count_std) {
1393 dev_err(vpif_dev, "Invalid index\n");
1394 return -EINVAL;
1395 }
1396 dec_idx = vid_ch->std_tbl[index].dec_idx;
1397 dec = channel->decoder[dec_idx];
1398 std->index = vid_ch->std_tbl[index].std_idx;
1399 ret = dec->std_ops->enumstd(std, dec);
1400 std->index = index;
1401 break;
1402 }
主要是记录了一些流程,具体的问题没有进行分析,相关芯片的驱动分析可以查阅前面的分析记录。