OK6410 V4L2 分析
主要分析来自下面一篇文章。
http://www.chinaaet.com/article/3000015768
/*
由mach-smdk6410.c文件可知,内核启动时将所有platform_device
包括 s3c_device_fimc0 s3c_device_fimc1
挂载到platform总线。
*//*
dev-fimc0.c
*/
struct platform_device s3c_device_fimc0 = {.name = "s3c-fimc",.id = 0,.num_resources = ARRAY_SIZE(s3c_fimc0_resource),.resource = s3c_fimc0_resource,
};
/*
dev-fimc1.c
*/
struct platform_device s3c_device_fimc1 = {.name = "s3c-fimc",.id = 1,.num_resources = ARRAY_SIZE(s3c_fimc1_resource),.resource = s3c_fimc1_resource,
};
/*
mach-smdk6410.c
*/
static struct platform_device *smdk6410_devices[] __initdata =
{&s3c_device_hsmmc0,&s3c_device_hsmmc1,&s3c_device_i2c0,&s3c_device_fb,&s3c_device_ohci,&s3c_device_usb_hsotg,&samsung_asoc_dma,&samsung_device_keypad,&gpio_button_device,&s3c_device_nand,
#ifdef CONFIG_DM9000&s3c_device_dm9000,
#endif&s3c64xx_device_ac97,&s3c_device_rtc,&s3c_device_ts,&s3c_device_fimc0,//FIMC 设备&s3c_device_fimc1,&s3c_device_wdt, &s3c_device_vpp,&s3c_device_mfc,&s3c_device_tvenc,&s3c_device_tvscaler,&s3c_device_rotator,&s3c_device_jpeg,&s3c_device_g2d,&s3c_device_g3d,&s3c64xx_device_spi0,&s3c64xx_device_spi1,
};
platform_add_devices(smdk6410_devices, ARRAY_SIZE(smdk6410_devices));
/*
platform总线的match函数将device和driver匹配之后,
会自动调用s3c_fimc_driver中指定的probe函数探测设备、
申请内存资源、申请中断等,
并将最终形成的platform_device类型数据保存到内核中,
供后续使用。
*/
/*
s3c_fimc_core.c
*/
static int s3c_fimc_probe(struct platform_device *pdev)
{struct s3c_platform_fimc *pdata;struct s3c_fimc_control *ctrl;struct clk *srclk;int ret;ctrl = s3c_fimc_register_controller(pdev);if (!ctrl) {err("cannot register fimc controller\n");goto err_fimc;}pdata = to_fimc_plat(&pdev->dev);if (pdata->cfg_gpio)pdata->cfg_gpio(pdev);/* fimc source clock */srclk = clk_get(&pdev->dev, pdata->srclk_name);if (IS_ERR(srclk)) {err("failed to get source clock of fimc\n");goto err_clk_io;}/* fimc clock */ctrl->clock = clk_get(&pdev->dev, pdata->clk_name);if (IS_ERR(ctrl->clock)) {err("failed to get fimc clock source\n");goto err_clk_io;}/* set parent clock */clk_enable(ctrl->clock);/* things to initialize once */if (ctrl->id == 0) {ret = s3c_fimc_init_global(pdev);if (ret)goto err_global;}/*注册 video4linux devices*/ret = video_register_device(ctrl->vd, VFL_TYPE_GRABBER, ctrl->id);if (ret) {err("cannot register video driver\n");goto err_video;}info("controller %d registered successfully\n", ctrl->id);return 0;
err_video:clk_put(s3c_fimc.cam_clock);
err_global:clk_disable(ctrl->clock);clk_put(ctrl->clock);
err_clk_io:s3c_fimc_unregister_controller(pdev);
err_fimc:return -EINVAL;}
static struct platform_driver s3c_fimc_driver = {.probe = s3c_fimc_probe,.remove = s3c_fimc_remove,.suspend = s3c_fimc_suspend,.resume = s3c_fimc_resume,.driver = {.name = "s3c-fimc",.owner = THIS_MODULE,},
};/*video_device结构体包括fops、ioctl_ops、release、name、vf_type几个成员变量,
其中,最重要的是file_operations类型的[fops] 和 v4l2_ioctl_ops类型的[ioctl_ops],
分别实现文件操作接口和V4L2接口。
*/
struct video_device s3c_fimc_video_device[S3C_FIMC_MAX_CTRLS] = {[0] = {.vfl_type = VID_TYPE_OVERLAY | VID_TYPE_CAPTURE | VID_TYPE_CLIPPING | VID_TYPE_SCALES,.fops = &s3c_fimc_fops,.ioctl_ops = &s3c_fimc_v4l2_ops,.release = s3c_fimc_vdev_release,.name = "sc3_video0",},[1] = {.vfl_type = VID_TYPE_OVERLAY | VID_TYPE_CAPTURE | VID_TYPE_CLIPPING | VID_TYPE_SCALES,.fops = &s3c_fimc_fops,.ioctl_ops = &s3c_fimc_v4l2_ops,.release = s3c_fimc_vdev_release,.name = "sc3_video1",},[2] = {.vfl_type = VID_TYPE_OVERLAY | VID_TYPE_CAPTURE | VID_TYPE_CLIPPING | VID_TYPE_SCALES,.fops = &s3c_fimc_fops,.ioctl_ops = &s3c_fimc_v4l2_ops,.release = s3c_fimc_vdev_release,.name = "sc3_video2",},
};struct video_device
{/* device ops */const struct v4l2_file_operations *fops;/* sysfs */struct device dev; /* v4l device */struct cdev *cdev; /* character device *//* Set either parent or v4l2_dev if your driver uses v4l2_device */struct device *parent; /* device parent */struct v4l2_device *v4l2_dev; /* v4l2_device parent *//* Control handler associated with this device node. May be NULL. */struct v4l2_ctrl_handler *ctrl_handler;/* device info */char name[32];int vfl_type;/* 'minor' is set to -1 if the registration failed */int minor;u16 num;/* added for TV */int type2;int users;/* use bitops to set/clear/test flags */unsigned long flags;/* attribute to differentiate multiple indices on one physical device */int index;/* V4L2 file handles */spinlock_t fh_lock; /* Lock for all v4l2_fhs */struct list_head fh_list; /* List of struct v4l2_fh */int debug; /* Activates debug level*//* Video standard vars */v4l2_std_id tvnorms; /* Supported tv norms */v4l2_std_id current_norm; /* Current tvnorm *//* callbacks */void (*release)(struct video_device *vdev);/* ioctl callbacks */const struct v4l2_ioctl_ops *ioctl_ops;
};
/*
s3c_fimc_core.c
FIMC驱动遵循V4L2接口标准,其file_operations接口定义如下:
当应用程序通过系统调用open()打开摄像头设备时,内核会最终找到s3c_fimc_open()
函数来打开摄像头。
应用程序通过read()获取图像数据,该函数通过copy_to_user()
将内核空间所申请缓冲区中图像数据拷贝到用户空间中开辟的图像数据区。
该函数没有充分利用FIMC接口提供的ping-pong缓冲区,按字进行拷贝(memcpy),
十分耗时。
mmap函数将内核空间中申请到的图像缓冲区映射到应用程序所在的用户空间,
这样,应用程序申请到的buffer将指向内核空间的图像缓冲区,应用程序可以
(不拷贝)直接对图像进行操作。该函数配合V4L2标准中的环形缓冲区队列,
节省了应用程序读取图像数据所消耗的时间。
*/
static const struct v4l2_file_operations s3c_fimc_fops = {
//static const struct file_operations s3c_fimc_fops = {.owner = THIS_MODULE,.open = s3c_fimc_open,.release = s3c_fimc_release,.unlocked_ioctl = video_ioctl2,.read = s3c_fimc_read,.write = s3c_fimc_write,.mmap = s3c_fimc_mmap,.poll = s3c_fimc_poll,
};
/*
s3c_fimc_v4l2.c
*//*************************应用程序通过ioctl接口使用这些函数,比如ioctl(fd,VIDIOC_S_FMT,&fmt)
用来设置图像格式,此时V4L2会将VIDIOC_S_FMT命令映射为s3c_fimc_v4l2_s_fmt_vid_cap()函数,
并将fmt指定的格式告知FIMC接口,FIMC会将OV9650传递过来的原始图像数据经过类型转换传递回应用程序。
s3c_fimc_v4l2_reqbufs()用于申请图像缓冲区,
该函数为应用程序在内核空间开辟ping-pong缓冲区。s3c_fimc_v4l2_qbuf()
函数将缓冲区组成环形缓冲队列,当应用程序需要调用图像数据时,使用s3c_fimc_v4l2_dqbuf()
使指定的缓冲区出队,缓冲区在出队期间,不会被新来的图像数据覆盖,
新到的图像数据会被传送到环形队列中指定缓冲区的下一个缓冲区。
由于FIMC控制器为P通道和C通道分别开辟了4个缓冲区,在内核初始化时已经申请到,
因此FIMC驱动中并不需要再重新申请。*************************/
const struct v4l2_ioctl_ops s3c_fimc_v4l2_ops = {.vidioc_querycap = s3c_fimc_v4l2_querycap,.vidioc_g_fbuf = s3c_fimc_v4l2_g_fbuf,.vidioc_s_fbuf = s3c_fimc_v4l2_s_fbuf,.vidioc_enum_fmt_vid_cap = s3c_fimc_v4l2_enum_fmt_vid_cap,.vidioc_g_fmt_vid_cap = s3c_fimc_v4l2_g_fmt_vid_cap,.vidioc_s_fmt_vid_cap = s3c_fimc_v4l2_s_fmt_vid_cap,.vidioc_try_fmt_vid_cap = s3c_fimc_v4l2_try_fmt_vid_cap,.vidioc_try_fmt_vid_overlay = s3c_fimc_v4l2_try_fmt_overlay,.vidioc_overlay = s3c_fimc_v4l2_overlay,.vidioc_g_ctrl = s3c_fimc_v4l2_g_ctrl,.vidioc_s_ctrl = s3c_fimc_v4l2_s_ctrl,.vidioc_streamon = s3c_fimc_v4l2_streamon,.vidioc_streamoff = s3c_fimc_v4l2_streamoff,.vidioc_g_input = s3c_fimc_v4l2_g_input,.vidioc_s_input = s3c_fimc_v4l2_s_input,.vidioc_g_output = s3c_fimc_v4l2_g_output,.vidioc_s_output = s3c_fimc_v4l2_s_output,.vidioc_enum_input = s3c_fimc_v4l2_enum_input,.vidioc_enum_output = s3c_fimc_v4l2_enum_output,.vidioc_reqbufs = s3c_fimc_v4l2_reqbufs,.vidioc_querybuf = s3c_fimc_v4l2_querybuf,.vidioc_qbuf = s3c_fimc_v4l2_qbuf,.vidioc_dqbuf = s3c_fimc_v4l2_dqbuf,.vidioc_cropcap = s3c_fimc_v4l2_cropcap,.vidioc_g_crop = s3c_fimc_v4l2_g_crop,.vidioc_s_crop = s3c_fimc_v4l2_s_crop,.vidioc_s_parm = s3c_fimc_v4l2_s_parm,
};
在内核中加入打印。追踪ok6410 官方camera 测试程序运行过程。
--s3c_fimc_probe
---[CAM]s3c_fimc_register_controller.id=0
--[CAM]s3c_fimc_set_active_camera,id=0
s3c_fimc_init_global s3c_fimc.cam_clock=-1065304896
--video_register_device
device: 'video0': device_add
s3c-fimc: controller 0 registered successfully
driver: 's3c-fimc.0': driver_bound: bound to device 's3c-fimc'
bus: 'platform': really_probe: bound device s3c-fimc.0 to driver s3c-fimc
bus: 'platform': driver_probe_device: matched device s3c-fimc.1 with driver s3c-fimc
bus: 'platform': really_probe: probing driver s3c-fimc with device s3c-fimc.1
--s3c_fimc_probe
---[CAM]s3c_fimc_register_controller.id=1
--[CAM]s3c_fimc_set_active_camera,id=0
--video_register_device
device: 'video1': device_add
s3c-fimc: controller 1 registered successfully
driver: 's3c-fimc.1': driver_bound: bound to device 's3c-fimc'
bus: 'platform': really_probe: bound device s3c-fimc.1 to driver s3c-fimc
s3c-fimc:
--info ov965x_init
bus: 'i2c': add driver ov965x
bus: 'i2c': driver_probe_device: matched device 0-0030 with driver ov965x
bus: 'i2c': really_probe: probing driver ov965x with device 0-0030
s3c-fimc:
--ov965x_probe
[CAM]s3c_fimc_register_camera,cam->id=0
s3c_fimc.cam_clock = c080bcc0
parent clock for camera: 266.000 MHz, divisor: 11
[CAM]RESET CAM.[CAM]Reset and init reg!1cam->client=cc460c00
[CAM]Reset and init reg!1
[CAM]Reset and init reg!2
--[CAM]s3c_fimc_init_camera
[CAM]I2C_CAM_INIT.
--[CAM]s3c_fimc_init_camera
--[CAM]s3c_fimc_init_camera
[CAM]Reset and init reg!3
s3c-fimc: //OV9650 寄存器设置
--reg 12 80
--reg ff 0a
--reg 6a 3e
--reg 3b 09
--reg 13 8f
--reg 01 80
--reg 02 80
--reg 00 00
--reg 10 00
--reg 35 91
--reg 0e a0
--reg 1e 34
--reg a8 80
--reg 04 00
--reg 0c 04
--reg 0d 80
--reg 11 81
--reg 12 40
--reg 37 91
--reg 38 12
--reg 39 43
--reg 18 c6
--reg 17 26
--reg 32 ad
--reg 03 00
--reg 1a 3d
--reg 19 01
--reg 3f a6
--reg 14 2e
--reg 15 10
--reg 41 02
--reg 42 08
--reg 1b 00
--reg 16 06
--reg 33 e2
--reg 34 bf
--reg 96 04
-reg 3a 00
--reg 8e 00
--reg 3c 77
--reg 8b 06
--reg 94 88
--reg 95 88
--reg 40 c1
--reg 29 3f
--reg 0f 42
--reg 3d 92
--reg 69 40
--reg 5c b9
--reg 5d 96
--reg 5e 10
--reg 59 c0
--reg 5a af
--reg 5b 55
-reg 43 f0
--reg 44 10
--reg 45 68
--reg 46 96
--reg 47 60
--reg 48 80
--reg 5f e0
--reg 60 8c
--reg 61 20
--reg a5 d9
--reg a4 74
--reg 8d 02
--reg 4f 3a
--reg 50 3d
--reg 51 03
--reg 52 12
--reg 53 26
--reg 54 36
--reg 55 45
--reg 56 40
--reg 57 40
--reg 58 0d
--reg 8c 23
--reg 3e 02
--reg a9 b8
--reg aa 92
--reg ab 0a
--reg 8f df
--reg 90 00
--reg 91 00
--reg 9f 00
--reg a0 00
--reg 3a 01
--reg 24 70
--reg 25 64
--reg 26 c3
--reg 2a 00
--reg 2b 00
--reg 6c 40
--reg 6d 30
--reg 6e 4b
--reg 6f 60
--reg 70 70
--reg 71 70
--reg 72 70
--reg 73 70
--reg 74 60
--reg 75 60
--reg 76 50
--reg 77 48
--reg 78 3a
--reg 79 2e
--reg 7a 28
--reg 7b 22
--reg 7c 04
--reg 7d 07
-reg 7e 10
--reg 7f 28
-reg 80 36
--reg 81 44
-reg 82 52
--reg 83 60
--reg 84 6c
--reg 85 78
--reg 86 8c
--reg 87 9e
--reg 88 bb
--reg 89 d2
--reg 8a e6
driver: '0-0030': driver_bound: bound to device 'ov965x'
bus: 'i2c': really_probe: bound device 0-0030 to driver ov965x
Please press Enter to activate this console. device: 'vcs2': device_add
device: 'vcsa2': device_add
device: 'vcs4': device_add
device: 'vcsa4': device_add
device: 'vcs3': device_add
device: 'vcsa3': device_add
touch...
[root@FORLINX6410]#
[root@FORLINX6410]# ls
adctest keytest sbin
at24c08test ledtest sdcard
bin lib spitest
camera linuxrc sys
dev mnt tmp
duhuitest mpu6050 uarttest
etc nfs.txt udisk
fork opt udp
gpio ov9650 usr
iictest proc var
key_workqueue_test root w25q128
[root@FORLINX6410]# cd camera
[root@FORLINX6410]# ls
422jpeg.h Makefile testcamera v4l2.c videodev.h videodev2.h
[root@FORLINX6410]# ./testcamera
//运行testcamera,开始显示图片
Start Main ---v4l2_open id=0
--v4l2 get
--[CAM]s3c_fimc_open.id=0
--[CAM]ctrl->in_cam->width=640
s3c_fimc_v4l2_s_fmt_vid_cap filp=cbcd4f00,fh=c08bbed0,f=cbccf000
s3c_fimc_alloc_output_memory width 140 height f0 format 0 buf_size = 26000
s3c_fimc_v4l2_streamon is called
--[CAM]s3c_fimc_init_camera
--v4l2 read
---s3c_fimc_read
already open the devicise codec
Before openning FB
VIDIOC_S_FMT is c0cc5605
VIDIOC_STREAMON is 40045612
start to get pic 0
display 153600
--v4l2 read
---s3c_fimc_read
display 153600
--v4l2 read
---s3c_fimc_read
display 153600
OK6410 V4L2 分析相关推荐
- 基于全志A64平台v4l2驱动分析
纪念再一次使用这里,刚好开通好博客,写下近年来的第一篇. 最近要做一个全志A64平台的vfe驱动培训,组织了下v4l2与vfe驱动分析.这里记录下. 全志A64芯片csi部份不自带isp(其实是有带一 ...
- DM6446开发攻略:V4L2视频驱动和应用分析
针对DAVINCI DM6446平台,网络上也有很多网友写了V4L2的驱动,但只是解析Montavistalinux-2.6.10 V4L2的原理.结构和函数,深度不够.本文决定把Montavista ...
- v4l2驱动框架_【干货分享】Xilinx Linux V4L2视频管道(Video Pipeline)驱动程序分析...
作者:付汉杰,hankf@xilinx.com, 文章转载自:赛灵思中文社区论坛 概述 Xilinx提供了完整的V4L2的驱动程序,Xilinx V4L2 driver.处于最顶层的驱动程序是V4L2 ...
- 基于OK6410开发板Uboot源码简单分析
2018-04-07 OK6410开发板是基于三星S3C6410芯片设计的一款开发板,资源比较丰富,可是想要使用这些资源就需要编写相应的启动引导程序,即BootLoader.当然,想要自己凭空写出Bo ...
- V4L2 驱动层分析
一.Camera V4L2 驱动层分析 Linux系统中视频输入设备主要包括以下四个部分: 1.字符设备驱动:V4L2本身就是一个字符设备,具有字符设备所有的特性,暴露接口给用户空间: 2.V4L2驱 ...
- linux v4l2架构分析之v4l2_ctrl_handler初始化及添加v4l2_ctrl的过程分析
本文根据原代码分析v4l2的handler初始化以及添加ctrl的过程,会涉及v4l2_ctrl_handler.v4l2_ctrl.v4l2_ctrl_ref结构体的分析,以及介绍v4l2_ctrl ...
- v4l2架构专题模块handler分析 -- handler ctrl的注册2
Linux v4l2架构学习总链接 上一篇文章中忽略了ctrl class,这里补上 static int handler_new_ref(struct v4l2_ctrl_handler *hdl, ...
- v4l2架构专题模块handler分析 --- handler的初始化及handler ctrl注册
Linux v4l2架构学习总链接 handler初始化代码调用如下: v4l2_ctrl_handler_init(handler, 9); 对应源码: #define v4l2_ctrl_hand ...
- 基于Ti Omap3x 分析v4l2架构
1 概述 本文将基于Ti Omap3x这个典型的实例来分析v4l2在具体media场景中的应用.通过分析app层的行为以及driver层的实现来对整个多媒体框架有一个大概的认识.内容主要包括主要包括v ...
最新文章
- ORACLE选择hint,ORACLE中的的HINT详解
- MaterialImageView
- 事务管理最佳实践全面解析
- 一步一图一代码之排序二叉树
- 033_NavMenu导航菜单
- android 跑分软件,跑分软件安兔兔公布了6月份Android手机性能榜TOP10
- Python自动化开发 - RESTful API
- overfitting(过度拟合)的概念
- Mac OS X终端的常用操作命令(UNIX指令)
- 【Linux系统编程学习】C库IO函数与系统IO函数的关系
- [Ext JS6] Grid 某些行不允许删除和选择的实现
- tensorflow Image 解码函数
- C - The Smallest String Concatenation CodeForces - 632C(按字典序列排列 )string或者数组
- 用nunit时,老是搞忘英文,在这里记录一下,方便到处查阅
- Mysql中间件代理 Atlas
- uniapp封装request
- 智慧监狱(所)设计方案
- 微信小程序头像怎么改变形状_微信小程序 open-data更改样式 open-data 显示头像 圆形...
- 拍照解数独之识别数独图片
- 76位健康专家共荐防病36计
热门文章
- 计算机通信中应用的调制解调与无线电通信,计算机通讯中的一对搭档——调制解调器和通讯软件...
- 办公室装修的五要四不要
- 深入详解python高级特性——函数柯里化(Currying)与反柯里化
- 太上玄门日诵晚课仙经
- RF信号下采样/矩阵下采样(附python实现代码)
- nn.Linear()函数详解及代码使用
- Swin-Unet跑自己的数据集(Transformer用于语义分割)
- 中科院大学计算机科学与技术王伟强,王伟强 - 中国科学院大学 - 计算机科学与技术学院...
- 努比亚android最高版本,努比亚Z11安卓7.1固件开发版下载地址:新增压力按键等功能...
- 计算机系统文件夹打不开,电脑系统的文件夹打不开可以试下这两个办法