linux vfe框架,Android Camera Architecture (Android Camera架构)

三、调试(sensor终于拿到了)

将sensor接到板子上,开机后,ADB中运行调试程序,preview画面并没有出来,失败,有点小失望,本来觉得可以一气呵成的,但毕竟这是一个全新的sensor,任何一个地方没有想到位做到位都会导致失败。那就找原因吧。

1、首先从trace得知,I2C已经读到了sensor的ID:0x05CA,这可以说明I2C通讯是没有问题的

2、接着检查Sensor的电源配置,测量了供给sensor的3个电源,都是OK的。

3、测量MCLK,这个是提供给sensor使用的,正常(24MHZ)

4、测量PCLK,这个是sensor输出的,正常(58MHZ,高通上限为96MHZ),和寄存器中配置的一致。

5、测量H/V同步信号,这个是sensor输出的,正常。和FPS和分辨率一致。

6、测量数据信号,这个是sensor输出的,正常。(数据信号,示波器上可以看到)

这样看来,sensor已经在正常工作了,但为何preview画面没有出来呢?继续检查高通这边的设定。

从trace看,高通的VFE已经reset并且start了,但一直接没有输出preview数据,这就奇怪了,sensor明明已经输出了,为什么VFE接收后并没有把数据吐出来呢,难道这个sensor输出的数据VFE无法识别?为了验证这个问题,我在另一块板子上测量了OV sensor输出数据的波形,主要是M/P clk、H/V同步信号,然后再拿来对比,不过并没有发现异常,只是H/V同步信号有所不同,主要高低的占空比不太一致,会不会是这样信号的问题呢?为了进一步验证,我同时测量了H/V 信号和数据信号,这时发现OV sensor输出的数据信号是包在V帧同步信号的低电平中;而Samsung 5CA输出的数据信号是包在V帧同步信号的高电平中,会不会是因为V信号极性设置不对导致VFE没有读取到sensor输出的数据呢?重新检查了一下高通VFE的设定,果然有一个参数是用来设定V信号极性的,这个参数默认是Active Low的,我这边并没有去修改它。接着把这个参数修改为Active High,重新build、download后,开机运行,Ok了,preview画面可以正常显示了。到这里为止sensor的硬件调试可以算作完成了,后续的其他功能也可以慢慢完善了。

FSL调试之Camera

fsl的camera hal层没有实现上层到下层的设置参数的接口,所以需要自己实现。好在从应用到hal层的参数已经弄好,否则工作量就更大了。

参数设置在hal层调用的函数是status_t CameraHal::setParameters(const CameraParameters& params)。在这个函数里实现对每个参数的设置。参数设置主要通过 CameraParameters这个类实现的。通过观察这个类发现,里面有个get()函数,可以分别得到各个参数。如

const char *white_balance = params.get(CameraParameters::KEY_WHITE_BALANCE);这个可以得到目前白平衡的参数即返回值。然后根据返回值判断是哪种情况,如

if (strcmp(white_balance, CameraParameters::WHITE_BALANCE_AUTO) == 0) { //判断为自动白平衡

LOGV("white_balance to ioctl is auto !/n");

ctl.id = V4L2_CID_AUTO_WHITE_BALANCE; //自动白平衡命令,ctl为v4l2_control结构,该结构很有用

ctl.value = 1;

if (ioctl(camera_device, VIDIOC_S_CTRL, &ctl) < 0){ //通过 VIDIOC_S_CTRL把ctl结构体传下去

LOGE("set control failed/n");

//return -1;

}

}else if(strcmp(white_balance, CameraParameters::WHITE_BALANCE_INCANDESCENT) == 0){ //白炽灯模式

LOGV("white_balance to ioctl is incandescent !/n");

ctl.id = V4L2_CID_DO_WHITE_BALANCE; //其它白平衡情况都用该命令

ctl.value = 2; //根据用户自己定义的白平衡模式数目排列

if (ioctl(camera_device, VIDIOC_S_CTRL, &ctl) < 0){ //同样通过 VIDIOC_S_CTRL把ctl结构体传下去,然后在根据value值分情况讨论

LOGE("set control failed/n");

//return -1;

}

}

