-
-
- camera内核驱动框架图
-
上图摘自RKDocs目录中文档Camera_for_RockChipSDK参考说明_v4.1.pdf
图中rk29需改成rk30, 即将添加的camera sensor,寄存器是放在hardware/rockchip/camera/中,不需要图中的ov2655.c部分。
流程:
v4l2-xxx --> soc_camera --> rk30_camera_oneframe.c --> generic_sensor.c --> xxx_sensor.c
Rockchip为sonsor做了个公用驱动generic_sensor.c,留出公共接口给不同的sonsor使用。
-
-
- host驱动
-
Camera Host驱动主要实现如下:
1、videobuf 回调以及控制;
2、VIP Controller 设置;
3、Camera 休眠唤醒;
4、IPP scale 控制;
-
-
-
- videobuf 回调以及控制
-
-
由参考文档得知,使用videobuf 机制必须实现videobuf_queue_ops 结构体中的4 个
回调函数。驱动对videobuf 的控制流程如下:
-
-
-
- VIP Controller 设置
-
-
VIP 控制器的设置主要涉及:VIP 各工作时钟控制、VIP 输出时钟(Sensor 工作时钟)
输出、VIP 采集时序极性控制;
以上控制主要集中在以下函数中:
rk_camera_set_bus_param;
rk_camera_setup_format;
rk_camera_set_fmt;
-
-
-
- Camera 休眠唤醒
-
-
VIP 控制器在休眠唤醒中需要寄存器进行备份设置,在唤醒时将备份的寄存器值重新恢
复到寄存器中。
-
-
-
- IPP Scale 控制
-
-
Sensor 能够输出的分辨率不一定能够完全满足用户的需求,这个时候就必须对sensor
的输出图像进行scale。
在使用到IPP scale 时,vip 采集的buf就不能是用户提供的videobuf,vip 驱动必须
获取一段buf 作为采集用,采集结束后将该段buf 中的数据利用IPP 进行scale 处理,同时
将输出到用户指定的videobuf 中,最后唤醒因获取该videobuf 而睡眠的进程。IPP 处理必
须在内核线程中进行处理。
-
-
-
- 代码分析
-
-
查看概述章节,可知设备注册代码为rk30_camera.c
- static int rk_register_camera_devices(void)
- {
- ……
- rk_cif_sensor_init();
- new_camera = rk_camera_platform_data.register_dev_new;
- ……
- #if RK_SUPPORT_CIF0
- if (host_registered_0) {
- platform_device_register(&rk_device_camera_host_0);//host_0 has sensor
- } //host_device_register
- #endif
- #if RK_SUPPORT_CIF1
- if (host_registered_1) {
- platform_device_register(&rk_device_camera_host_1);//host_1 has sensor
- } //host_device_register
- #endif
- if (rk_camera_platform_data.sensor_register)
- (rk_camera_platform_data.sensor_register)(); //call rk_sensor_register()
- return 0;
- }
rk_cif_sensor_init做了一些初始化工作, 开始进入函数platform_device_register
- static int rk_cif_sensor_init(void)
- {
- debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()/n", __FILE__, __LINE__,__FUNCTION__);
- platform_driver_register(&rk_cif_driver);
- platform_driver_register(&rk_sensor_driver);
- return 0;
- }
- static struct platform_driver rk_cif_driver =
- {
- .driver = {
- .name = RK_CIF_NAME,
- .owner = THIS_MODULE,
- .of_match_table = of_match_ptr(of_match_cif),
- },
- .probe = rk_dts_cif_probe,
- .remove = rk_dts_cif_remove,
- };
- static struct platform_driver rk_sensor_driver =
- {
- .driver = {
- .name = RK_SENSOR_NAME,
- .owner = THIS_MODULE,
- .of_match_table = of_match_ptr(of_match_sensor),
- },
- .probe = rk_dts_sensor_probe,
- .remove = rk_dts_sensor_remove,
- };
根据cif, sensor设备树中内容,匹配到相关初始化值,注册平台驱动
- struct platform_device rk_device_camera_host_0 = {
- .name = RK29_CAM_DRV_NAME,
- .id = RK_CAM_PLATFORM_DEV_ID_0, /* This is used to put cameras on this interface*/
- .num_resources= 2,
- .resource = rk_camera_resource_host_0,
- .dev = {
- .dma_mask = &rockchip_device_camera_dmamask,
- .coherent_dma_mask = 0xffffffffUL,
- .platform_data = &rk_camera_platform_data,
- }
- };
#define RK29_CAM_DRV_NAME "rk312x-camera"
rk30_camera_oneframe.c通过这个名与之匹配。
- static struct platform_driver rk_camera_driver =
- {
- .driver = {
- .name = RK29_CAM_DRV_NAME, /*host */
- },
- .probe = rk_camera_probe,
- .remove = (rk_camera_remove),
- };
- static int rk_camera_init_async(void *unused)
- {
- debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()\n", __FILE__, __LINE__,__FUNCTION__);
- platform_driver_register(&rk_camera_driver);
- return 0;
- }
- static int __init rk_camera_init(void)
- {
- debug_printk( "/$$$$$$$$$$$$$$$$$$$$$$//n Here I am: %s:%i-------%s()\n", __FILE__, __LINE__,__FUNCTION__);
- kthread_run(rk_camera_init_async, NULL, "rk_camera_init");
- return 0;
- }
- static struct soc_camera_host_ops rk_soc_camera_host_ops =
- {
- .owner = THIS_MODULE,
- .add = rk_camera_add_device,
- .remove = rk_camera_remove_device,
- .suspend = rk_camera_suspend,
- .resume = rk_camera_resume,
- .enum_frameinervals = rk_camera_enum_frameintervals,
- .cropcap = rk_camera_cropcap,
- .set_crop = rk_camera_set_crop,
- .get_crop = rk_camera_get_crop,
- .get_formats = rk_camera_get_formats,
- .put_formats = rk_camera_put_formats,
- .set_fmt = rk_camera_set_fmt,
- .try_fmt = rk_camera_try_fmt,
- .init_videobuf = rk_camera_init_videobuf,
- .reqbufs = rk_camera_reqbufs,
- .poll = rk_camera_poll,
- .querycap = rk_camera_querycap,
- .set_bus_param = rk_camera_set_bus_param,
- .s_stream = rk_camera_s_stream, /* [email protected] : Add stream control for host */
- .set_ctrl = rk_camera_set_ctrl,
- .controls = rk_camera_controls,
- .num_controls = ARRAY_SIZE(rk_camera_controls)
- };
上面列出了一些功能,最后提供给用户空间使用。
-
-
- kernel层方式添加sensor
-
查看概述章节,用gc0329.c为例.
需要取消hal层添加摄像头的功能,代码位置:
hardware/rockchip/camera/CameraHal_board_xml_parse.cpp
//register i2c device
int err = RegisterSensorDevice(pCamInfo);
make menuconfig 中加入gc0329, 也加入设备树内容。
-
-
-
- 设备树内容
-
-
kernel/arch/arm/boot/dts/rk3288-cif-sensor.dtsi
- #include "rk3288.dtsi"
- #include "rk3288-pinctrl.dtsi"
- #include "../../mach-rockchip/rk_camera_sensor_info.h"
- /{
- rk3288_cif_sensor: rk3288_cif_sensor{
- compatible = "rockchip,sensor";
- status = "disabled";
- gc0329{
- is_front = <0>;
- rockchip,power = <&gpio0 GPIO_C1 GPIO_ACTIVE_HIGH>;
- //rockchip,power_pmu_name1 = "rk818_ldo4";
- //rockchip,power_pmu_voltage1 = <2800000>;
- //rockchip,power_pmu_name2 = "rk818_ldo8";
- //rockchip,power_pmu_voltage2 = <1800000>;
- rockchip,powerdown = <&gpio2 GPIO_B4 GPIO_ACTIVE_HIGH>;
- //rockchip,powerdown_pmu = "";
- //rockchip,powerdown_pmu_voltage = <3000000>;
- pwdn_active = <gc0329_PWRDN_ACTIVE>;
- pwr_active = <PWR_ACTIVE_HIGH>;
- mir = <0>;
- flash_attach = <1>;
- //rockchip,flash = <>;
- flash_active = <1>;
- resolution = <gc0329_FULL_RESOLUTION>;
- powerup_sequence = <gc0329_PWRSEQ>;
- orientation = <0>;
- i2c_add = <gc0329_I2C_ADDR>;
- i2c_rata = <100000>;
- i2c_chl = <3>;
- cif_chl = <0>;
- mclk_rate = <24>;
- };
- };
- };
gc0329_I2C_ADDR 在kernel/arch/arm/mach-rockchip/rk_camera_sensor_info.h
-
-
-
- 代码分析
-
-
kernel/drivers/media/video/gc0309.c
gc0309的实现。结合generic_sensor.c, 实现不同于其它sensor的代码。
- #define SENSOR_NAME RK29_CAM_SENSOR_GC0329
- #define SENSOR_V4L2_IDENT V4L2_IDENT_GC0329
- #define SENSOR_ID 0xc0
- #define SENSOR_BUS_PARAM (V4L2_MBUS_MASTER |\
- V4L2_MBUS_PCLK_SAMPLE_RISING|V4L2_MBUS_HSYNC_ACTIVE_HIGH| V4L2_MBUS_VSYNC_ACTIVE_HIGH|\
- V4L2_MBUS_DATA_ACTIVE_HIGH |SOCAM_MCLK_24MHZ)
重要的宏定义
- sensor_init_parameters_default_code();
- sensor_v4l2_struct_initialization();
- sensor_probe_default_code();
- sensor_remove_default_code();
- sensor_driver_default_module_code();
这部分在generic_sensor中实现。
kernel/drivers/media/video/generic_sensor.h
- extern int generic_sensor_softreset(struct i2c_client *client, struct rk_sensor_reg *series);
- extern int generic_sensor_check_id(struct i2c_client *client, struct rk_sensor_reg *series);
- extern int sensor_write_reg2val1(struct i2c_client *client, u16 reg,u8 val);
- extern int sensor_write_reg2val2(struct i2c_client *client, u16 reg,u16 val);
- extern int sensor_write_reg1val1(struct i2c_client *client, u8 reg,u8 val);
- extern int sensor_write_reg1val2(struct i2c_client *client, u8 reg,u16 val);
- extern int sensor_read_reg1val1(struct i2c_client *client, u8 reg,u8* val);
- extern int sensor_read_reg2val1(struct i2c_client *client, u16 reg,u8* val);
- extern int sensor_read_reg1val2(struct i2c_client *client, u8 reg,u16* val);
- extern int sensor_read_reg2val2(struct i2c_client *client, u16 reg,u16* val);
- extern int generic_sensor_write(struct i2c_client *client,struct rk_sensor_reg* sensor_reg);
- extern int generic_sensor_read(struct i2c_client *client, struct rk_sensor_reg* sensor_reg);
- extern int generic_sensor_write_array(struct i2c_client *client, struct rk_sensor_reg *regarray);
- extern int generic_sensor_get_max_min_res(struct rk_sensor_sequence* res_array,int num,struct rk_sensor_seq_info * max_real_res
- ,struct rk_sensor_seq_info * max_res,struct rk_sensor_seq_info *min_res);
- extern int generic_sensor_init(struct v4l2_subdev *sd, u32 val);
- extern int generic_sensor_enum_frameintervals(struct v4l2_subdev *sd, struct v4l2_frmivalenum *fival);
- extern int generic_sensor_try_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf);
- extern int generic_sensor_ioctrl(struct soc_camera_device *icd,enum rk29sensor_power_cmd cmd, int on);
- extern unsigned long generic_sensor_query_bus_param(struct soc_camera_device *icd);
- extern int generic_sensor_g_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf);
- extern int generic_sensor_set_bus_param(struct soc_camera_device *icd,unsigned long flags);
- extern int generic_sensor_g_control(struct v4l2_subdev *sd, struct v4l2_control *ctrl);
- extern int generic_sensor_s_control(struct v4l2_subdev *sd, struct v4l2_control *ctrl);
- extern int generic_sensor_g_ext_control(struct soc_camera_device *icd , struct v4l2_ext_control *ext_ctrl);
- extern int generic_sensor_s_ext_control(struct soc_camera_device *icd, struct v4l2_ext_control *ext_ctrl);
- extern int generic_sensor_g_ext_controls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ext_ctrl);
- extern int generic_sensor_s_ext_controls(struct v4l2_subdev *sd, struct v4l2_ext_controls *ext_ctrl);
- extern long generic_sensor_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg);
- extern int generic_sensor_s_power(struct v4l2_subdev *sd, int on);/*yzm*/
- extern int generic_sensor_enum_fmt(struct v4l2_subdev *sd, unsigned int index,enum v4l2_mbus_pixelcode *code);
- extern int generic_sensor_s_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf);
- extern int generic_sensor_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *id);
- extern int generic_sensor_af_workqueue_set(struct soc_camera_device *icd, enum rk_sensor_focus_wq_cmd cmd, int var, bool wait);
- extern int generic_sensor_s_stream(struct v4l2_subdev *sd, int enable);
- extern int generic_sensor_writebuf(struct i2c_client *client, char *buf, int buf_size);
- extern int generic_sensor_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *cc);
- extern int generic_sensor_enum_framesizes(struct v4l2_subdev *sd, struct v4l2_frmsizeenum *fsize);
一些功能函数。