Skip to main content

添加新的Camera

1 添加流程

1.1 添加新的sensor模块

​ 在module_driver/devices/camera/x1600下添加新的sensor文件夹, 其中包含.c文件、Makefile. (可参考同级目录下君正已经添加的sensor代码)

1.2 实现接口

sensor_ctrl_ops.power_on()                       // 主要实现sensor的上电功能,包括时钟的使能
sensor_ctrl_ops.power_off() // 实现sensor关电功能,关时钟
sensor_ctrl_ops.stream_on() // 实现sensor开流
sensor_ctrl_ops.stream_off() // 实现sensor关流
i2c_driver.probe // i2c设备驱动的probe函数,主要实现申请相关gpio, 以及调用camera_register_sensor注册sensor
i2c_driver.remove // i2c设备驱动的remove函数,主要实现释放相关gpio, 以及调用camera_unregister_sensor注销sensor
module_init() //驱动的入口函数,主要实现i2c设备驱动的添加以及i2c设备的注册
module_exit() //驱动的出口函数,主要实现i2c设备驱动的删除以及i2c设备的注销

1.3 配置Sensor结构体

在新添加的sensor.c代码中定义一个struct sensor_attr 类型的变量, 并进行配置. 该结构体类型的相关说明在第2章

1.4 注册Sensor

调用camera_register_sensor()函数对新添加的Sensor进行注册, 并将第一步配置的结构体变量作为实参传入. 注册注销函数的相关说明在第3章

1.5 将sensor.c文件加入IConfig配置界面并且加入编译

使用IConfigTool对x1600的Camera驱动进行配置, 配置方法在第4章

2 配置Sensor结构体

2.1 包含头文件

#include "soc/x1600/camera/camera_sensor.h"

2.2 Sensor结构体说明

摄像头配置结构体
struct sensor_attr {
char *device_name; //摄像头设备名称
unsigned int cbus_addr; //控制总线设备地址(SPI or IIC)
struct camera_info info; //配置sensor信息

sensor_data_dma_mode dma_mode; //控制器DMA输出格式选择
sensor_data_bus_tye dbus_type; //数据总线类型
union {
struct dvp_bus dvp; //配置dvp接口信息
struct mipi_csi_bus mipi; //配置mipi接口信息
};

struct sensor_info sensor_info; //sensor基本属性信息
struct sensor_ctrl_ops ops; //sensor控制配置结构体
};

2.3 结构体成员详解

摄像头信息结构体

struct camera_info {
char name[64]; //摄像头名称
unsigned int width; //每行像素数
unsigned int height; //行数
unsigned int fps; //camera 帧率
camera_pixel_fmt data_fmt; //camera 帧数据格式

unsigned int line_length; //一行的⻓度,单位字节
unsigned int frame_size; //一帧数据经过对⻬之前的大小
unsigned int frame_nums; //帧缓冲总数
unsigned long phys_mem; //帧缓冲的物理基地址
void *mapped_mem; //mmap 后的帧缓冲基地址
unsigned int frame_align_size; //帧对⻬大小
};

其中 camera_pixel_fmt 是枚举型的像素格式集合,其定义位于 /module_driver/include/camera_pixel_format.h

/* 和X1021/X1520/X1830/X2000不同,该类型没有对应寄存器的配置,在frame的DMA的description中指定是否输出为Y8*/

typedef enum {
SENSOR_DATA_DMA_MODE_RAW = 0, /* 按输入格式输出 */
SENSOR_DATA_DMA_MODE_GREY = 100, /* 自定义 */
} sensor_data_dma_mode;
DVP接口信息配置
struct dvp_bus {
dvp_sample_polarity pclk_polarity;
dvp_sync_polarity hsync_polarity;
dvp_sync_polarity vsync_polarity;
dvp_img_scan_mode img_scan_mode;
};
MIPI接口信息配置
struct mipi_csi_bus {
int lanes;
unsigned long clk;
};
sensor基本属性信息
struct sensor_info {
void *private_init_setting; // sensor寄存器配置表

/* The following attributes are determined by private_init_setting */
int width; // sensor输出图像宽
int height; // sensor输出图像高
sensor_pixel_fmt fmt; // sensor输出格式

unsigned int fps; /* fps = Numerator / denominator; [31:16]:Numerator [15:0]:denominator */
};

3 注册Sensor

3.1 注册注销函数说明

int camera_register_sensor(struct sensor_attr *sensor)

功能:注册一个sensor到camera驱动
参数:sensor // 将第2章配置的sensor结构体变量传入

