
Release history
| Date | Revision | Change |
|---|---|---|
| 2024.09.10 | 1.0 | First release |
简介
本文档主要针对添加一个新型号 camera 到 kernel-x.x 标准内核平台进行说明。
camera 适配前准备
硬件原理图
自定义的主板适配,需要主板原理图,平台公板适配,需要模组转接板原理图以及对应公板的原理图。
init setting
适配前需确定camera setting,包含信息有:register init list,mclk,输出 raw 图位宽,输出格式,mipi clk/lanes 或 dvp vsync/hsync/pclk,分辨率,i2c 地址。
配置设备树
适配新型号camera时,可以仿照已有型号配置camera.dtsi,然后在板级.dts中include对应的 dtsi。
设备树所在位置: halley6: module_drivers/dts/halley6_cameras panda : module_drivers/dts/panda_cameras
mipi camera 配置
在halley6_cameras/RD_X1600_HALLEY6_MIPI_CAMERA.dtsi中,对cim控制器进行如下配置:其中,data-lanes字段根据接入的mipi sensor的data lane数量填充,例如:接入2 lane mipi sensor,data-lanes需填充两个参数,data-lanes = <0 1>,接入4 lane mipi sensor,data-lanes需填充四个参数,data-lanes = <0 1 3 4>;clk-lanes字段根据接入的mipi sensor的clock lane数量填充,例如:mipi sensor 连接一根clk lane,clk-lanes需填充一个参数,clk-lanes = <2>。
&cim {
status = "okay";
port {
cim_0: endpoint@0 {
remote-endpoint = <&sc031gs_ep0>;
data-lanes = <0 1>;
clk-lanes = <2>;
};
};
};在halley6_cameras/RD_X1600_HALLEY6_MIPI_CAMERA.dtsi中,对camera sensor进行如下配置:根据原理图确定i2c,例如:i2c0_pa;根据camera datasheet确定i2c address,例如:0x30;确定mclk,reset,pwdn,vcc等gpio有效方式以及上电时序。
&i2c0 {
status = "okay";
clock-frequency = <100000>;
timeout = <1000>;
pinctrl-names = "default";
pinctrl-0 = <&i2c0_pa>;
sc031gs_0:sc031gs@30 {
status = "okay";
compatible = "sc031gs";
reg = <0x30>;
pinctrl-names = "default";
pinctrl-0 = <&cim_mipi_mclk_pc>;
resetb-gpios = <&gpa 30 GPIO_ACTIVE_LOW INGENIC_GPIO_NOBIAS>;
vcc-en-gpios = <&gpb 12 GPIO_ACTIVE_HIGH INGENIC_GPIO_NOBIAS>;
port {
sc031gs_ep0:endpoint {
remote-endpoint = <&cim_0>;
};
};
};
};dvp camera 配置
在halley6_cameras/RD_X1600_HALLEY6_DVP_CAMERA.dtsi中,对cim控制器进行如下配置:根据datasheet 或波形测量确定hsync,vsync,pclk,data有效方式。
&cim {
status = "okay";
port {
cim_0: endpoint@0 {
remote-endpoint = <&sc031gs_ep0>;
bus-width = <8>;
data-shift = <0>;
bus-type = <5>;
hsync-active = <1>;
vsync-active = <0>;
data-active = <1>;
pclk-sample = <1>;
};
};
};在halley6_cameras/RD_X1600_HALLEY6_DVP_CAMERA.dtsi中,对camera sensor进行如下配置:
&i2c0 {
status = "okay";
clock-frequency = <100000>;
timeout = <1000>;
pinctrl-names = "default";
pinctrl-0 = <&i2c0_pa>;
sc031gs_0:sc031gs@30 {
status = "okay";
compatible = "sc031gs";
reg = <0x30>;
pinctrl-names = "default";
pinctrl-0 = <&cim_mipi_mclk_pc>, <&cim_pa>;
resetb-gpios = <&gpa 30 GPIO_ACTIVE_HIGH INGENIC_GPIO_NOBIAS>;
vcc-en-gpios = <&gpb 12 GPIO_ACTIVE_LOW INGENIC_GPIO_NOBIAS>;
port {
sc031gs_ep0:endpoint {
remote-endpoint = <&cim_0>;
};
};
};
};bt656 camera 配置
在wy827_bt656.dtsi中,对cim控制器进行如下配置:根据datasheet或波形测量确定pclk,data有效方式。
&cim {
status = "okay";
port {
cim_0: endpoint@0 {
remote-endpoint = <&wy827_ep0>;
bus-width = <8>; /* Used data lines */
data-shift = <0>; /* Lines 9:0 are used */
/* If hsync-active/vsync-active are missing,
embedded BT.656 sync is used */
pclk-sample = <0>; /* Falling */
data-active = <1>; /* Active high */
};
};
};在wy827_bt656.dtsi中,对camera sensor进行如下配置:根据原理图确定i2c,例如:i2c3_pc;根据camera datasheet确定i2c address,例如:0x3d;确定mclk,reset,pwdn,vcc等gpio有效方式以及上电时序。
&i2c3 {
status = "okay";
clock-frequency = <100000>;
timeout = <1000>;
pinctrl-names = "default";
pinctrl-0 = <&i2c3_pc>;
wy827_0:wy827@0x3d {
status = "ok";
compatible = "bt656,wy827";
reg = <0x3d>;
pinctrl-names = "default";
pinctrl-0 = <&cim_pa>;
port {
wy827_ep0:endpoint {
remote-endpoint = <&cim_0>;
};
};
};
};配置驱动
适配新型号camera时,可以仿照已有型号。以下将以sc031gs为例进一步分析如何配置驱动。
驱动所在位置: module_drivers/drivers/media/i2c/ingenic-cim
获取 reset、pdwn、vcc 等 gpio 属性
/* Request the reset GPIO deasserted */ priv->resetb_gpio = devm_gpiod_get_optional(&client->dev, "resetb", GPIOD_OUT_LOW); if (!priv->resetb_gpio) dev_dbg(&client->dev, "resetb gpio is not assigned!\n"); else if (IS_ERR(priv->resetb_gpio)) return PTR_ERR(priv->resetb_gpio); /* Request the power down GPIO asserted */ priv->pwdn_gpio = devm_gpiod_get_optional(&client->dev, "pwdn", GPIOD_OUT_LOW); if (!priv->pwdn_gpio) dev_dbg(&client->dev, "pwdn gpio is not assigned!\n"); else if (IS_ERR(priv->pwdn_gpio)) return PTR_ERR(priv->pwdn_gpio); /* Request the power down GPIO asserted */ priv->vcc_en_gpio = devm_gpiod_get_optional(&client->dev, "vcc-en", GPIOD_OUT_LOW); if (!priv->vcc_en_gpio) dev_dbg(&client->dev, "vcc_en gpio is not assigned!\n"); else if (IS_ERR(priv->vcc_en_gpio)) return PTR_ERR(priv->vcc_en_gpio);
配置mclk
priv->clk = v4l2_clk_get(&client->dev, "div_cim"); if (IS_ERR(priv->clk)) return -EPROBE_DEFER; v4l2_clk_set_rate(priv->clk, 24000000); /* mclk 24M */
配置camera chip_id
根据datasheet确定chip_id和寄存器。
#define REG_CHIP_ID_HIGH 0x3107
#define REG_CHIP_ID_LOW 0x3108
#define CHIP_ID_HIGH 0x00
#define CHIP_ID_LOW 0x31
/*
* check and show product ID and manufacturer ID
*/
retval_high = sc031gs_read_reg(client, REG_CHIP_ID_HIGH);
if (retval_high != CHIP_ID_HIGH) {
dev_err(&client->dev, "read sensor %s chip_id high %x is error\n",
client->name, retval_high);
ret = -EINVAL;
goto done;
}
retval_low = sc031gs_read_reg(client, REG_CHIP_ID_LOW);
if (retval_low != CHIP_ID_LOW) {
dev_err(&client->dev, "read sensor %s chip_id low %x is error\n",
client->name, retval_low);
ret = -EINVAL;
goto done;
}添加camera初始化寄存器列表
该列表需要有模组厂商提供。
struct regval_list {
u16 reg_num;
u16 value;
};
static const struct regval_list sc031gs_init_regs[] = {
{0x0103, 0x01},
{0x0100, 0x00},
{0x36e9, 0x80},
{0x36f9, 0x80},
{0x3001, 0x00},
{0x3000, 0x00},
{0x300f, 0x0f},
{………………, …………},
{………………, …………},
{SC031_REG_DELAY,10},
ENDMARKER,
};camera参数配置
xxx_win_size结构体用于存储camera分辨率,输出格式,mclk频率,寄存器初始化等信息。
#define SC031GS_DEFAULT_WIDTH 640
#define SC031GS_DEFAULT_HEIGHT 480
enum sc031gs_width {
W_VGA = SC031GS_DEFAULT_WIDTH,
};
enum sc031gs_height {
H_VGA = SC031GS_DEFAULT_HEIGHT,
};
struct sc031gs_win_size {
char *name;
enum sc031gs_width width;
enum sc031gs_height height;
const struct regval_list *regs;
unsigned int mbus_code;
struct sensor_info sensor_info;
};
static struct sc031gs_win_size sc031gs_supported_win_sizes[] = {
{
.name = "sc031gs",
.width = W_VGA,
.height = H_VGA,
.regs = sc031gs_vga_regs,
.mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10,
.sensor_info.mipi_clk = 800,
},
};| output format | mbus_code |
|---|---|
| raw8 | MEDIA_BUS_FMT_SBGGR8_1X8 (序列:BGGR/GBRG/GRBG/RGGB) |
| raw10 | MEDIA_BUS_FMT_SGBRG10_1X10 (序列:BGGR/GBRG/GRBG/RGGB) |
| raw12 | MEDIA_BUS_FMT_SGRBG12_1X12 (序列:BGGR/GBRG/GRBG/RGGB) |
| GREY | MEDIA_BUS_FMT_Y8_1X8 |
| YUV | MEDIA_BUS_FMT_YVYU8_2X8 (序列:YUYV/YVYU/UYVY/VYUY) |