OV5645 MIPI CSI-2 2-Lane配置分析:驱动与设备树的真实关系
问题背景
在调试基于Zynq UltraScale+ MPSoC的OV5645摄像头MIPI CSI-2接口时,发现设备树中配置了data-lanes = <1 2>,但驱动代码似乎并未使用此配置。本文分析了正点原子(Altik)和Xilinx官方两种OV5645驱动的2-lane配置机制。
硬件基础:OV5645的MIPI Lane配置
关键寄存器:0x300E (MIPI CONTROL 00)
OV5645通过寄存器0x300E控制MIPI物理层配置:
寄存器地址:0x300E
默认值:0x58Bit[7:5]: mipi_lane_mode001 (0x20): 1-lane模式010 (0x40): 2-lane模式 ← OV5645默认配置其他: Debug模式Bit[4]: MIPI TX PHY power down
Bit[3]: MIPI RX PHY power down
Bit[2]: mipi_en (0=DVP, 1=MIPI)
Bit[1]: MIPI suspend
Bit[0]: Lane disable option
芯片上电默认值分析:
0x58 = 0101 1000
Bit[7:5] = 010 → 已经是2-lane模式
Bit[4] = 1 → TX PHY power down(待驱动启用)
Bit[3] = 1 → RX PHY power down
Bit[2] = 0 → DVP模式(待切换到MIPI)
驱动实现分析
正点原子(Altik)驱动
宏定义方式固定2-lane:
#define OV5645_2LANES 2
#define OV5645_IO_MIPI_CTRL00 0x300e
启动流配置:
static int __ov5645_start_stream(struct ov5645 *ov5645)
{// 启动时写入0x45ret = ov5645_write_reg(ov5645->client, OV5645_IO_MIPI_CTRL00,OV5645_REG_VALUE_08BIT, 0x45);return ov5645_write_reg(ov5645->client, OV5645_SYSTEM_CTRL0,OV5645_REG_VALUE_08BIT, OV5645_SYSTEM_CTRL0_START);
}
0x45寄存器值解析:
0x45 = 0100 0101
Bit[7:5] = 010 → 2-lane模式
Bit[4] = 0 → PHY正常工作
Bit[3] = 0 → PHY正常工作
Bit[2] = 1 → MIPI使能(关键:从DVP切换到MIPI)
Bit[1] = 0 → 不suspend
Bit[0] = 1 → Lane disable option
停止流配置:
static int __ov5645_stop_stream(struct ov5645 *ov5645)
{// 停止时写入0x40ov5645_write_reg(ov5645->client, OV5645_IO_MIPI_CTRL00,OV5645_REG_VALUE_08BIT, 0x40);return ov5645_write_reg(ov5645->client, OV5645_SYSTEM_CTRL0,OV5645_REG_VALUE_08BIT, OV5645_SYSTEM_CTRL0_STOP);
}
0x40寄存器值解析:
0x40 = 0100 0000
Bit[7:5] = 010 → 保持2-lane模式
Bit[2] = 0 → 禁用MIPI输出
V4L2 mbus配置(旧版API):
static int ov5645_g_mbus_config(struct v4l2_subdev *sd,struct v4l2_mbus_config *config)
{u32 val = 0;// 1 << (2 - 1) = 2 = 0b00000010 (Bit 1表示2-lane)val = 1 << (OV5645_2LANES - 1) |V4L2_MBUS_CSI2_CHANNEL_0 |V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;config->type = V4L2_MBUS_CSI2_DPHY;config->flags = val;return 0;
}
像素时钟计算包含lane数:
pixel_rate = (u32)link_freq / mode->bpp * 2 * OV5645_2LANES;
关键特点:
- ❌ 未解析设备树endpoint
- ❌ 未读取data-lanes配置
- ✅ Hard-coded为2-lane
- ✅ 使用固定寄存器值0x45/0x40
Xilinx官方驱动
Probe函数中解析设备树:
static int ov5645_probe(struct i2c_client *client)
{struct v4l2_fwnode_endpoint ep;// 解析endpointendpoint = of_graph_get_next_endpoint(dev->of_node, NULL);ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(endpoint), &ov5645->ep);// 验证总线类型if (ov5645->ep.bus_type != V4L2_MBUS_CSI2_DPHY) {dev_err(dev, "invalid bus type, must be CSI2\n");return -EINVAL;}// 注意:解析了ep但从未使用ep.bus.mipi_csi2.num_data_lanes!
}
启动/停止流配置(与Altik完全相同):
static int ov5645_s_stream(struct v4l2_subdev *subdev, int enable)
{if (enable) {// 启动流ret = ov5645_write_reg(ov5645, OV5645_IO_MIPI_CTRL00, 0x45);ret = ov5645_write_reg(ov5645, OV5645_SYSTEM_CTRL0,OV5645_SYSTEM_CTRL0_START);} else {// 停止流ret = ov5645_write_reg(ov5645, OV5645_IO_MIPI_CTRL00, 0x40);ret = ov5645_write_reg(ov5645, OV5645_SYSTEM_CTRL0,OV5645_SYSTEM_CTRL0_STOP);}
}
断电时恢复默认值:
static int ov5645_set_power_off(struct device *dev)
{ov5645_write_reg(ov5645, OV5645_IO_MIPI_CTRL00, 0x58);// 其他断电操作...
}
关键特点:
- ✅ 解析了设备树endpoint
- ✅ 验证了总线类型
- ❌ 但从未使用
ep.bus.mipi_csi2.num_data_lanes - ✅ 使用相同的寄存器值0x45/0x40/0x58
对比:正确使用data-lanes的驱动(OV5640)
OV5640驱动展示了如何正确使用设备树的data-lanes配置:
struct ov5640_dev {struct v4l2_fwnode_endpoint ep;// ... 其他成员
};// 在时钟配置中使用num_data_lanes
static int ov5640_set_mipi_pclk(struct ov5640_dev *sensor)
{unsigned char num_lanes;// 从解析的endpoint读取lane数num_lanes = sensor->ep.bus.mipi_csi2.num_data_lanes;// 用于计算采样率sample_rate = (link_freq * mipi_div * num_lanes * 2) / 16;// ... 其他计算
}
设备树配置分析
典型设备树配置
&i2c1 {ov5645_cam: camera@3c {compatible = "ovti,ov5645";reg = <0x3c>;port {ov5645_ep: endpoint {data-lanes = <1 2>; // ← 声明使用lane1和lane2link-frequencies = /bits/64 <594000000>; // ← DDR速率:594 Mbpsremote-endpoint = <&mipi_csi_in>;};};};
};&mipi_csi2_rx_subsyst_0 {mipi_csi_port0: port@0 {mipi_csi_in: endpoint {data-lanes = <1 2>; // ← MIPI RX端也声明2-laneremote-endpoint = <&ov5645_ep>;};};
};
V4L2 Endpoint结构体
struct v4l2_fwnode_endpoint {enum v4l2_mbus_type bus_type;union {struct {unsigned int num_data_lanes; // ← data-lanes数量unsigned int data_lanes[8]; // ← 每条lane的编号unsigned int clock_lane;// ... 其他成员} mipi_csi2;// ... 其他总线类型} bus;
};
关键结论
OV5645的2-Lane配置机制
| 配置层次 | 配置方法 | 是否必需 | 实际作用 |
|---|---|---|---|
| 硬件默认 | 芯片Reset值0x58 | - | Bit[7:5]=010,默认2-lane |
| 寄存器配置 | 0x300E写入0x45/0x40 | ✅ 必需 | Bit[2]控制MIPI使能 |
| 设备树data-lanes | data-lanes = <1 2> | ❌ 不必需 | 驱动未读取此值 |
| 设备树link-frequencies | link-frequencies = <594000000> | ✅ 必需 | V4L2框架匹配验证 |
三个关键发现
-
OV5645芯片硬件默认就是2-lane模式
- Reset默认值0x58的Bit[7:5]=010
- 驱动所有配置(0x45/0x40/0x58)的Bit[7:5]都保持为010
-
两种驱动都未使用设备树的data-lanes配置
- Altik驱动:完全不解析endpoint
- Xilinx驱动:解析endpoint但不使用
num_data_lanes - 都通过hard-coded方式配置2-lane
-
寄存器0x300E的真正作用是控制MIPI使能
- Bit[7:5]控制lane数(固定为010)
- Bit[2]控制MIPI vs DVP切换(关键)
- Bit[4:3]控制PHY电源
- 0x45启动流:Bit[2]=1使能MIPI输出
- 0x40停止流:Bit[2]=0禁用MIPI输出
实际影响
对于使用OV5645的开发者:
-
设备树中的
data-lanes = <1 2>可以省略- OV5645驱动不会读取此配置
- 芯片硬件固定工作在2-lane模式
- 除非物理上只连接1根数据线
-
真正需要配置的是
link-frequencieslink-frequencies = /bits/64 <594000000>; // DDR速率- 用于V4L2框架的link_freq控制匹配
- 驱动中link_freq应设置为297MHz(594/2)
- Vivado MIPI CSI-2 IP核的Line Rate应配置为594 Mbps
-
驱动移植注意事项
- 如需支持1-lane模式,必须修改驱动代码
- 需要从设备树读取
ep.bus.mipi_csi2.num_data_lanes - 根据lane数动态配置0x300E的Bit[7:5]
- 参考OV5640驱动的实现方式
改进建议
如果要让OV5645驱动支持动态lane配置,应参考OV5640驱动:
struct ov5645 {struct v4l2_fwnode_endpoint ep;unsigned int num_lanes; // 新增成员// ... 其他成员
};static int ov5645_probe(struct i2c_client *client)
{// 解析endpointret = v4l2_fwnode_endpoint_parse(..., &ov5645->ep);// 读取并验证lane数num_lanes = ov5645->ep.bus.mipi_csi2.num_data_lanes;if (num_lanes != 1 && num_lanes != 2) {dev_err(dev, "invalid number of lanes: %u\n", num_lanes);return -EINVAL;}ov5645->num_lanes = num_lanes;// ... 其他初始化
}static int ov5645_start_stream(struct ov5645 *ov5645)
{u8 lane_mode;u8 reg_val;// 根据lane数配置寄存器lane_mode = (ov5645->num_lanes == 1) ? 0x20 : 0x40; // Bit[7:5]reg_val = lane_mode | 0x05; // 加上Bit[2]=1和Bit[0]=1ret = ov5645_write_reg(ov5645, 0x300E, reg_val);// ... 其他配置
}
参考资料
- OV5645 Datasheet v2.01
- Linux Kernel v6.6.40 - drivers/media/i2c/ov5645.c
- Linux Kernel v6.6.40 - drivers/media/i2c/ov5640.c
- Xilinx MIPI CSI-2 RX Subsystem v5.0/v6.0 文档
总结
OV5645的2-lane配置是通过硬件默认值和驱动hard-coded实现的,与设备树的data-lanes配置无关。这种实现方式简单直接,但缺乏灵活性。对于固定使用2-lane的场景,当前实现已足够;如需支持1-lane模式,则需要参考其他驱动进行改进。
