在开始LT6911C驱动移植前,需要明确几个关键概念。V4L2(Video4Linux2)是Linux内核中处理视频设备的通用框架,而MIPI CSI-2则是移动设备中广泛使用的摄像头接口标准。LT6911C作为HDMI到MIPI CSI-2的桥接芯片,其驱动开发需要同时理解这两种技术规范。
必备工具清单:
芯片的寄存器访问采用bank机制,0xFF寄存器用于bank选择。例如访问0xA123寄存器时:
注意:不同bank的寄存器功能各异,视频时序相关寄存器通常分布在特定bank中。
首先创建驱动的基本骨架,注册为V4L2子设备:
c复制static const struct v4l2_subdev_ops lt6911c_subdev_ops = {
.core = <6911c_core_ops,
.video = <6911c_video_ops,
};
static int lt6911c_probe(struct i2c_client *client)
{
struct v4l2_subdev *sd;
sd = devm_kzalloc(&client->dev, sizeof(*sd), GFP_KERNEL);
v4l2_i2c_subdev_init(sd, client, <6911c_subdev_ops);
return 0;
}
LT6911C的所有功能都通过I2C接口控制,需要实现安全的读写函数:
c复制static int lt6911c_i2c_read(struct v4l2_subdev *sd, u16 reg, u8 *val)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
u8 bank = reg >> 8;
u8 offset = reg & 0xFF;
// 先设置bank
i2c_smbus_write_byte_data(client, 0xFF, bank);
// 读取目标寄存器
*val = i2c_smbus_read_byte_data(client, offset);
return 0;
}
典型问题排查:
i2cdetect工具确认设备地址v4l2_dv_timings结构体需要填充以下关键参数:
| 参数项 | 寄存器组 | 计算公式 |
|---|---|---|
| 像素时钟 | 0xB8B1-0xB8B3 | (clk_h<<16 |
| 水平总像素 | 0xA002-0xA003 | (val_h<<8 |
| 垂直总行数 | 0xA006-0xA007 | val_h<<8 |
| 有效图像宽度 | 0xA00A-0xA00B | val_h<<8 |
实现代码示例:
c复制static int lt6911c_get_timings(struct v4l2_subdev *sd,
struct v4l2_dv_timings *timings)
{
u8 clk_h, clk_m, clk_l;
lt6911c_i2c_read(sd, 0xB8B1, &clk_h);
lt6911c_i2c_read(sd, 0xB8B2, &clk_m);
lt6911c_i2c_read(sd, 0xB8B3, &clk_l);
timings->bt.pixelclock = (((clk_h & 0xF) << 16) |
(clk_m << 8) | clk_l) * 1000;
// HDMI 2.0特殊处理
if (hdmi_version == HDMI_2_0)
timings->bt.pixelclock *= 2;
}
LT6911C通过中断通知分辨率变化等事件,典型配置流程:
c复制static irqreturn_t lt6911c_irq_handler(int irq, void *dev_id)
{
struct lt6911c_state *state = dev_id;
u8 int_status;
lt6911c_i2c_read(state->sd, 0xA000, &int_status);
if (int_status & RES_CHANGE_INT) {
v4l2_subdev_notify(state->sd, RESOLUTION_CHANGE, NULL);
}
return IRQ_HANDLED;
}
dts复制lt6911c: lt6911c@2b {
compatible = "lontium,lt6911c";
reg = <0x2b>; /* 注意:实际I2C地址0x56右移1位 */
pinctrl-names = "default";
pinctrl-0 = <<6911c_pins>;
interrupt-parent = <&gpio3>;
interrupts = <RK_PA4 IRQ_TYPE_EDGE_RISING>;
reset-gpios = <&gpio3 RK_PB1 GPIO_ACTIVE_LOW>;
power-gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_HIGH>;
};
常见配置错误:
分辨率不匹配问题排查步骤:
性能优化技巧:
不同Linux平台(如Rockchip、NXP i.MX等)可能需要特殊处理:
Rockchip平台注意事项:
c复制static const struct rkmodule_csi_dphy_param rk3588_dphy_cfg = {
.lp_clk_settle_cnt = 0x14,
.lp_hs_settle_cnt = 0x14,
};
static int lt6911c_get_module_info(struct v4l2_subdev *sd,
struct rkmodule_inf *inf)
{
strscpy(inf->base.sensor, "LT6911C", sizeof(inf->base.sensor));
inf->base.module = "Lontium";
inf->csi2.dphy = rk3588_dphy_cfg;
return 0;
}
跨平台兼容方案:
在完成基本功能后,建议增加以下高级特性: