这篇文章介绍一下VCM马达驱动的调试,以RK3588,安卓平台,移植DW9763驱动为例。
目录
(一)概述
(1)VCM简介
介绍一下VCM,这里从知乎上面摘抄一段:VCM全称Voice Coil Montor,电子学里面的音圈电机,是马达的一种。因为原理和扬声器类似,所以叫音圈电机,具有高频响、高精度的特点。其主要原理是在一个永久磁场内,通过改变马达内线圈的直流电流大小,来控制弹簧片的拉伸位置,从而带动上下运动。手机摄像头广泛的使用VCM实现自动对焦功能,通过VCM可以调节镜头的位置,呈现清晰的图像。
(2)实现camera对焦方法
①实现光学变焦采用变焦马达(ZOOM)
通过移动镜头内部的镜片来改变焦点的位置,改变镜头焦距的长短,并改变镜头的视角大小,从而实现影响的放大与缩小。
②实现自动对焦采用对焦马达(AF)
过微距离移动整个镜头(而不是镜头内的镜片)的位置,控制镜头焦距的长短,而实现影像 的清晰.手机中常用的方法。
光学变焦是通过移动镜头内部镜片的相对位置来改变焦点的位置,改变镜头焦距的长短,并改变镜头的视角大小,从而实现影像的放大与缩小;
光学对焦是实际上是调整整个镜头的位置(而不是镜头内的镜片)的位置,来控制像距,从而使成像最清晰。
目前VCM是使用最广泛的对焦方式。
(二)DW9763 马达驱动移植
马达驱动一般比较简单,只需要按照时序控制,设置位置的寄存器即可控制马达移动,这里以RK3588安卓12平台,移植DW9763马达驱动为例,内核版本为kernel-5.10。
①从马达规格书获取控制时序图和控制模式
datesheet一般都有描述马达所支持的控制模式和控制时序,如DW9763就支持,Direct mode和SAC mode,SAC mode分为SAC1,SAC2,SAC2.5,SAC3,SAC4,具体的模式选择有寄存器可以配置:
控制时序一般如下:
- 设置Ringing control寄存器:这个寄存器设置是direct mode还是ringingmode
- 设置具体的SAC mode和DIV
- 设置Tvib
- 向寄存器设置DAC
②驱动实现
驱动的关键点如下:
-
设备资源的获取;RK私有资源定义,命名方式如rockchip,camera-module-xxx,主要是提供设备参数和Camera设备进行匹配。VCM参数定义,命名方式如rockchip,vcm-xxx,主要涉及硬件参数启动电流、额定电流、移动模式,参数跟马达移动的范围和速度相关。
-
entity.function的指定,与camera sensor驱动不同,马达驱动注册的需要指定为:MEDIA_ENT_F_LENS
-
v4l2_subdev_core_ops:设置ioctl回调接口,目前使用了私有的ioctl实现马达移动时间的查询:RK_VIDIOC_VCM_TIMEINFO;;
-
v4l2_ctrl_ops:实现dw9763_get_ctrl和dw9763_set_ctrl,也就是获取和设置马达的位置接口,即对V4L2_CID_FOCUS_ABSOLUTE这个ioctl进行支持。
-
RK AF算法将模组镜头整个可移动行程的位置参数定义为[0,64],模组镜头整个可移动行程在VCM驱动电流上对应的变化范围为[启动电流,额定电流],该函数中建议实现这2者间的映射换算关系;
static int dw9763_set_pos(struct dw9763_device *dev_vcm,
unsigned int dest_pos)
{
int ret;
unsigned int position = 0;
struct i2c_client *client = dev_vcm->client;
u32 is_busy, i;
if (dest_pos >= VCMDRV_MAX_LOG)
position = dev_vcm->start_current;
else
position = dev_vcm->start_current +
(dev_vcm->step * (VCMDRV_MAX_LOG - dest_pos));
if (position > DW9763_MAX_REG)
position = DW9763_MAX_REG;
dev_vcm->current_lens_pos = position;
dev_vcm->current_related_pos = dest_pos;
for (i = 0; i < 100; i++) {
ret = dw9763_read_reg(client, 0x05, 1, &is_busy);
if (!ret && !(is_busy & 0x01))
break;
usleep_range(100, 200);
}
ret = dw9763_write_reg(client, 0x03, 2, dev_vcm->current_lens_pos);
if (ret != 0)
goto err;
dev_dbg(&client->dev,
"%s: set reg val %d\n", __func__, dev_vcm->current_lens_pos);
return ret;
err:
dev_err(&client->dev,
"%s: failed with error %d\n", __func__, ret);
return ret;
}
③dts配置
dts配置参考如下:
dw9763: dw9763@c {
compatible = "dongwoon,dw9763";
status = "okay";
reg = <0x0c>;
rockchip,vcm-max-current = <120>;
rockchip,vcm-start-current = <20>;
rockchip,vcm-rated-current = <90>;
rockchip,vcm-step-mode = <3>;
rockchip,vcm-t-src = <0x20>;
rockchip,vcm-t-div = <1>;
rockchip,camera-module-index = <0>;
rockchip,camera-module-facing = "back";
};
ov13855: ov13855@36 {
......
lens-focus = <&dw9763>;
......
};
vcm-max-current设置最大电流,vcm-start-current设置启动电流,vcm-rated-current设置额定电流,vcm-step-mode设置VCM的模式。
④安卓上层配置
如果支持VCM的话,安卓XML需要添加对应的AFmode支持,camera3_profiles.xml添加如下:
<control.afAvailableModes value="OFF,AUTO,MACRO,CONTINUOUS_VIDEO,CONTINUOUS_PICTURE,EDOF"/>
⑤JSON效果文件配置
效果文件需要打开AF:
⑥调试命令
上述效果文件打开会自动对焦,调试的时候可以将上述关掉,手动使用命令控制马达移动:
v4l2-ctl -d /dev/v4l-subdev3 --set-ctrl 'focus_absolute=64'
v4l2-ctl -d /dev/v4l-subdev3 --set-ctrl 'focus_absolute=0'
(三)总结
VCM马达的控制比较简单,只需要控制位置的寄存器即可,就介绍到此。大家有问题,可以在评论区一起讨论。