返回值:0 注册成功 非0 注册失败

void camera_unregister_sensor(struct sensor_attr *sensor)

功能:注销sensor
参数:sensor // 将第2章配置的sensor结构体变量传入

返回值:无

3.2 注册注销实例

可以参考下面君正添加的sc031_dvp sensor 是如何注册sensor的

static int sc031_probe(struct i2c_client *client,const struct i2c_device_id *id)
{
int ret;
ret = init_gpio();
if (ret)
return ret;
ret = camera_register_sensor(&sc031_sensor_attr);
if (ret) {
deinit_gpio();
return ret;
}

return 0;
}

static int sc031_remove(struct i2c_client *client)
{
camera_unregister_sensor(&sc031_sensor_attr);
deinit_gpio();
return 0;
}

4 加入IConfig配置界面以及加入编译

在module_driver/package/devices/camera/x1600目录下, 添加新的camera sensor模块文件夹, 文件夹包含Config.in文件、.mk文件

4.1 加入IConfig配置界面

Config.in文件可参考以下sc031_dvp sensor的Config.in实例,也可借鉴其他目录的Config.in文件

menuconfig MD_X1600_SENSOR_SC031_DVP
bool "sensor sc031 (dvp,raw8)"
select MD_X1600_CAMERA
depends on MD_SOC_X1600_BASE

config MD_X1600_SC031_DVP_GPIO_RESET
string "gpio reset(sensor 复位脚)"
choice from SOC_GPIO_PINS
default -1

config MD_X1600_SC031_DVP_GPIO_PWDN
string "gpio pwdn(sensor 电源控制引脚, 低有效)"
choice from SOC_GPIO_PINS
default -1

config MD_X1600_SC031_DVP_GPIO_POWER
string "gpio power(sensor 电源控制引脚, 高有效)"
choice from SOC_GPIO_PINS
default -1

config MD_X1600_SC031_DVP_I2C_BUSNUM
int "i2c bus num (sensor 挂接的i2c总线号)"
default -1

endmenu

在module_driver/package/device/camera/Config.in文件末尾添加:

source package/devices/camera/x1600/"添加的camera模块文件夹"/Config.in

以sc031_dvp为例: source package/devices/camera/x1600/sc031_dvp/Config.in

4.2 加入编译

.mk文件可参考以下sc031_dvp sensor的sc031_dvp.mk实例

#-------------------------------------------------------
package_name = sensor_sc031_dvp
package_depends = utils soc_camera
package_module_src = devices/camera/x1600/sc031_dvp
package_make_hook =
package_init_hook =
package_finalize_hook = sensor_sc031_dvp_finalize_hook
package_clean_hook =
#-------------------------------------------------------

shell_sensor_init_file = output/sensor_sc031_dvp.sh


define sensor_sc031_dvp_finalize_hook
$(if $(MD_X1600_SENSOR_SC031_DVP), $(Q)cp devices/camera/x1600/sc031_dvp/sensor_sc031_dvp.ko output/)
$(if $(MD_X1600_SENSOR_SC031_DVP), $(Q)echo -n 'insmod sensor_sc031_dvp.ko' > $(shell_sensor_init_file))
$(if $(MD_X1600_SENSOR_SC031_DVP), $(Q)echo -n ' power_gpio=$(MD_X1600_SC031_DVP_GPIO_POWER)' >> $(shell_sensor_init_file))
$(if $(MD_X1600_SENSOR_SC031_DVP), $(Q)echo -n ' reset_gpio=$(MD_X1600_SC031_DVP_GPIO_RESET)' >> $(shell_sensor_init_file))
$(if $(MD_X1600_SENSOR_SC031_DVP), $(Q)echo -n ' pwdn_gpio=$(MD_X1600_SC031_DVP_GPIO_PWDN)' >> $(shell_sensor_init_file))
$(if $(MD_X1600_SENSOR_SC031_DVP), $(Q)echo -n ' i2c_bus_num=$(MD_X1600_SC031_DVP_I2C_BUSNUM)' >> $(shell_sensor_init_file))

$(Q)echo >> $(shell_sensor_init_file)

endef

在module_driver/package/device/camera/camera.mk文件末尾添加

package-$("新添加sensor模块对应的宏控") += package/devices/camera/x1600/"新添加sensor模块文件夹"/".mk文件"

以sc031_dvp为例:package-$(MD_X1600_SENSOR_SC031_DVP) += package/devices/camera/x1600/sc031_dvp/sc031_dvp.mk