首页 > 技术知识 > 正文

前言

项目上使用了2片NVP6158C来接8路AHD是视频输入,从FAE那边拿到了驱动的源码,自适应的的应用代码后,就开始画板调试了,因为之前有使用NVP6124B及NVP6134,觉着这货还不是小菜一点,交给了同事去搞,毕竟我们还是要提高整体团队的战斗力的。。。小伙伴搞了几天没整完,今天刚好又是周六。。。所以祖国需要我。。。

问题现象

芯片都能通过I2C配置,2颗同时用的时候,有2个问题:

问题现象1.接8路摄像头: 第一颗芯片上接的4个摄像头,海思端无法采集,第二颗芯片能正常。

问题现象2.插拔摄像头 拔插摄像头的时候,有些通道出现摄像头loss信号检测正常,format检测不出来。

奇怪的是单独使用第一颗芯片(把第二颗新片去了)是正常的,单独使用第二颗(把第一颗去掉)也是正常,按照正常的思路怀疑同时上8路,供电跟不上了,硬件查电路,量电压,后来发现不是,问题依旧。后面还试了各种更可能的情况,将2个芯片分别挂到2个I2C总线上,供电分别单独供,各种折腾,还是不行。

排查问题

后来联系了FAE,他给了2组进寄存器还是很有用的

bank5678 0x2c == 0x08 bank0 0x78/0x79 == 0xaa #colorbar

用这个组参数,默认不接摄像头就是可以出彩条的,海思端采集使用1080P。彩条如下: 海思Hi3531DV100/V200上多片6158C踩坑记录

配置后启动程序,发现8个通道全部有数据,都能正常采集到图像,证明物理连接是没有问题的,那么问题到底出在哪里呢?怀疑驱动,单颗又是好的。后面就一步一步排查,将海思的DEMO重新写了下,确保没有问题。最后只能去分析6158C驱动代码了。应为我们使用的是自适应分辨率,需要动态获取视频格式来初始化VI属性。看到驱动里面这么个线程:

static int nvp6158_kernel_thread(void *data) { //int ch; //nvp6158_input_videofmt videofmt; NVP6158_INFORMATION_S s_nvp6158_vfmts; video_equalizer_info_s s_eq_info; unsigned char prefmt=0, curfmt=0, chvloss=0; unsigned char ch = 0; while(!kthread_should_stop()) { #if 1 //standard rutine of a process down(&nvp6158_lock); ch = ch % (nvp6158_cnt*4); nvp6158_getvideoloss(); video_fmt_det(ch, &s_nvp6158_vfmts); curfmt = s_nvp6158_vfmts.curvideofmt[ch]; prefmt = s_nvp6158_vfmts.prevideofmt[ch]; chvloss = s_nvp6158_vfmts.curvideoloss[ch]; printk(“>>>>>>%s CH[%d] chvloss = %d curfmt = %x prefmt = %x\n”, __func__, ch, chvloss, curfmt, prefmt); if(chvloss == 0x00) { if(ch_mode_status[ch] != prefmt) { nvp6158_set_chnmode(ch, curfmt); //nvp6158_set_portmode(0, ch%4, NVP6158_OUTMODE_1MUX_FHD, ch%4); // 不明白为什么写死是0,多个芯片的话就不对了啊,而且第二个参数也是不对,严重怀疑写这个驱动的人没有在6158C上验证过 nvp6158_set_portmode(0, ch%2, NVP6158_OUTMODE_2MUX_SD, ch%2); s_eq_info.Ch = ch%4; s_eq_info.devnum = ch/4; s_eq_info.FmtDef = curfmt; nvp6158_get_eq_dist(&s_eq_info); s_nvp6158_vfmts.prevideofmt[ch] = curfmt; printk(“>>>>>>%s CH[%d] s_eq_info.distance = %d\n”, __func__, ch, s_eq_info.distance); nvp6158_set_equalizer(&s_eq_info); } } else { if(ch_mode_status[ch] != NC_VIVO_CH_FORMATDEF_UNKNOWN) { nvp6158_set_chnmode(ch, NC_VIVO_CH_FORMATDEF_UNKNOWN); nvp6158_set_portmode(0, ch%4, NVP6158_OUTMODE_1MUX_FHD, ch%4); } } ch ++; up(&nvp6158_lock); #endif schedule_timeout_interruptible(msecs_to_jiffies(2000)); // printk(“nvp6158_kernel_thread running\n”); } return 0; }
<

解决问题

根据上面线程的流程,自己改写了从FAE哪边拿过来的代码,发现这个NVP的驱动写的贼乱,通道号和设备号使用不统一,有的外部算,有的内部算。为了方便配合海思动态检测前端分辨率,我们将线程代码抽取了出来,放在APP层,这个部分代码同时解决了好几个坑,自己看代码把,就不细说了,修改过的8路检测关键代码代码如下:

while(1) { for(i=0; i<8 ;i++) { info.ch = i; ioctl(fd, IOC_VDEC_GET_INPUT_VIDEO_FMT, &info); usleep(200*1000); printf(“ch:%d curvideofmt = %d prevideofmt=%d, curvideoloss=%d\n”, i, info.curvideofmt[i],info.prevideofmt[i], info.curvideoloss[i]); if(info.curvideoloss[i] == VIDEO_LOSS_ON) { if(info.prevideofmt[i] != chFormats[i]) { chmode.ch = i; chmode.chmode = info.curvideofmt[i]; ioctl(fd, IOC_VDEC_SET_CHNMODE, &chmode); mode.chipsel =i/4; if((i%4) <2) { mode.portsel = 1; mode.chid = 0; } else { mode.portsel = 2; mode.chid = 1; } mode.portmode = NVP6158_OUTMODE_2MUX_FHD; ioctl(fd, IOC_VDEC_SET_OUTPORTMODE, &mode); info.prevideofmt[i] = info.curvideofmt[i]; chFormats[i] = info.curvideofmt[i]; printf(“set ch:%d into %d mode\n”,i, chFormats[i]); video_info.Ch = i%4; video_info.devnum = i/4; video_info.FmtDef = info.curvideofmt[i]; ioctl(fd, IOC_VDEC_GET_EQ_DIST, &video_info); printf(“APP get CH[%d] EQ stage is %d\n”, i, video_info.distance); ioctl(fd, IOC_VDEC_SET_EQUALIZER, &video_info); } } else { if(NC_VIVO_CH_FORMATDEF_UNKNOWN != chFormats[i]) { chmode.ch = i; chmode.chmode = NC_VIVO_CH_FORMATDEF_UNKNOWN; ioctl(fd, IOC_VDEC_SET_CHNMODE, &chmode); chFormats[i] = NC_VIVO_CH_FORMATDEF_UNKNOWN; printf(“========NC_VIVO_CH_FORMATDEF_UNKNOWN set ch:%d into %d mode\n”,i, chFormats[i]); mode.chipsel =i/4; if((i%4) <2) { mode.portsel = 1; mode.chid = 0; } else { mode.portsel = 2; mode.chid = 1; } mode.portmode = NVP6158_OUTMODE_2MUX_FHD; ioctl(fd, IOC_VDEC_SET_OUTPORTMODE, &mode); } } } sleep(1); }
<

完整的代码下载地址:https://www.ebaina.com/resources/240000028628

猜你喜欢