新主板回来,需要点亮摄像头。主板摄像头情况(前后摄像的i2c和mclk都是独立的)。将驱动文件移植好之后(后摄sp2507 前摄sp0a09),后摄能点亮,看内核打印信息,sp0a09不到id。按https://blog.csdn.net/mike8825/article/details/106163001里的检查方法检查后,没发现异常。这些摄像头在另一个项目上是能点亮的,而这两个项目的camera引脚能完全对上(缺货,替代方案)cam_rst,cam_pdn,cam_i2c,vcamd,vcamio,vcama,mclk都有信号输出,但就是读不到id。怀疑是上电的问题,但量信号没看出有异常。刚好前摄像也有sp2507的模组,配置上去有,前摄也能点亮。但为什么sp0a09读不到id呢。
再点另一组模组gc02m1/gc030a,实验结果也是后摄gc02m1能点亮,gc030a读不到id。
继续点另两组模组bf2553/bf2253和bf2253和bf20a1(为什么会有这么多模组,跟目前的半导体器件缺货有关,cpu要有备份,tp和lcd也要备份几家供应商),这次只有bf2553点亮了,bf2253作为后摄居然没点亮,前面的两组都是前摄点不亮。
从目前的实验情况看,点亮的模组有sp2507/gc02m1/bf2553,成功率约为一半,而且后摄和前摄都有点不亮的情况。因为现象跟着摄像头走,一度怀疑是主板信号有问题,才出现此类问题,但量信号又量不出问题。
比亚迪的fae说camera的powerdown脚可能没拉低,导致读不到id,让将powerdown脚拉倒地试下。拿镊子将camera的powerdown脚短路到地,然后让主板开机,看log,居然读到id了。那就是powerdown脚的配置有问题了,但再三检查,移植的驱动没有任何问题。于是将摄像头的上电过程打印出来,发现跟配置的上电时序对不上。
看下这段代码kernel4.14-mtk/drivers/misc/mediatek/imgsensor/src/common/v1/imgsensor_hw.c
static enum IMGSENSOR_RETURN imgsensor_hw_power_sequence(
struct IMGSENSOR_HW *phw,
enum IMGSENSOR_SENSOR_IDX sensor_idx,
enum IMGSENSOR_HW_POWER_STATUS pwr_status,
struct IMGSENSOR_HW_POWER_SEQ *ppower_sequence,
char *pcurr_idx)
{
struct IMGSENSOR_HW_SENSOR_POWER *psensor_pwr =
&phw->sensor_pwr[sensor_idx];
struct IMGSENSOR_HW_POWER_SEQ *ppwr_seq = ppower_sequence;
struct IMGSENSOR_HW_POWER_INFO *ppwr_info;
struct IMGSENSOR_HW_DEVICE *pdev;
int pin_cnt = 0;
/* while (ppwr_seq < ppower_sequence + IMGSENSOR_HW_SENSOR_MAX_NUM &&
ppwr_seq->name != NULL) {
if (!strcmp(ppwr_seq->name, PLATFORM_POWER_SEQ_NAME)) {
if (sensor_idx == ppwr_seq->_idx)
break;
} else {
if (!strcmp(ppwr_seq->name, pcurr_idx))
break;
}
ppwr_seq++;
}
if (ppwr_seq->name == NULL)
return IMGSENSOR_RETURN_ERROR;
*/
ppwr_info = ppwr_seq->pwr_info;
while (ppwr_info->pin != IMGSENSOR_HW_PIN_NONE &&
ppwr_info < ppwr_seq->pwr_info + IMGSENSOR_HW_POWER_INFO_MAX) {
if (pwr_status == IMGSENSOR_HW_POWER_STATUS_ON &&
ppwr_info->pin != IMGSENSOR_HW_PIN_UNDEF) {
pdev = phw->pdev[psensor_pwr->id[ppwr_info->pin]];
/*pr_debug(
* "sensor_idx = %d, pin=%d, pin_state_on=%d, hw_id =%d\n",
* sensor_idx,
* ppwr_info->pin,
* ppwr_info->pin_state_on,
* psensor_pwr->id[ppwr_info->pin]);
*/
if (pdev->set != NULL)
pdev->set(
pdev->pinstance,
sensor_idx,
ppwr_info->pin,
ppwr_info->pin_state_on);
mdelay(ppwr_info->pin_on_delay);
}
ppwr_info++;
pin_cnt++;
}
if (pwr_status == IMGSENSOR_HW_POWER_STATUS_OFF) {
while (pin_cnt) {
ppwr_info--;
pin_cnt--;
if (ppwr_info->pin != IMGSENSOR_HW_PIN_UNDEF) {
pdev =
phw->pdev[psensor_pwr->id[ppwr_info->pin]];
mdelay(ppwr_info->pin_on_delay);
if (pdev->set != NULL)
pdev->set(
pdev->pinstance,
sensor_idx,
ppwr_info->pin,
ppwr_info->pin_state_off);
}
}
}
/* wait for power stable */
if (pwr_status == IMGSENSOR_HW_POWER_STATUS_ON)
mdelay(5);
return IMGSENSOR_RETURN_SUCCESS;
}
也就是都用第一个都用sensor_power_sequence里的第一个模组的上电时序。
看kernel4.14-mtk/drivers/misc/mediatek/imgsensor/src/common/v1_1/imgsensor_hw.c里面是没有屏蔽这段代码的
/* while (ppwr_seq < ppower_sequence + IMGSENSOR_HW_SENSOR_MAX_NUM &&
ppwr_seq->name != NULL) {
if (!strcmp(ppwr_seq->name, PLATFORM_POWER_SEQ_NAME)) {
if (sensor_idx == ppwr_seq->_idx)
break;
} else {
if (!strcmp(ppwr_seq->name, pcurr_idx))
break;
}
ppwr_seq++;
}
if (ppwr_seq->name == NULL)
return IMGSENSOR_RETURN_ERROR;
*/
找了两份原始代码来确认,都有同样的问题,但kernel4.19下的这个文件也是对的,那找谁理论去。唯一的解释就是soc对老平台的关注度不高,导致出现这种低级错误。
再来反思下,为什么定位问题花了这么久的时间。如果单点一个摄像头应该可以点亮,但为了偷懒,直接在dts里配置要点亮的摄像头,但跟单点一个摄像头的效果还是有差异的。
将
cam0_enable_sensor = "bf2553l_mipi_raw bf2253l_mipi_raw gc02m1_mipi_raw sp2507_mipi_raw";
cam1_enable_sensor = "bf2253lf_mipi_raw bf20a1_mipi_raw gc030a_mipi_raw sp0a09_mipi_raw sp2507f_mipi_raw";
改成
cam0_enable_sensor = "sp2507_mipi_raw";
cam1_enable_sensor = "sp0a09_mipi_raw";
再从信号方面分析。
sp2507的上电图
bf2253l的上电图
量信号最好只配单个摄像头,如果同时量了XPD和XRST的信号,应该能定位到信号异常。但摄像头一般不会留测试点,需要焊线出来(有些引脚点还不好焊接),每次量两组信号,该过程较为繁琐,能精确到如此地步的工程师估计也不多。