解决摄像头驱动起不来的情况

一,保留现场

换了个板子和kernel版本后,ov13850驱动起不来了,报如下错误

root@feifeirk:/tmp# insmod rk_ov.ko

335.315715 rk_ov: loading out-of-tree module taints kernel.

335.322983 ov13850 3-0010: driver version: 00.01.03

335.328061 ov13850 3-0010: GPIO lookup for consumer reset

335.333545 ov13850 3-0010: using device tree for GPIO lookup

335.339356 of_get_named_gpiod_flags: parsed 'reset-gpios' property of node '/i2c@ff150000/ov13850@100' - status (0)

335.350337 ov13850 3-0010: GPIO lookup for consumer pwdn

335.355762 ov13850 3-0010: using device tree for GPIO lookup

335.361522 of_get_named_gpiod_flags: parsed 'pwdn-gpios' property of node '/i2c@ff150000/ov13850@100' - status (0)

335.374348 ov13850 3-0010: Unexpected sensor id(000000), ret(-5)

root@feifeirk:/tmp#

跟踪日志到ov13850_probe->ov13850_check_sensor_id

ret = ov13850_read_reg(client, OV13850_REG_CHIP_ID,

OV13850_REG_VALUE_16BIT, &id);

if (id != CHIP_ID) {

dev_err(dev, "Unexpected sensor id(%06x), ret(%d)\n", id, ret);

return -ENODEV;

}

原先的代码ov13850_check_sensor_id出错后会关闭power

ret = ov13850_check_sensor_id(ov13850, client);

if (ret)

goto err_power_off;

先改成直接返回成功,保留现场

ret = ov13850_check_sensor_id(ov13850, client);

return 0;

二,分析pin脚和pwr

引脚:

引脚3表示数字电压DVDD,给芯片的数字信号供电,CIF_POWER (GPIO7_B4)引脚控制

引脚4是芯片引脚出来的电压IOVDD,rk3288中受DVP_PWR(GPIO0_B3)控制

引脚7是模拟电压AVDD,给芯片中的模拟器件供电,比如camera供电就要用到AVDD,也是相对于DVDD区别出来的,rk3288中受DVP_PWR(GPIO0_B3)控制

引脚11复位信号输出,GPIO2_B7,硬件上拉

引脚12是Power Down 信号输出,GPIO2_B6

引脚14是时钟输出(提供给外部摄像头的主时钟),GPIO2_B3

电源引脚3/4/7先不看,直接量电压。

reset和Power Down都是高,都是正常的,引脚14暂时还用不到,说明pin脚没有问题。

三,分析power

从dts中总结有三个:

dvdd_1v2: dvdd-1v2 {

status = "okay";

compatible = "regulator-fixed";

enable-active-high;

gpio = <&gpio7 12 GPIO_ACTIVE_HIGH>;

pinctrl-names = "default";

pinctrl-0 = <&cif_pwr>;

regulator-name = "dvdd_1v2";

};

vcc28_dvp: vcc28-dvp-regulator {

compatible = "regulator-fixed";

enable-active-high;

gpio = <&gpio0 11 GPIO_ACTIVE_HIGH>;

pinctrl-names = "default";

pinctrl-0 = <&dvp_pwr>;

regulator-name = "vcc28_dvp";

regulator-min-microvolt = <2800000>;

regulator-max-microvolt = <2800000>;

regulator-always-on;

vin-supply = <&vcc_io>;

};

dovdd_1v8: dovdd-1v8-regulator {

compatible = "regulator-fixed";

regulator-name = "dovdd_1v8";

regulator-min-microvolt = <1800000>;

regulator-max-microvolt = <1800000>;

regulator-always-on;

regulator-boot-on;

vin-supply = <&vcc28_dvp>;

};

root@feifeirk:/tmp# ls /sys/class/regulator/regulator.*/name

/sys/class/regulator/regulator.0/name

/sys/class/regulator/regulator.1/name

/sys/class/regulator/regulator.10/name

/sys/class/regulator/regulator.11/name

/sys/class/regulator/regulator.12/name

/sys/class/regulator/regulator.13/name

/sys/class/regulator/regulator.14/name

/sys/class/regulator/regulator.15/name

/sys/class/regulator/regulator.16/name

/sys/class/regulator/regulator.17/name

/sys/class/regulator/regulator.18/name

/sys/class/regulator/regulator.19/name

/sys/class/regulator/regulator.2/name

/sys/class/regulator/regulator.20/name

/sys/class/regulator/regulator.21/name

/sys/class/regulator/regulator.3/name

/sys/class/regulator/regulator.4/name

/sys/class/regulator/regulator.5/name

/sys/class/regulator/regulator.6/name

