Android版本:4.4
前前后后调试了快一个月,最后调试到产品稳定。
扫描头本质是摄像头,遵循Camera架构.
第一阶段:
驱动挂上了,i2c读写不稳定,用系统前置预览,没有图像。
示波器量mipi,没有波形,查看手册才发现扫描头支持并口和mipi接口,需要手动配置成mipi接口,0x86寄存器写入0x3。
static int32_t scan_sensor_start_stream(struct msm_sensor_ctrl_t *s_ctrl)
{
..........
reg_addr = 0x86;
data = 0x03;
rc = scan_i2c_write(this_client, reg_addr, &data, 1);
........
return rc;
}
配置完mipi接口输出后,前置预览还是出不了图像,mipi已经出波形了,电平1.2V也符合要求,说明扫描头已经有传输数据,高通平台这层出了问题。
按照以往经验,Vendor 配置是YUV图像输出,
{0, CSI_YUV422_8, CSI_DECODE_8BIT},
刚开始以为mipi通路问题,试了一个调试过的前置,预览正常,证明mipi通路是正确的。联系了FAE才知道是RAW8格式。修改成RAW8后,系统前置预览图像出来了。
{0, CSI_RAW8, CSI_DECODE_8BIT},
格式设置错了,能预览但是没提示又错误,framebuff也一直有,格式错了应该也会花屏,这个地方纠结了一阵子。
第二阶段:
demo应用预览图像有条纹或者显示不全,图像可以看得不清晰,无法解码。FAE强调分辨率是1280 * 720。后面几番尝试,修改分辨率为1360 * 800,应用demo预览正常了。这有一部分原因是i2c不稳定而导致误判,FAE demo和我用也不一样。
Kernel层代码:
reg_addr = 0x84;
data = 0x01;
rc = scan_i2c_write(this_client, reg_addr, &data, 1);
Vendor层代码:
.x_output = 1360,
.y_output = 800,
.line_length_pclk = 1688,
.frame_length_lines = 832,
第三阶段:
扫描头I2c不稳定,偶尔能正常出图像,代码上优化也不能避免i2c读写出错。
扫描头命令协议是cmd + data + checksum,大部分命令长度是3个。
I2C Command Format:
<I2C-Start Bit> <SLA-W> <Cmd-Opcode> <[Cmd-Data]> <Checksum> <I2C-Stop-Bit>
调试以来,使用的都是高通i2c接口i2c_write_seq和i2c_read_seq接口。
i2c_write_seq(s_ctrl->sensor_i2c_client, reg_addr,txdata, tx_len);
i2c_read_seq(s_ctrl->sensor_i2c_client, reg_addr,rxdata, rx_len);
高通架构i2c为发送命令4字节对齐,和扫描头通信协议冲突,校验值计算错误,造成i2c错乱。扫描头i2c电路上飞线到其他路i2c,驱动在扫描头加载的时候加入新的i2c挂载.
static int32_t scan_platform_probe(struct platform_device *pdev)
{
..........
i2c_add_driver(&real_i2c_driver);
rc = msm_sensor_platform_probe(pdev, match->data);
return rc;
}
注册一个i2c设备,实际使用到i2c的地方,就用这个新注册的i2c读写,使用i2c_transfer接口,i2c就此稳定。
static int scan_i2c_write(struct i2c_client *client, u8 reg, u8 *val, u8 len)
{
struct i2c_msg msg;
u8 data[4];
int i = 0;
int rc = -1, cnt = 0;
data[0] = reg;
for ( i = 0; i < len; i++)
{
data[i+1] = val[i];
}
data[i+1] = scan_calc_checksum(data, len+1);
msg.addr = client->addr;
msg.flags = 0;
msg.len = len + 2;
msg.buf = data;
do {
rc = i2c_transfer(client->adapter, &msg, 1);
msleep(1);
}while(cnt++ < 3 && rc < 0);
return rc;
}
使用普通i2c读写接口
第四阶段:
优化代码,单个命令不会出错,写多个命令经常会i2c出错,实际调试发现,每个写命令之间最好要有1ms间隔,读字符串命令需要等待5ms。