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

一,保留现场

换了个板子和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@10\[0\]' - 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@10\[0\]' - 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)![](https://i-blog.csdnimg.cn/direct/390f6d939c5e4bf4a90af7c773c4ffee.png) (2)![](https://i-blog.csdnimg.cn/direct/071ccd14c593418f8249357ad70da144.png) (3)![](https://i-blog.csdnimg.cn/direct/dfb4c85d7f094f0980c338b5b343255f.png) 改了这几处之后正常出流了: 因为发现dvdd_1v2中间被系统关闭了,所以ko改成编进内核,切屏蔽了dev_pm_ops,电源不被系统接管; ov13850_s_power直接返回是临时屏蔽isp调用摄像头的s_pwr off功能造成的干扰,s_pwr off里面后操作reset拉低,先临时关闭; 因为ov13850_s_power直接返回了,所以里面的初始化序列加载了probe函数里面。 ## 六,总结 修复的代码方式只是规避,但是能证明问题跟硬件没关系,跟三个pwr的顺序或reset有关,后续微调就能找到问题,比较好解决了。 开始以为引脚有问题,测量和加日志后发现没有任何问题。当时还怀疑硬件出问题了,这个引脚比较多,时序复杂,示波器line不够,如果没有一个出流的方案估计得上逻辑分析仪测试下电源启动顺序了,找到一个规避方法就能来回切换测试了。

相关推荐
YYYing.1 小时前
【Linux/C++进阶篇 (一)】man手册、gdb调试、静态库与动态库
linux·运维·c++
pingzhuyan1 小时前
linux运维-KylinV10的aarch64架构-docker微服务运维部署(全篇)
linux·docker·jdk·rocketmq·kylin·aarch64
摸摸电2 小时前
DRAM结构
单片机·嵌入式硬件·设计规范
前方一片光明2 小时前
Linux——麒麟v10国产化系统升级openssh到10.0版本全过程
linux·运维·服务器
Trouvaille ~2 小时前
【Linux】Linux线程概念与控制(四):glibc源码剖析与实现原理
linux·运维·服务器·c++·操作系统·glibc·线程控制
YuTaoShao2 小时前
【LeetCode 每日一题】3602. 十六进制和三十六进制转化——(解法二)手写进制转换
linux·python·leetcode
上海运维Q先生2 小时前
[漏洞修复]openssh-9.9p2 漏洞升级修复补丁
linux·运维·服务器
skywalk81632 小时前
clonos web界面使用cbsd创建一个bhyve ubuntu server虚拟机(未成功)
linux·运维·服务器·freebsd
程序猿编码2 小时前
深入浅出Linux内核级防火墙:IP/端口黑白名单的高性能实现
linux·c语言·c++·tcp/ip·内核