传到驱动的mxc_v4l2_capture.c文件的mxc_v4l_ioctl中,mxc_v4l_ioctl调用mxc_v4l_do_ioctl,mxc_v4l_do_ioctl对命令的解释如下

/*!

* V4l2 VIDIOC_S_CTRL ioctl

*/

case VIDIOC_S_CTRL: {

pr_debug(" case VIDIOC_S_CTRL/n");

retval = mxc_v4l2_s_ctrl(cam, arg);

break;

}

这样就到了mxc_v4l2_s_ctrl。在mxc_v4l2_s_ctrl通过对ctl.id分情况调用

switch (c->id) {

......

case V4L2_CID_AUTO_WHITE_BALANCE:

ipu_csi_enable_mclk_if(CSI_MCLK_I2C, cam->csi, true, true);

ret = vidioc_int_s_ctrl(cam->sensor, c); //该函数是v4l2对应ov7670驱动中的s_ctl

ipu_csi_enable_mclk_if(CSI_MCLK_I2C, cam->csi, false, false);

break;

case V4L2_CID_DO_WHITE_BALANCE:

ipu_csi_enable_mclk_if(CSI_MCLK_I2C, cam->csi, true, true);

ret = vidioc_int_s_ctrl(cam->sensor, c);

ipu_csi_enable_mclk_if(CSI_MCLK_I2C, cam->csi, false, false);

break;

......

其中vidioc_int_s_ctrl()是v4l2对应ov7670驱动中的 ioctl_s_ctrl,具体代码怎么对应由于篇幅原因就不贴出来。

根据ctl结构体的id分情况去实现即可。

switch (vc->id) {

.....

case V4L2_CID_AUTO_WHITE_BALANCE:

retval = ov7670_autowhitebalance(vc->value);

break;

case V4L2_CID_DO_WHITE_BALANCE:

retval = ov7670_dowhitebalance(vc->value);

break;

......

下面是whitebalance函数的实现

static int ov7670_autowhitebalance(int value)

{

unsigned char v = 0;

int ret;

printk("0v7670_autowhitebalance called/n");

ret = ov7670_read(ov7670_data.i2c_client, REG_COM8, &v);

if (value)

v |= COM8_AWB; //自动白平衡

msleep(10); /* FIXME */

ret += ov7670_write(ov7670_data.i2c_client, 0x01, 0x56);

ret += ov7670_write(ov7670_data.i2c_client, 0x02, 0x44);

ret += ov7670_write(ov7670_data.i2c_client, REG_COM8, v);

return ret;

}

static int ov7670_dowhitebalance(int value)

{

unsigned char v = 0;

int ret;

printk("0v7670_dowhitebalance called value:%d/n",value);

ret = ov7670_read(ov7670_data.i2c_client, REG_COM8, &v);

if (value)

v &= ~COM8_AWB; //关闭自动白平衡

msleep(10); /* FIXME */

ret += ov7670_write(ov7670_data.i2c_client, REG_COM8, v);

if(value == 2) //INCANDESCENCE //这个值就是ctl的value值

{

ret += ov7670_write(ov7670_data.i2c_client, 0x01, 0x8c);

ret += ov7670_write(ov7670_data.i2c_client, 0x02, 0x59);

}else if(value == 3) //FLUORESCENT

{

ret += ov7670_write(ov7670_data.i2c_client, 0x01, 0x7e);

ret += ov7670_write(ov7670_data.i2c_client, 0x02, 0x49);

}else if(value == 4) //DAYLIGHT

{

ret += ov7670_write(ov7670_data.i2c_client, 0x01, 0x52);

ret += ov7670_write(ov7670_data.i2c_client, 0x02, 0x66);

}

return ret;

}

其中函数中ox01、0x02分别是蓝红通道的增益的寄存器。

上面是白平衡从hal层最终到sensor的参数设置过程。其它如色彩效果、取景模式等都是同样的过程。

取景模式根据具体的情况如夜间模式等设定具体的寄存器即可

色彩效果主要通过设置uv的值实现的0b1331709591d260c1c78e86d0c51c18.png

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值