/sys/class/regulator/regulator.7/name

/sys/class/regulator/regulator.8/name

/sys/class/regulator/regulator.9/name

root@feifeirk:/tmp# cat /sys/class/regulator/regulator.*/name

regulator-dummy

dvdd_1v2

vcc_ddr

vcc_io

vdd_log

vcc_20

vccio_sd

vdd10_lcd

vcca_codec

vcc_lan

vccio_pmu

vdd_10

vcc28_dvp

vcc_18

vcc18_lcd

dovdd_1v8

vcc1v8_sys

vcc_host

vcc_phy

vcc_sys

vdd_cpu

vdd_gpu

root@feifeirk:/tmp# cat /sys/class/regulator/regulator.*/state

disabled

enabled

enabled

enabled

enabled

enabled

enabled

enabled

enabled

enabled

enabled

enabled

enabled

enabled

enabled

enabled

enabled

enabled

万用表量三个电源都没有问题,

但是cat /sys/class/regulator/regulator.*/state查看dvdd_1v2偶尔没有state文件,说明dvdd_1v2电源有关闭情况。

给dvdd_1v2加上regulator-always-on属性后测试/sys/class/regulator/regulator稳定了,但还是probe失败。

四,分析原因

分析可能的原因:

1,dovdd_1v8需要io_domain配置dvp-supply = <&dovdd_1v8>,且摄像头驱动要在iodomain配置之后启动电源,iodomain寄存器配置错误

2,三个电源的启动顺序不对,影响了时序

3,reset或pwdn有拉低再拉高情况,没有走正常的pm_ops

第一点通过读寄存器验证没有问题

第二点通过临时去掉休眠,直接在probe关闭三个电源后,reset和pwdn拉低后,重新操作电源启动测试,

第三点通过确认dts没有干扰后,在每次操作reset和pwdn加日志打印确认拉高拉低确认

五,修复后的代码

1,dvdd_1v2加了regulator-always-on属性

2,增加了CONFIG_VIDEO_OV13850=y,将驱动写入了内核,这个是想看iodomain和ov的配置顺序,虽然没有问题,但是保留了这个修改

3,13850驱动里面,修改

(1)

(2)

(3)

改了这几处之后正常出流了:

因为发现dvdd_1v2中间被系统关闭了,所以ko改成编进内核,切屏蔽了dev_pm_ops,电源不被系统接管;

ov13850_s_power直接返回是临时屏蔽isp调用摄像头的s_pwr off功能造成的干扰,s_pwr off里面后操作reset拉低,先临时关闭;

因为ov13850_s_power直接返回了,所以里面的初始化序列加载了probe函数里面。

六,总结

修复的代码方式只是规避,但是能证明问题跟硬件没关系,跟三个pwr的顺序或reset有关,后续微调就能找到问题,比较好解决了。

开始以为引脚有问题,测量和加日志后发现没有任何问题。当时还怀疑硬件出问题了,这个引脚比较多,时序复杂,示波器line不够,如果没有一个出流的方案估计得上逻辑分析仪测试下电源启动顺序了,找到一个规避方法就能来回切换测试了。

相关推荐
zcmodeltech几秒前
钢铁冶金沙盘模型多工序协同控制系统设计:基于STM32与Modbus RTU的高炉-连铸-热轧全流程联动方案
stm32·单片机·嵌入式硬件·数据库架构·嵌入式实时数据库·多分类
大眼、不聚光15 分钟前
9.linux系统管理-ssh免密配置
linux·ssh·github
啦啦啦!20 分钟前
虚拟机如何接入Codex并配置中转站(vscode插件版)
linux·vscode·ubuntu·编辑器
love530love21 分钟前
Ubuntu系统通过Homebrew安装Lightpanda完整实战教程(含端口占用排坑)
大数据·linux·运维·人工智能·elasticsearch·搜索引擎
j7~25 分钟前
【Linux】二十八.线程篇五《Linux多线程编程:线程同步之条件变量》---详解
linux·运维·c++·学习·条件变量·线程同步
似水এ᭄往昔41 分钟前
【Linux网络编程】--UDP__SCOKE
linux·计算机网络
小张同学a.1 小时前
LAMP架构4——MySQL高可用
linux·运维·服务器·数据库·mysql·架构·负载均衡
zcmodeltech1 小时前
供热系统模型多工况控制系统设计:基于STM32与Modbus RTU的热源-管网-末端联动方案
大数据·stm32·单片机·嵌入式硬件·制造·数据库系统
进击切图仔1 小时前
Ubuntu 挂载 XFS 磁盘并免密读写
linux·网络·ubuntu
qetfw1 小时前
Debian Apache2 执行 Shell CGI:动态时间页面配置与验证
linux·运维·debian