S5P6818开发板移植OV5640摄像头



此文章是S5P6818开发板移植OV5640摄像头的记录

开发平台:DMATEK  EIS-680

内核:Linux3.4.39

系统:Android5.0

作者:lyp461340781


此文章记录S5P6818开发板移植OV5640摄像头的过程,可参考此流程在S5P6818开发板上进行其他摄像头的移植。

OV5640摄像头支持DVP接口和MIPI接口,我们平台采用的是DVP接口,即8位并行数据传输。

camera与CPU连接的原理图如下图所示:


1、首先,修改内核中文件,kernel采用NEXELL提供的版本

  • 修改内核中初始化配置文件\kernel\arch\arm\plat-s5p6818\dmatek\device.c

此处将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驱动程序的修改

移植过程发现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系统层

  • 修改BSP包目录下找device\nexell\dmatek_s5p6818\camera\board-camera.cpp

修改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;
    }

  • 在BSP包目录下找hardware\samsung_slsi\slsiap\libcamerasensor目录,在libcamerasensor目录下创建OV5640.cpp和OV5640.h

OV5640.cpp部分代码如下:(可参考SP2518.cpp进行修改)


修改完成后进行编译烧写测试。


此处只是大概记录一下移植过程,具体的源码下载链接如下:

http://download.csdn.net/detail/lyp461340781/9648855





你可能感兴趣的:(Android系统开发,linux驱动开发)