zhuanzi: http://blogold.chinaunix.net/u3/116954/showart_2309015.html
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的值實現的