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

一,保留现场

换了个板子和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不够,如果没有一个出流的方案估计得上逻辑分析仪测试下电源启动顺序了,找到一个规避方法就能来回切换测试了。

相关推荐
Coder个人博客2 小时前
Linux6.19-ARM64 mm mmu子模块深入分析
大数据·linux·车载系统·系统架构·系统安全·鸿蒙系统
Doro再努力5 小时前
Vim 快速上手实操手册:从入门到生产环境实战
linux·编辑器·vim
wypywyp5 小时前
8. ubuntu 虚拟机 linux 服务器 TCP/IP 概念辨析
linux·服务器·ubuntu
Doro再努力5 小时前
【Linux操作系统10】Makefile深度解析:从依赖推导到有效编译
android·linux·运维·服务器·编辑器·vim
senijusene5 小时前
Linux软件编程:IO编程,标准IO(1)
linux·运维·服务器
忧郁的橙子.6 小时前
02-本地部署Ollama、Python
linux·运维·服务器
醇氧6 小时前
【linux】查看发行版信息
linux·运维·服务器
BackCatK Chen6 小时前
第 8 篇:TMC2240 电机正反转实现|DIR 引脚控制 + 代码优化(稳定不抖动)
stm32·单片机·嵌入式硬件·保姆级教程·电机正反转·tmc2240·dir引脚控制
No8g攻城狮6 小时前
【Linux】Windows11 安装 WSL2 并运行 Ubuntu 22.04 详细操作步骤
linux·运维·ubuntu
星马梦缘7 小时前
EDA彩灯电路绘制
单片机·嵌入式硬件·物联网·pcb·eda·嘉立创