Davinci V4L2视频采集框架分析
2013-07-28 18:16
429 查看
这里只是记录一些日志,难免有些错误,欢迎批评指正。Davinci V4L2视频采集框架主要是分析davinci_capture.c这个模块。
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.csdn.net/piaozhiye/article/details/7537419这里我就不罗嗦了。
模块注册与注销
3290module_init(vpif_init);
3291 module_exit(vpif_cleanup);
另外向其他模块提供了两个导出函数,提供给视频设备注册和注销。
3286 EXPORT_SYMBOL(vpif_register_decoder);
3287 EXPORT_SYMBOL(vpif_unregister_decoder);
vpif_initVPIF采集接口的初始化工作
主要是分配缓冲,检查设备类型,分配内存给channel objects,建立VBI处理的工作队列,注册vpif_driver,注册_vpif_device,申请request_irq,引脚复用的设置。在注册的时候会使用vpif_driver 的probe来进行注册,注册一些相关的ioctrol等。
01. 具体如下:
02.2979 /* vpif_init : This function registers device and driver to
03.2980 * the kernel, requests irq handler and allocates memory
04.2981 * for channel objects
05.2982 */
06.2983 static __init int vpif_init(void)
07.2984 {
08.2985 intfree_irq_no_index;
09.2986 int err = 0, i,j;
10.2987 intfree_channel_objects_index;
11.2988 intfree_buffer_channel_index;
12.2989 intfree_buffer_index;
13.2990 u8 *addr;
14.2991 u32 size;
15.2992
16.2993 /* Default number ofbuffers should be 3 */
17.2994 if((channel0_numbuffers > 0) &&
18.2995 (channel0_numbuffers < config_params.min_numbuffers))
19.2996 channel0_numbuffers = config_params.min_numbuffers;
20.2997 if((channel1_numbuffers > 0) &&
21.2998 (channel1_numbuffers < config_params.min_numbuffers))
22.2999 channel1_numbuffers = config_params.min_numbuffers;
23.3000
24.3001 /* Set buffer size tomin buffers size if invalid buffer size is
25.3002 * given */
26.3003 if (channel0_bufsize< config_params.min_bufsize[VPIF_CHANNEL0_VIDEO])
27.3004 channel0_bufsize =
28.3005 config_params.min_bufsize[VPIF_CHANNEL0_VIDEO];
29.3006 if (channel1_bufsize< config_params.min_bufsize[VPIF_CHANNEL1_VIDEO])
30.3007 channel1_bufsize =
31.3008 config_params.min_bufsize[VPIF_CHANNEL1_VIDEO];
32.3009
33.3010 config_params.numbuffers[VPIF_CHANNEL0_VIDEO] = channel0_numbuffers;
34.3011 config_params.numbuffers[VPIF_CHANNEL1_VIDEO] = channel1_numbuffers;
35.3012 if(channel0_numbuffers) {
36.3013 config_params.channel_bufsize[VPIF_CHANNEL0_VIDEO]
37.3014 = channel0_bufsize;
38.3015 }
39.3016 if (channel1_numbuffers){
40.3017 config_params.channel_bufsize[VPIF_CHANNEL1_VIDEO]
41.3018 = channel1_bufsize;
42.3019 }
43.3020
44.3021 /* Check the correctvalue of device_type */
45.3022 if ((device_type >config_params.max_device_type) || (device_type < 0)) {
46.3023 config_params.device_type = 0;
47.3024 } else {
48.3025 config_params.device_type = device_type;
49.3026 }
50.3027 /* Allocate memory forsix channel objects */
51.3028 for (i = 0; i <VPIF_CAPTURE_MAX_DEVICES; i++) {
52.3029 vpif_obj.dev[i] =
53.3030 kmalloc(sizeof(struct channel_obj), GFP_KERNEL);
54.3031 /* If memory allocation fails, return error */
55.3032 if (!vpif_obj.dev[i]) {
56.3033 free_channel_objects_index = i;
57.3034 goto vpif_init_free_channel_objects;
58.3035 err = -ENOMEM;
59.3036 }
60.3037 }
61.3038 free_channel_objects_index = VPIF_CAPTURE_MAX_DEVICES;
62.3039
63.3040 /* Allocate memory forbuffers */
64.3041 for (i = 0; i <VPIF_CAPTURE_NUM_CHANNELS; i++) {
65.3042 size = config_params.channel_bufsize[i];
66.3043 for (j = 0; j < config_params.numbuffers[i]; j++) {
67.3044 addr = (u8 *) vpif_alloc_buffer(size);
68.3045 if (!addr) {
69.3046 free_buffer_channel_index = i;
70.3047 free_buffer_index = j;
71.3048 err = -ENOMEM;
72.3049 goto vpif_init_free_buffers;
73.3050 }
74.3051 vpif_obj.dev[i]->common[VPIF_VIDEO_INDEX].fbuffers[j] =
75.3052 addr;
76.3053 }
77.3054 }
78.3055 free_buffer_channel_index = VPIF_CAPTURE_NUM_CHANNELS;
79.3056 free_buffer_index =config_params.numbuffers[i - 1];
80.3057
81.3058 /* Create the workqueue*/
82.3059 vbi_workqueue =create_singlethread_workqueue("vbi");
83.3060 if (!vbi_workqueue){
84.3061 err = -ENOMEM;
85.3062 goto vpif_init_free_buffers;
86.3063 }
87.3064
88.3065 /* Register driver tothe kernel */
89.3066 err =driver_register(&vpif_driver);
90.3067 if (0 != err) {
91.3068 goto vpif_init_free_buffers;
92.3069 }
93.3070 /* register device as aplatform device to the kernel */
94.3071 err = platform_device_register(&_vpif_device);
95.3072 if (0 != err) {
96.3073 goto vpif_init_unregister_vpif_driver;
97.3074 }
98.3075 for (j = 0; j <VPIF_CAPTURE_NUM_CHANNELS; j++) {
99.3076 err =
100.3077 request_irq(vpif_get_irq_number(j),
101.3078 vpif_channel_isr, SA_INTERRUPT,
102.3079 "DM646x_Capture",
103.3080 (void *)(&(vpif_obj.dev[j]->channel_id)));
104.3081 if (0 != err) {
105.3082 if (j == 0) {
106.3083 goto vpif_init_unregister_vpif_device;
107.3084 } else {
108.3085 free_irq_no_index = j;
109.3086 goto vpif_init_free_irq;
110.3087 }
111.3088
fd3d
}
112.3089 }
113.3090 free_irq_no_index =VPIF_CAPTURE_NUM_CHANNELS;
114.3091
115.3092 /*err = request_irq(4,vpif_err_isr, SA_INTERRUPT, "DM646x_Capture_err",*/
116.3093 /*(void*)NULL);*/
117.3094 /*if (0 !=err)*/
118.3095 /*{*/
119.3096 /*printk("requesterror interrupt is err!\n");*/
120.3097 /*return err;*/
121.3098 /*}*/
122.3099
123.3100 /*//initialize errorinterrupt register.*/
124.3101 /*init_int_err();*/
125.3102
126.3103 /* Set the pinmuxsettings */
127.3104 set_vpif_pinmux();
128.3105 set_vpif_capture_pinmux();
129.3106
130.3107 return 0;
131.3108
132.3109 vpif_init_free_irq:
133.3110 for (j = 0; j <free_irq_no_index; j++) {
134.3111 free_irq(vpif_get_irq_number(j),
135.3112 (void *)(&(vpif_obj.dev[j]->channel_id)));
136.3113 }
137.3114 vpif_init_unregister_vpif_device:
138.3115 platform_device_unregister(&_vpif_device);
139.3116
140.3117 vpif_init_unregister_vpif_driver:
141.3118 driver_unregister(&vpif_driver);
142.3119
143.3120 vpif_init_free_buffers:
144.3121 for (i = 0; i <free_buffer_channel_index; i++) {
145.3122 for (j = 0; j < config_params.numbuffers[i]; j++) {
146.3123 addr = vpif_obj.dev[i]->common[VPIF_VIDEO_INDEX].
147.3124 fbuffers[j];
148.3125 if (addr) {
149.3126 vpif_free_buffer((unsigned long)addr,
150.3127 config_params.
151.3128 channel_bufsize[i]
152.3129 );
153.3130 vpif_obj.dev[i]->common[VPIF_VIDEO_INDEX].
154.3131 fbuffers[j] = NULL;
155.3132 }
156.3133 }
157.3134 }
158.3135 for (j = 0; j <free_buffer_index; j++) {
159.3136 addr =
160.3137 vpif_obj.dev[free_buffer_channel_index]->
161.3138 common[VPIF_VIDEO_INDEX].fbuffers[j];
162.3139 if (addr) {
163.3140 vpif_free_buffer((unsigned long)addr,
164.3141 config_params.channel_bufsize[i]);
165.3142 vpif_obj.dev[free_buffer_channel_index]->
166.3143 common[VPIF_VIDEO_INDEX].fbuffers[j]
167.3144 = NULL;
168.3145 }
169.3146 }
170.3147
171.3148 vpif_init_free_channel_objects:
172.3149 for (j = 0; j <free_channel_objects_index; j++) {
173.3150 if (vpif_obj.dev[i]) {
174.3151 kfree(vpif_obj.dev[j]);
175.3152 vpif_obj.dev[i] = NULL;
176.3153 }
177.3154 }
178.3155 return err;
179.3156 }
其中的一些关键结构:
01.vpif_driver
02.2950 static struct device_driver vpif_driver = {
03.2951 .name = "vpifcapture",
04.2952 .bus =&platform_bus_type,
05.2953 .probe =vpif_probe,
06.2954 .remove =vpif_remove,
07.2955 };
08.2956 static struct platform_device _vpif_device = {
09.2957 .name = "vpifcapture",
10.2958 .id = 1,
11.2959 .dev = {
12.2960 .release = vpif_platform_release,
13.2961 }
14.2962};
vpif_probe
用video_device_alloc(); 给video_device *vfd 分配内存,并初始化,然后channel->video_dev指向vfd,初始化channel objects,最后使用video_register_device注册video_dev。
具体如下:
01.2816 /* vpif_probe : This function creates device entries by register
02.2817 * itself to the V4L2 driver and initializes fields of each
03.2818 * channel objects */
04.2819 static __init int vpif_probe(struct device *device)
05.2820 {
06.2821 struct common_obj*common = NULL;
07.2822 int i, j = 0, k, err =0, index = 0;
08.2823 struct video_device*vfd = NULL;
09.2824 struct channel_obj*channel = NULL;
10.2825 struct video_obj*vid_ch = NULL;
11.2826 vpif_dev =device;
12.2827
13.2828 for (i = 0; i <VPIF_CAPTURE_MAX_DEVICES; i++) {
14.2829 /* Get the pointer to the channel object */
15.2830 channel = vpif_obj.dev[i];
16.2831 /* Allocate memory for video device */
17.2832 vfd = video_device_alloc();
18.2833 if (ISNULL(vfd)) {
19.2834 for (j = 0; j < i; j++) {
20.2835 video_device_release(vpif_obj.dev[j]->
21.2836 video_dev);
22.2837 }
23.2838 return -ENOMEM;
24.2839 }
25.2840
26.2841 /* Initialize field of video device */
27.2842 *vfd = vpif_video_template;
28.2843 vfd->dev = device;
29.2844 vfd->release = video_device_release;
30.2845 snprintf(vfd->name, sizeof(vfd->name),
31.2846 "DM646x_VPIFCapture_DRIVER_V%d.%d.%d",
32.2847 (VPIF_CAPTURE_VERSION_CODE >> 16) & 0xff,
33.2848 (VPIF_CAPTURE_VERSION_CODE >> 8) & 0xff,
34.2849 (VPIF_CAPTURE_VERSION_CODE) & 0xff);
35.2850 /* Set video_dev to the video device */
36.2851 channel->video_dev = vfd;
37.2852 }
38.2853
39.2854 for (j = 0; j <VPIF_CAPTURE_MAX_DEVICES; j++) {
40.2855 channel = vpif_obj.dev[j];
41.2856 channel->usrs = 0;
42.2857 for (k = VPIF_VIDEO_INDEX; k <= VPIF_HBI_INDEX; k++) {
43.2858 common = &(channel->common[k]);
44.2859 common->io_usrs = 0;
45.2860 common->started = 0;
46.2861 spin_lock_init(&common->irqlock);
47.2862 init_MUTEX(&common->lock);
48.2863 common->numbuffers = 0;
49.2864 common->set_addr = NULL;
50.2865 common->ytop_off = common->ybtm_off = 0;
51.2866 common->ctop_off = common->cbtm_off = 0;
52.2867 common->curFrm = common->nextFrm = NULL;
53.2868 memset(&common->fmt, 0, sizeof(struct v4l2_format));
54.2869 }
55.2870 channel->video.std = 0;
56.2871 channel->initialized = 0;
57.2872 channel->channel_id = j;
58.2873
59.2874 common = &(channel->common[VPIF_VIDEO_INDEX]);
60.2875 vid_ch = &(channel->video);
61.2876 /* Initialize field of the channel objects */
62.2877 channel->usrs = common->io_usrs = vid_ch->std = 0;
63.2878 common->started = channel->initialized = 0;
64.2879 channel->channel_id = j;
65.2880 common->numbuffers =
66.2881 config_params.numbuffers[channel->channel_id];
67.2882
68.2883 channel->numdecoders = 0;
69.2884 channel->current_decoder = 0;
70.2885 for (index = 0; index < VPIF_CAPTURE_NUM_DECODERS; index++) {
71.2886 channel->decoder[index] = NULL;
72.2887 }
73.2888
74.2889 memset(&(channel->vpifparams), 0, sizeof(struct vpif_params));
75.2890 /* Initialize prio member of channel object */
76.2891 v4l2_prio_init(&channel->prio);
77.2892
78.2893 /* Set the tasklet handler in the tasklet struct */
79.2894 channel->vbi.vbi_tasklet.func = vbi_work_handler;
80.2895 /* Set Timer counter */
81.2896 channel->vbi.timer_counter = VPIF_TIMER_COUNT;
82.2897 /* Initialize the work structure */
83.2898 INIT_WORK(&vbi_work[channel->channel_id],
84.2899 (void (*)(void *))vbi_work_handler, (void *)channel);
85.2900 /* register video device */
86.2901 dev_dbg(vpif_dev, "trying to register vpif device.\n");
87.2902 dev_dbg(vpif_dev, "channel=%x,channel->video_dev=%x\n",
88.2903 (int)channel, (int)&channel->video_dev);
89.2904 channel->common[VPIF_VIDEO_INDEX].fmt.type =
90.2905 V4L2_BUF_TYPE_VIDEO_OUTPUT;
91.2906 channel->common[VPIF_VBI_INDEX].fmt.type =
92.2907 V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
93.2908 channel->common[VPIF_HBI_INDEX].fmt.type =
94.2909 V4L2_BUF_TYPE_HBI_CAPTURE;
95.2910 err = video_register_device(channel->video_dev,
96.2911 VFL_TYPE_GRABBER, vpif_nr[j]);
97.2912 if (err)
98.2913 goto probe_out;
99.2914 }
100.2915 return 0;
101.2916
102.2917 probe_out:
103.2918 for (k = 0; k < j;k++) {
104.2919 /* Get the pointer to the channel object */
105.2920 channel = vpif_obj.dev[k];
106.2921 /* Unregister video device */
107.2922 video_unregister_device(channel->video_dev);
108.2923 /* Release video device */
109.2924 video_device_release(channel->video_dev);
110.2925 channel->video_dev = NULL;
111.2926 }
112.2927 dev_dbg(vpif_dev,"</vpif_probe>\n");
113.2928 return err;
114.2929 }
structvideo_device *vfd = vpif_video_template;
01. vfd = vpif_video_template;是V4L2里面的video_device结构,
02. 在drivers/media/video/davinci/davinci_capture.c中
03.2809 static struct video_device vpif_video_template = {
04.2810 .name ="vpif",
05.2811 .type =VID_TYPE_CAPTURE,
06.2812 .hardware = 0,
07.2813 .fops =&vpif_fops,.minor = -1,
08.2814 };
09.
10.2801 static struct file_operations vpif_fops = {
11.2802 .owner =THIS_MODULE,
12.2803 .open = vpif_open,//打开设备做一些初始化工作
13.2804 .release =vpif_release, //释放资源
14.2805 .ioctl = vpif_ioctl,//控制命令包括V4L2的命令和自定义的命令
15.2806 .mmap = vpif_mmap,//映射内核空间内存到用户空间
16.2807 .poll =vpif_poll
17.2808};
vpif_ioctl的一些控制命令
vpif_ioctl封装了一些自定义的命了和V4L2的命令,其中V4L2的命令主要在vpif_doioctl实现。
01./* If the case is for querying capabilities */
02. caseVIDIOC_QUERYCAP:
03. /* If the case is for enumerating inputs */
04. caseVIDIOC_ENUMINPUT:
05. /* If the case is for getting input */
06. caseVIDIOC_G_INPUT:
07. /* If the case is for setting input */
08. caseVIDIOC_S_INPUT:
09. /* If the case is for enumerating standards */
10. caseVIDIOC_ENUMSTD:
11. /* If the case is for querying standards */
12. caseVIDIOC_QUERYSTD:
13. /* If the case is for getting standard */
14. caseVIDIOC_G_STD:
15. /* If the case is for setting standard */
16. caseVIDIOC_S_STD:
17. /* If the case is for enumerating formats */
18. caseVIDIOC_ENUM_FMT:
19. /* If the case is for getting formats */
20. caseVIDIOC_G_FMT:
21. /* If the case is for setting formats */
22. caseVIDIOC_S_FMT:
23. /* If the case is for trying formats */
24. caseVIDIOC_TRY_FMT:
25. /* If the case is for querying controls */
26. caseVIDIOC_QUERYCTRL:
27. /* If the case is for getting controls value */
28. caseVIDIOC_G_CTRL:
29. /* If the case is for getting controls value */
30. caseVIDIOC_S_CTRL:
31. /* If the case is for getting decoder parameters */
32. caseVPIF_CMD_G_DECODER_PARAMS:
33. /* If the case is for setting decoder parameters */
34. caseVPIF_CMD_S_DECODER_PARAMS:
35. /* If the case is for requesting buffer allocation */
36. caseVIDIOC_REQBUFS:
37. /* If the case is for en-queing buffer in the buffer
38. * queue */
39. caseVIDIOC_QBUF:
40. /* If the case is for de-queing buffer from the buffer queue */
41. caseVIDIOC_DQBUF:
42. /*If the case is for querying information about
43. * buffer for memory mapping io */
44. caseVIDIOC_QUERYBUF:
45. /* If the case is starting streaming */
46. caseVIDIOC_STREAMON:
47. /* If the case is for stopping streaming */
48. caseVIDIOC_STREAMOFF:
49. /* If the case is for setting VPIF parameters */
50. caseVPIF_S_VPIF_PARAMS:
51. /* If the case is for getting VPIF Parameters */
52. caseVPIF_G_VPIF_PARAMS:
53. /* If the case is for getting TVP5146 parameters */
54. caseVPFE_CMD_CONFIG_TVP5146:
55. /* If the case is for setting mt9t001 parameters */
56. caseVPFE_S_MT9T001_PARAMS:
57. /* If the case is for setting mt9t001 parameters */
58. caseVPFE_G_MT9T001_PARAMS:
59. case VIDIOC_S_PRIORITY:
60. caseVIDIOC_G_PRIORITY:
61. /* If the case is for getting sliced vbi capabilites */
62. caseVIDIOC_G_SLICED_VBI_CAP:
63. /* If the case if for getting cropping parameters */
64. caseVIDIOC_CROPCAP:
65. caseVPIF_RESYNC:
66. caseVPIF_RESET:
例如使用VIDIOC_ENUMSTD查询标准的时候,大概流程是这样的
1、首先判断是芯片驱动std_ops和dec->std_ops->enumstd是否有完成,如果没有完成则返回失败。
2、判断index是否是合法的
3、最后使用dec->std_ops->enumstd(std, dec),这个会函数直接调用芯片驱动的的xxx_enumstd函数(如sii9013_enumstd)。
具体代码如下:
01.1377 /* If the case is for enumerating standards */
02.1378 case VIDIOC_ENUMSTD:
03.1379 {
04.1380 struct v4l2_standard *std = (struct v4l2_standard *)arg;
05.1381 struct video_obj *vid_ch = &(channel->video);
06.1382 int index = std->index, dec_idx;
07.1383 dev_dbg(vpif_dev, "VIDIOC_ENUMSTD\n");
08.1384
09.1385
10.1386 /* Call enumstd function of decoder device */
11.1387 if (ISNULL(dec->std_ops)
12.1388 || ISNULL(dec->std_ops->enumstd)) {
13.1389 dev_err(vpif_dev, "vpif_doioctl:No enumstd\n");
14.1390 return -EINVAL;
15.1391 }
16.1392 if (index >= vid_ch->count_std) {
17.1393 dev_err(vpif_dev, "Invalid index\n");
18.1394 return -EINVAL;
19.1395 }
20.1396 dec_idx = vid_ch->std_tbl[index].dec_idx;
21.1397 dec = channel->decoder[dec_idx];
22.1398 std->index = vid_ch->std_tbl[index].std_idx;
23.1399 ret = dec->std_ops->enumstd(std, dec);
24.1400 std->index = index;
25.1401 break;
26.1402 }
主要是记录了一些流程,具体的问题没有进行分析,相关芯片的驱动分析可以查阅前面的分析记录。
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.csdn.net/piaozhiye/article/details/7537419这里我就不罗嗦了。
模块注册与注销
3290module_init(vpif_init);
3291 module_exit(vpif_cleanup);
另外向其他模块提供了两个导出函数,提供给视频设备注册和注销。
3286 EXPORT_SYMBOL(vpif_register_decoder);
3287 EXPORT_SYMBOL(vpif_unregister_decoder);
vpif_initVPIF采集接口的初始化工作
主要是分配缓冲,检查设备类型,分配内存给channel objects,建立VBI处理的工作队列,注册vpif_driver,注册_vpif_device,申请request_irq,引脚复用的设置。在注册的时候会使用vpif_driver 的probe来进行注册,注册一些相关的ioctrol等。
01. 具体如下:
02.2979 /* vpif_init : This function registers device and driver to
03.2980 * the kernel, requests irq handler and allocates memory
04.2981 * for channel objects
05.2982 */
06.2983 static __init int vpif_init(void)
07.2984 {
08.2985 intfree_irq_no_index;
09.2986 int err = 0, i,j;
10.2987 intfree_channel_objects_index;
11.2988 intfree_buffer_channel_index;
12.2989 intfree_buffer_index;
13.2990 u8 *addr;
14.2991 u32 size;
15.2992
16.2993 /* Default number ofbuffers should be 3 */
17.2994 if((channel0_numbuffers > 0) &&
18.2995 (channel0_numbuffers < config_params.min_numbuffers))
19.2996 channel0_numbuffers = config_params.min_numbuffers;
20.2997 if((channel1_numbuffers > 0) &&
21.2998 (channel1_numbuffers < config_params.min_numbuffers))
22.2999 channel1_numbuffers = config_params.min_numbuffers;
23.3000
24.3001 /* Set buffer size tomin buffers size if invalid buffer size is
25.3002 * given */
26.3003 if (channel0_bufsize< config_params.min_bufsize[VPIF_CHANNEL0_VIDEO])
27.3004 channel0_bufsize =
28.3005 config_params.min_bufsize[VPIF_CHANNEL0_VIDEO];
29.3006 if (channel1_bufsize< config_params.min_bufsize[VPIF_CHANNEL1_VIDEO])
30.3007 channel1_bufsize =
31.3008 config_params.min_bufsize[VPIF_CHANNEL1_VIDEO];
32.3009
33.3010 config_params.numbuffers[VPIF_CHANNEL0_VIDEO] = channel0_numbuffers;
34.3011 config_params.numbuffers[VPIF_CHANNEL1_VIDEO] = channel1_numbuffers;
35.3012 if(channel0_numbuffers) {
36.3013 config_params.channel_bufsize[VPIF_CHANNEL0_VIDEO]
37.3014 = channel0_bufsize;
38.3015 }
39.3016 if (channel1_numbuffers){
40.3017 config_params.channel_bufsize[VPIF_CHANNEL1_VIDEO]
41.3018 = channel1_bufsize;
42.3019 }
43.3020
44.3021 /* Check the correctvalue of device_type */
45.3022 if ((device_type >config_params.max_device_type) || (device_type < 0)) {
46.3023 config_params.device_type = 0;
47.3024 } else {
48.3025 config_params.device_type = device_type;
49.3026 }
50.3027 /* Allocate memory forsix channel objects */
51.3028 for (i = 0; i <VPIF_CAPTURE_MAX_DEVICES; i++) {
52.3029 vpif_obj.dev[i] =
53.3030 kmalloc(sizeof(struct channel_obj), GFP_KERNEL);
54.3031 /* If memory allocation fails, return error */
55.3032 if (!vpif_obj.dev[i]) {
56.3033 free_channel_objects_index = i;
57.3034 goto vpif_init_free_channel_objects;
58.3035 err = -ENOMEM;
59.3036 }
60.3037 }
61.3038 free_channel_objects_index = VPIF_CAPTURE_MAX_DEVICES;
62.3039
63.3040 /* Allocate memory forbuffers */
64.3041 for (i = 0; i <VPIF_CAPTURE_NUM_CHANNELS; i++) {
65.3042 size = config_params.channel_bufsize[i];
66.3043 for (j = 0; j < config_params.numbuffers[i]; j++) {
67.3044 addr = (u8 *) vpif_alloc_buffer(size);
68.3045 if (!addr) {
69.3046 free_buffer_channel_index = i;
70.3047 free_buffer_index = j;
71.3048 err = -ENOMEM;
72.3049 goto vpif_init_free_buffers;
73.3050 }
74.3051 vpif_obj.dev[i]->common[VPIF_VIDEO_INDEX].fbuffers[j] =
75.3052 addr;
76.3053 }
77.3054 }
78.3055 free_buffer_channel_index = VPIF_CAPTURE_NUM_CHANNELS;
79.3056 free_buffer_index =config_params.numbuffers[i - 1];
80.3057
81.3058 /* Create the workqueue*/
82.3059 vbi_workqueue =create_singlethread_workqueue("vbi");
83.3060 if (!vbi_workqueue){
84.3061 err = -ENOMEM;
85.3062 goto vpif_init_free_buffers;
86.3063 }
87.3064
88.3065 /* Register driver tothe kernel */
89.3066 err =driver_register(&vpif_driver);
90.3067 if (0 != err) {
91.3068 goto vpif_init_free_buffers;
92.3069 }
93.3070 /* register device as aplatform device to the kernel */
94.3071 err = platform_device_register(&_vpif_device);
95.3072 if (0 != err) {
96.3073 goto vpif_init_unregister_vpif_driver;
97.3074 }
98.3075 for (j = 0; j <VPIF_CAPTURE_NUM_CHANNELS; j++) {
99.3076 err =
100.3077 request_irq(vpif_get_irq_number(j),
101.3078 vpif_channel_isr, SA_INTERRUPT,
102.3079 "DM646x_Capture",
103.3080 (void *)(&(vpif_obj.dev[j]->channel_id)));
104.3081 if (0 != err) {
105.3082 if (j == 0) {
106.3083 goto vpif_init_unregister_vpif_device;
107.3084 } else {
108.3085 free_irq_no_index = j;
109.3086 goto vpif_init_free_irq;
110.3087 }
111.3088
fd3d
}
112.3089 }
113.3090 free_irq_no_index =VPIF_CAPTURE_NUM_CHANNELS;
114.3091
115.3092 /*err = request_irq(4,vpif_err_isr, SA_INTERRUPT, "DM646x_Capture_err",*/
116.3093 /*(void*)NULL);*/
117.3094 /*if (0 !=err)*/
118.3095 /*{*/
119.3096 /*printk("requesterror interrupt is err!\n");*/
120.3097 /*return err;*/
121.3098 /*}*/
122.3099
123.3100 /*//initialize errorinterrupt register.*/
124.3101 /*init_int_err();*/
125.3102
126.3103 /* Set the pinmuxsettings */
127.3104 set_vpif_pinmux();
128.3105 set_vpif_capture_pinmux();
129.3106
130.3107 return 0;
131.3108
132.3109 vpif_init_free_irq:
133.3110 for (j = 0; j <free_irq_no_index; j++) {
134.3111 free_irq(vpif_get_irq_number(j),
135.3112 (void *)(&(vpif_obj.dev[j]->channel_id)));
136.3113 }
137.3114 vpif_init_unregister_vpif_device:
138.3115 platform_device_unregister(&_vpif_device);
139.3116
140.3117 vpif_init_unregister_vpif_driver:
141.3118 driver_unregister(&vpif_driver);
142.3119
143.3120 vpif_init_free_buffers:
144.3121 for (i = 0; i <free_buffer_channel_index; i++) {
145.3122 for (j = 0; j < config_params.numbuffers[i]; j++) {
146.3123 addr = vpif_obj.dev[i]->common[VPIF_VIDEO_INDEX].
147.3124 fbuffers[j];
148.3125 if (addr) {
149.3126 vpif_free_buffer((unsigned long)addr,
150.3127 config_params.
151.3128 channel_bufsize[i]
152.3129 );
153.3130 vpif_obj.dev[i]->common[VPIF_VIDEO_INDEX].
154.3131 fbuffers[j] = NULL;
155.3132 }
156.3133 }
157.3134 }
158.3135 for (j = 0; j <free_buffer_index; j++) {
159.3136 addr =
160.3137 vpif_obj.dev[free_buffer_channel_index]->
161.3138 common[VPIF_VIDEO_INDEX].fbuffers[j];
162.3139 if (addr) {
163.3140 vpif_free_buffer((unsigned long)addr,
164.3141 config_params.channel_bufsize[i]);
165.3142 vpif_obj.dev[free_buffer_channel_index]->
166.3143 common[VPIF_VIDEO_INDEX].fbuffers[j]
167.3144 = NULL;
168.3145 }
169.3146 }
170.3147
171.3148 vpif_init_free_channel_objects:
172.3149 for (j = 0; j <free_channel_objects_index; j++) {
173.3150 if (vpif_obj.dev[i]) {
174.3151 kfree(vpif_obj.dev[j]);
175.3152 vpif_obj.dev[i] = NULL;
176.3153 }
177.3154 }
178.3155 return err;
179.3156 }
其中的一些关键结构:
01.vpif_driver
02.2950 static struct device_driver vpif_driver = {
03.2951 .name = "vpifcapture",
04.2952 .bus =&platform_bus_type,
05.2953 .probe =vpif_probe,
06.2954 .remove =vpif_remove,
07.2955 };
08.2956 static struct platform_device _vpif_device = {
09.2957 .name = "vpifcapture",
10.2958 .id = 1,
11.2959 .dev = {
12.2960 .release = vpif_platform_release,
13.2961 }
14.2962};
vpif_probe
用video_device_alloc(); 给video_device *vfd 分配内存,并初始化,然后channel->video_dev指向vfd,初始化channel objects,最后使用video_register_device注册video_dev。
具体如下:
01.2816 /* vpif_probe : This function creates device entries by register
02.2817 * itself to the V4L2 driver and initializes fields of each
03.2818 * channel objects */
04.2819 static __init int vpif_probe(struct device *device)
05.2820 {
06.2821 struct common_obj*common = NULL;
07.2822 int i, j = 0, k, err =0, index = 0;
08.2823 struct video_device*vfd = NULL;
09.2824 struct channel_obj*channel = NULL;
10.2825 struct video_obj*vid_ch = NULL;
11.2826 vpif_dev =device;
12.2827
13.2828 for (i = 0; i <VPIF_CAPTURE_MAX_DEVICES; i++) {
14.2829 /* Get the pointer to the channel object */
15.2830 channel = vpif_obj.dev[i];
16.2831 /* Allocate memory for video device */
17.2832 vfd = video_device_alloc();
18.2833 if (ISNULL(vfd)) {
19.2834 for (j = 0; j < i; j++) {
20.2835 video_device_release(vpif_obj.dev[j]->
21.2836 video_dev);
22.2837 }
23.2838 return -ENOMEM;
24.2839 }
25.2840
26.2841 /* Initialize field of video device */
27.2842 *vfd = vpif_video_template;
28.2843 vfd->dev = device;
29.2844 vfd->release = video_device_release;
30.2845 snprintf(vfd->name, sizeof(vfd->name),
31.2846 "DM646x_VPIFCapture_DRIVER_V%d.%d.%d",
32.2847 (VPIF_CAPTURE_VERSION_CODE >> 16) & 0xff,
33.2848 (VPIF_CAPTURE_VERSION_CODE >> 8) & 0xff,
34.2849 (VPIF_CAPTURE_VERSION_CODE) & 0xff);
35.2850 /* Set video_dev to the video device */
36.2851 channel->video_dev = vfd;
37.2852 }
38.2853
39.2854 for (j = 0; j <VPIF_CAPTURE_MAX_DEVICES; j++) {
40.2855 channel = vpif_obj.dev[j];
41.2856 channel->usrs = 0;
42.2857 for (k = VPIF_VIDEO_INDEX; k <= VPIF_HBI_INDEX; k++) {
43.2858 common = &(channel->common[k]);
44.2859 common->io_usrs = 0;
45.2860 common->started = 0;
46.2861 spin_lock_init(&common->irqlock);
47.2862 init_MUTEX(&common->lock);
48.2863 common->numbuffers = 0;
49.2864 common->set_addr = NULL;
50.2865 common->ytop_off = common->ybtm_off = 0;
51.2866 common->ctop_off = common->cbtm_off = 0;
52.2867 common->curFrm = common->nextFrm = NULL;
53.2868 memset(&common->fmt, 0, sizeof(struct v4l2_format));
54.2869 }
55.2870 channel->video.std = 0;
56.2871 channel->initialized = 0;
57.2872 channel->channel_id = j;
58.2873
59.2874 common = &(channel->common[VPIF_VIDEO_INDEX]);
60.2875 vid_ch = &(channel->video);
61.2876 /* Initialize field of the channel objects */
62.2877 channel->usrs = common->io_usrs = vid_ch->std = 0;
63.2878 common->started = channel->initialized = 0;
64.2879 channel->channel_id = j;
65.2880 common->numbuffers =
66.2881 config_params.numbuffers[channel->channel_id];
67.2882
68.2883 channel->numdecoders = 0;
69.2884 channel->current_decoder = 0;
70.2885 for (index = 0; index < VPIF_CAPTURE_NUM_DECODERS; index++) {
71.2886 channel->decoder[index] = NULL;
72.2887 }
73.2888
74.2889 memset(&(channel->vpifparams), 0, sizeof(struct vpif_params));
75.2890 /* Initialize prio member of channel object */
76.2891 v4l2_prio_init(&channel->prio);
77.2892
78.2893 /* Set the tasklet handler in the tasklet struct */
79.2894 channel->vbi.vbi_tasklet.func = vbi_work_handler;
80.2895 /* Set Timer counter */
81.2896 channel->vbi.timer_counter = VPIF_TIMER_COUNT;
82.2897 /* Initialize the work structure */
83.2898 INIT_WORK(&vbi_work[channel->channel_id],
84.2899 (void (*)(void *))vbi_work_handler, (void *)channel);
85.2900 /* register video device */
86.2901 dev_dbg(vpif_dev, "trying to register vpif device.\n");
87.2902 dev_dbg(vpif_dev, "channel=%x,channel->video_dev=%x\n",
88.2903 (int)channel, (int)&channel->video_dev);
89.2904 channel->common[VPIF_VIDEO_INDEX].fmt.type =
90.2905 V4L2_BUF_TYPE_VIDEO_OUTPUT;
91.2906 channel->common[VPIF_VBI_INDEX].fmt.type =
92.2907 V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
93.2908 channel->common[VPIF_HBI_INDEX].fmt.type =
94.2909 V4L2_BUF_TYPE_HBI_CAPTURE;
95.2910 err = video_register_device(channel->video_dev,
96.2911 VFL_TYPE_GRABBER, vpif_nr[j]);
97.2912 if (err)
98.2913 goto probe_out;
99.2914 }
100.2915 return 0;
101.2916
102.2917 probe_out:
103.2918 for (k = 0; k < j;k++) {
104.2919 /* Get the pointer to the channel object */
105.2920 channel = vpif_obj.dev[k];
106.2921 /* Unregister video device */
107.2922 video_unregister_device(channel->video_dev);
108.2923 /* Release video device */
109.2924 video_device_release(channel->video_dev);
110.2925 channel->video_dev = NULL;
111.2926 }
112.2927 dev_dbg(vpif_dev,"</vpif_probe>\n");
113.2928 return err;
114.2929 }
structvideo_device *vfd = vpif_video_template;
01. vfd = vpif_video_template;是V4L2里面的video_device结构,
02. 在drivers/media/video/davinci/davinci_capture.c中
03.2809 static struct video_device vpif_video_template = {
04.2810 .name ="vpif",
05.2811 .type =VID_TYPE_CAPTURE,
06.2812 .hardware = 0,
07.2813 .fops =&vpif_fops,.minor = -1,
08.2814 };
09.
10.2801 static struct file_operations vpif_fops = {
11.2802 .owner =THIS_MODULE,
12.2803 .open = vpif_open,//打开设备做一些初始化工作
13.2804 .release =vpif_release, //释放资源
14.2805 .ioctl = vpif_ioctl,//控制命令包括V4L2的命令和自定义的命令
15.2806 .mmap = vpif_mmap,//映射内核空间内存到用户空间
16.2807 .poll =vpif_poll
17.2808};
vpif_ioctl的一些控制命令
vpif_ioctl封装了一些自定义的命了和V4L2的命令,其中V4L2的命令主要在vpif_doioctl实现。
01./* If the case is for querying capabilities */
02. caseVIDIOC_QUERYCAP:
03. /* If the case is for enumerating inputs */
04. caseVIDIOC_ENUMINPUT:
05. /* If the case is for getting input */
06. caseVIDIOC_G_INPUT:
07. /* If the case is for setting input */
08. caseVIDIOC_S_INPUT:
09. /* If the case is for enumerating standards */
10. caseVIDIOC_ENUMSTD:
11. /* If the case is for querying standards */
12. caseVIDIOC_QUERYSTD:
13. /* If the case is for getting standard */
14. caseVIDIOC_G_STD:
15. /* If the case is for setting standard */
16. caseVIDIOC_S_STD:
17. /* If the case is for enumerating formats */
18. caseVIDIOC_ENUM_FMT:
19. /* If the case is for getting formats */
20. caseVIDIOC_G_FMT:
21. /* If the case is for setting formats */
22. caseVIDIOC_S_FMT:
23. /* If the case is for trying formats */
24. caseVIDIOC_TRY_FMT:
25. /* If the case is for querying controls */
26. caseVIDIOC_QUERYCTRL:
27. /* If the case is for getting controls value */
28. caseVIDIOC_G_CTRL:
29. /* If the case is for getting controls value */
30. caseVIDIOC_S_CTRL:
31. /* If the case is for getting decoder parameters */
32. caseVPIF_CMD_G_DECODER_PARAMS:
33. /* If the case is for setting decoder parameters */
34. caseVPIF_CMD_S_DECODER_PARAMS:
35. /* If the case is for requesting buffer allocation */
36. caseVIDIOC_REQBUFS:
37. /* If the case is for en-queing buffer in the buffer
38. * queue */
39. caseVIDIOC_QBUF:
40. /* If the case is for de-queing buffer from the buffer queue */
41. caseVIDIOC_DQBUF:
42. /*If the case is for querying information about
43. * buffer for memory mapping io */
44. caseVIDIOC_QUERYBUF:
45. /* If the case is starting streaming */
46. caseVIDIOC_STREAMON:
47. /* If the case is for stopping streaming */
48. caseVIDIOC_STREAMOFF:
49. /* If the case is for setting VPIF parameters */
50. caseVPIF_S_VPIF_PARAMS:
51. /* If the case is for getting VPIF Parameters */
52. caseVPIF_G_VPIF_PARAMS:
53. /* If the case is for getting TVP5146 parameters */
54. caseVPFE_CMD_CONFIG_TVP5146:
55. /* If the case is for setting mt9t001 parameters */
56. caseVPFE_S_MT9T001_PARAMS:
57. /* If the case is for setting mt9t001 parameters */
58. caseVPFE_G_MT9T001_PARAMS:
59. case VIDIOC_S_PRIORITY:
60. caseVIDIOC_G_PRIORITY:
61. /* If the case is for getting sliced vbi capabilites */
62. caseVIDIOC_G_SLICED_VBI_CAP:
63. /* If the case if for getting cropping parameters */
64. caseVIDIOC_CROPCAP:
65. caseVPIF_RESYNC:
66. caseVPIF_RESET:
例如使用VIDIOC_ENUMSTD查询标准的时候,大概流程是这样的
1、首先判断是芯片驱动std_ops和dec->std_ops->enumstd是否有完成,如果没有完成则返回失败。
2、判断index是否是合法的
3、最后使用dec->std_ops->enumstd(std, dec),这个会函数直接调用芯片驱动的的xxx_enumstd函数(如sii9013_enumstd)。
具体代码如下:
01.1377 /* If the case is for enumerating standards */
02.1378 case VIDIOC_ENUMSTD:
03.1379 {
04.1380 struct v4l2_standard *std = (struct v4l2_standard *)arg;
05.1381 struct video_obj *vid_ch = &(channel->video);
06.1382 int index = std->index, dec_idx;
07.1383 dev_dbg(vpif_dev, "VIDIOC_ENUMSTD\n");
08.1384
09.1385
10.1386 /* Call enumstd function of decoder device */
11.1387 if (ISNULL(dec->std_ops)
12.1388 || ISNULL(dec->std_ops->enumstd)) {
13.1389 dev_err(vpif_dev, "vpif_doioctl:No enumstd\n");
14.1390 return -EINVAL;
15.1391 }
16.1392 if (index >= vid_ch->count_std) {
17.1393 dev_err(vpif_dev, "Invalid index\n");
18.1394 return -EINVAL;
19.1395 }
20.1396 dec_idx = vid_ch->std_tbl[index].dec_idx;
21.1397 dec = channel->decoder[dec_idx];
22.1398 std->index = vid_ch->std_tbl[index].std_idx;
23.1399 ret = dec->std_ops->enumstd(std, dec);
24.1400 std->index = index;
25.1401 break;
26.1402 }
主要是记录了一些流程,具体的问题没有进行分析,相关芯片的驱动分析可以查阅前面的分析记录。
相关文章推荐
- Davinci V4L2视频采集框架分析
- v4l2视频采集驱动框架
- V4L2视频采集框架
- V4L2视频采集驱动框架
- Linux内核中的V4L2核心框架分析(V4L2 framework,video for linux 2,linux视频子系统) .
- [完结]Linux内核中的V4L2核心框架分析(V4L2 framework,video for linux 2,linux视频子系统)
- v4l2视频采集驱动框架(vfe, camera i2c driver,v4l2_subdev等之间的联系)
- linux3.3 v4l2视频采集驱动框架(vfe, camera i2c driver,v4l2_subdev等之间的联系)
- Linux内核中的V4L2核心框架分析(V4L2 framework,video for linux 2,linux视频子系统)
- V4L2视频采集接口使用说明
- 实现 V4L2视频采集与 FFMPEG 编码YUYV 数据 为H264(2)
- Linux之V4L2视频采集编程详解
- V4L2框架分析
- V4L2视频采集操作流程和接口说明
- DAVINCI DM6446 开发攻略——V4L2视频驱动和应用分析
- 入门视频采集与处理(学会分析YUV数据)
- V4L2采集yuv视频花屏:Linux视频采集与编码(一)
- V4L2框架分析学习
- 嵌入式LINUX环境下基于V4L2视频采集知识
- 基于V4L2视频采集缓存机制应用与实现