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

一,保留现场

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

相关推荐
Lester_110114 小时前
STM32 高级定时器PWM互补输出模式--如果没有死区,突然关闭PWM有产生瞬间导通的可能吗
stm32·单片机·嵌入式硬件·嵌入式软件
天才奇男子16 小时前
HAProxy高级功能全解析
linux·运维·服务器·微服务·云原生
小李独爱秋16 小时前
“bootmgr is compressed”错误:根源、笔记本与台式机差异化解决方案深度指南
运维·stm32·单片机·嵌入式硬件·文件系统·电脑故障
学嵌入式的小杨同学16 小时前
【Linux 封神之路】信号编程全解析:从信号基础到 MP3 播放器实战(含核心 API 与避坑指南)
java·linux·c语言·开发语言·vscode·vim·ux
酥暮沐16 小时前
iscsi部署网络存储
linux·网络·存储·iscsi
❀͜͡傀儡师17 小时前
centos 7部署dns服务器
linux·服务器·centos·dns
Dying.Light17 小时前
Linux部署问题
linux·运维·服务器
S190117 小时前
Linux的常用指令
linux·运维·服务器
小义_17 小时前
【RH134知识点问答题】第7章 管理基本存储
linux·运维·服务器
梁洪飞18 小时前
内核的schedule和SMP多核处理器启动协议
linux·arm开发·嵌入式硬件·arm