此文章是S5P6818开发板移植OV5640摄像头的记录
开发平台:DMATEK EIS-680
内核:Linux3.4.39
系统:Android5.0
作者:lyp461340781
此文章记录S5P6818开发板移植OV5640摄像头的过程,可参考此流程在S5P6818开发板上进行其他摄像头的移植。
OV5640摄像头支持DVP接口和MIPI接口,我们平台采用的是DVP接口,即8位并行数据传输。
camera与CPU连接的原理图如下图所示:
1、首先,修改内核中文件,kernel采用NEXELL提供的版本
此处将OV5640初始化为后置摄像头
static struct i2c_board_info back_camera_i2c_boardinfo[] = {
I2C_BOARD_INFO("OV5640", 0x78>>1),
};后置摄像头GPIO控制函数,上电和断电,此函数在下面结构体capture_plat_data[] 中调用
static int back_camera_power_enable(bool on)
{
unsigned int io = CFG_IO_CAMERA_BACK_POWER_DOWN;
unsigned int reset_io = CFG_IO_CAMERA_RESET;
PM_DBGOUT("%s: is_back_camera_enabled %d, on %d\n", __func__, is_back_camera_enabled, on);
if (on) {
front_camera_power_enable(0);
if (!is_back_camera_enabled) {
camera_power_control(1);
//OV5640 add by lyp
/* First RST signal to low */
nxp_soc_gpio_set_out_value(reset_io, 0);
nxp_soc_gpio_set_out_value(io, 1); //ok;hdc 20150718;PN's status is important
mdelay(5);nxp_soc_gpio_set_out_value(io, 0); //ok;hdc 20150718
mdelay(1);
nxp_soc_gpio_set_out_value(reset_io, 1);
mdelay(1);camera_common_set_clock(24000000);
is_back_camera_enabled = true;
mdelay(20);
is_back_camera_power_state_changed = true;
}else
{
is_back_camera_power_state_changed = false;
}
} else {
if (is_back_camera_enabled) {
nxp_soc_gpio_set_out_value(io, 0);
is_back_camera_enabled = false;
is_back_camera_power_state_changed = true;
} else {
nxp_soc_gpio_set_out_value(io, 0);
is_back_camera_power_state_changed = false;
}
if (!(is_back_camera_enabled || is_front_camera_enabled)) {
camera_power_control(0);
}
}return 0;
}该结构体初始化摄像头的一些参数
static struct nxp_capture_platformdata capture_plat_data[] = {
{
.module = 0, //VIP0
.sensor = &sensor[0],
.type = NXP_CAPTURE_INF_PARALLEL,
.parallel = {
.is_mipi = false, //是否采用MIPI接口
.external_sync = false, //是否采用外部同步信号
.h_active = 800,
.h_frontporch = 0,
.h_syncwidth = 0,
.h_backporch = 2,
.v_active = 600,
.v_frontporch = 0,
.v_syncwidth = 0,
.v_backporch = 13,
.clock_invert = false,
.port = 0,
.data_order = NXP_VIN_CBY0CRY1, //输出YUV顺序
.interlace = false,
.clk_rate = 24000000,
.late_power_down = true,
.power_enable = back_camera_power_enable, //电源使能,调用刚才上面的函数
.power_state_changed = back_camera_power_state_changed,
.set_clock = camera_common_set_clock,
.setup_io = camera_common_vin_setup_io,
},
.deci = {
.start_delay_ms = 0,
.stop_delay_ms = 0,
},},
};
移植过程发现OV5640寄存器配置必须支持CCIR656格式输出,即0x4730寄存器的配置。OV5640部分驱动程序如下:
static int ov5640_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
struct ov5640_priv *priv;
struct v4l2_subdev *sd;
int ret;priv = kzalloc(sizeof(struct ov5640_priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
printk("...................................%s %d\n",__func__,__LINE__);
ov5640_priv_init(priv);sd = &priv->subdev;
strcpy(sd->name, MODULE_NAME);//ov5640_video_probe(client);
/* register subdev */
v4l2_i2c_subdev_init(sd, client, &ov5640_subdev_ops);sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
priv->pad.flags = MEDIA_PAD_FL_SOURCE;
sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR;
sd->entity.ops = &ov5640_media_ops;
if (media_entity_init(&sd->entity, 1, &priv->pad, 0)) {
dev_err(&client->dev, "%s: failed to media_entity_init()\n", __func__);
kfree(priv);
return -ENOENT;
}ret = ov5640_initialize_ctrls(priv);
if (ret < 0) {
printk(KERN_ERR "%s: failed to initialize controls\n", __func__);
kfree(priv);
return ret;
}return 0;
}static int ov5640_remove(struct i2c_client *client)
{
struct v4l2_subdev *sd = i2c_get_clientdata(client);
v4l2_device_unregister_subdev(sd);
v4l2_ctrl_handler_free(sd->ctrl_handler);
media_entity_cleanup(&sd->entity);
kfree(to_priv(sd));
return 0;
}static const struct i2c_device_id ov5640_id[] = {
{ MODULE_NAME, 0 },
{ }
};MODULE_DEVICE_TABLE(i2c, ov5640_id);
static struct i2c_driver ov5640_i2c_driver = {
.driver = {
.name = MODULE_NAME,
},
.probe = ov5640_probe,
.remove = ov5640_remove,
.id_table = ov5640_id,
};module_i2c_driver(ov5640_i2c_driver);
MODULE_DESCRIPTION("SoC Camera driver for ov5640");
MODULE_AUTHOR("lyp([email protected])");
MODULE_LICENSE("GPL v2");
2、修改Android系统层
修改NXCameraBoardSensor *get_board_camera_sensor(int id) 函数,
if (id == 0) {
if (!backSensor) {
backSensor = new OV5640(nxp_v4l2_sensor0); //后置摄像头调用OV5640
if (!backSensor)
ALOGE("%s: cannot create BACK Sensor", __func__);
}
sensor = backSensor;
}
OV5640.cpp部分代码如下:(可参考SP2518.cpp进行修改)
修改完成后进行编译烧写测试。
此处只是大概记录一下移植过程,具体的源码下载链接如下:
http://download.csdn.net/detail/lyp461340781/9648855