博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
飞思卡尔 imx6 GC0308 摄像头驱动配置调试过程
阅读量:6375 次
发布时间:2019-06-23

本文共 5626 字,大约阅读时间需要 18 分钟。

GC0308摄像头驱动程序使用的是linux v4l2协议,通过i2c信号进行控制。GC0308摄像头。对上电时序要求非常严格,一定要依据datasheet初始化摄像头。

本驱动使用的3.10内核,所以首先要配置dts,在内核启动阶段支持摄像头,结合硬件原理图。首先配置硬件接口属性:

pinctrl_ipu1_4: ipu1grp-4 { /*++++  GC0308  camera */            fsl,pins = <                MX6QDL_PAD_GPIO_3__CCM_CLKO2               0x130b0    /*时钟*/                MX6QDL_PAD_CSI0_DAT10__GPIO5_IO28          0x80000000  /*CAM_nRST_CSI0_DAT10*/                MX6QDL_PAD_CSI0_DAT11__GPIO5_IO29          0x80000000 /* DAT11 */ /*CAM_SHDN_CSI0_DAT11*/                MX6QDL_PAD_CSI0_DAT12__IPU1_CSI0_DATA12    0x80000000  /*12-19八条数据线*/                MX6QDL_PAD_CSI0_DAT13__IPU1_CSI0_DATA13    0x80000000                MX6QDL_PAD_CSI0_DAT14__IPU1_CSI0_DATA14    0x80000000                MX6QDL_PAD_CSI0_DAT15__IPU1_CSI0_DATA15    0x80000000                MX6QDL_PAD_CSI0_DAT16__IPU1_CSI0_DATA16    0x80000000                MX6QDL_PAD_CSI0_DAT17__IPU1_CSI0_DATA17    0x80000000                MX6QDL_PAD_CSI0_DAT18__IPU1_CSI0_DATA18    0x80000000                MX6QDL_PAD_CSI0_DAT19__IPU1_CSI0_DATA19    0x80000000                MX6QDL_PAD_CSI0_DATA_EN__IPU1_CSI0_DATA_EN 0x80000000  /* 硬件悬空*/                MX6QDL_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK   0x80000000   /*像素时钟*/                MX6QDL_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC      0x80000000                MX6QDL_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC     0x80000000                >;        };
然后配置摄像头属性:

&i2c3{    clock-frequency = <100000>;    pinctrl-names = "default";    pinctrl-0 = <&pinctrl_i2c3_1>;    status = "okay";    gc0308: gc0308@21{        compatible = "gc0308-capture";        reg = <0x21>;        pinctrl-names = "default";        pinctrl-0 = <&pinctrl_ipu1_4>; /* GC0308  camera*/        clocks = <&clks 201>;        clock-names = "csi_mclk";        DOVDD-supply = <&vgen4_reg>; /* 1.8v */        AVDD-supply = <&vgen3_reg>;  /* 2.8v, on rev C board is VGEN3,                        on rev B board is VGEN5 */        DVDD-supply = <&vgen2_reg>;  /* 1.5v*/        pwn-gpios = <&gpio5 29 1>;   /* active low: SD1_DAT0 */        rst-gpios = <&gpio5 28 0>;   /* active high: SD1_DAT1 */        csi_id = <0>;        mclk = <24000000>;        mclk_source = <0>;    };};
部分内核驱动代码分析:

static const struct i2c_device_id gc0308_id[] = {                                                                         {"gc0308-capture", 0},                                                                                                {},                                                                                                               };                                                                                                                                                                                                                                          MODULE_DEVICE_TABLE(i2c, gc0308_id);

将gc0308_id增加i2c队列。当在dts中有对应名字的设备声明时,调用驱动程序的probe函数。

static struct i2c_driver gc0308_i2c_driver = {    .driver = {          .owner = THIS_MODULE,          .name  = "gc0308-capture",          },    .probe  = gc0308_probe,    .remove = gc0308_remove,    .id_table = gc0308_id,};
驱动程序初始化的时候,增加到i2c设备。

static s32 gc0308_write_reg(u8 reg, u8 val){    u8 au8Buf[3] = {0};    au8Buf[0] = reg;    au8Buf[1] = val;      if (i2c_master_send(gc0308_data.i2c_client, au8Buf, 2) < 0) {        pr_err("%s:write reg error:reg=%x,val=%x\n",            __func__, reg, val);        return -1;    }    return 0;}

static s32 gc0308_read_reg(u8 reg, u8 *val){    u8 au8RegBuf[2] = {0};    u8 u8RdVal = 0;    au8RegBuf[0] = reg;    if (1 != i2c_master_send(gc0308_data.i2c_client, au8RegBuf, 1)) {        pr_err("%s:write reg error:reg=%x\n",                __func__, reg);        return -1;    }    if (1 != i2c_master_recv(gc0308_data.i2c_client, &u8RdVal, 1)) {        pr_err("%s:read reg error:reg=%x,val=%x\n",                __func__, reg, u8RdVal);        return -1;    }    return u8RdVal;}
I2C数据读写

static struct v4l2_int_ioctl_desc gc0308_ioctl_desc[] = {    {vidioc_int_dev_init_num, (v4l2_int_ioctl_func *)ioctl_dev_init},    {vidioc_int_dev_exit_num, ioctl_dev_exit},    {vidioc_int_s_power_num, (v4l2_int_ioctl_func *)ioctl_s_power},    {vidioc_int_g_ifparm_num, (v4l2_int_ioctl_func *)ioctl_g_ifparm},    {vidioc_int_init_num, (v4l2_int_ioctl_func *)ioctl_init},    {vidioc_int_enum_fmt_cap_num,                (v4l2_int_ioctl_func *)ioctl_enum_fmt_cap},    {vidioc_int_g_fmt_cap_num, (v4l2_int_ioctl_func *)ioctl_g_fmt_cap},    {vidioc_int_g_parm_num, (v4l2_int_ioctl_func *)ioctl_g_parm},    {vidioc_int_s_parm_num, (v4l2_int_ioctl_func *)ioctl_s_parm},    {vidioc_int_g_ctrl_num, (v4l2_int_ioctl_func *)ioctl_g_ctrl},    {vidioc_int_s_ctrl_num, (v4l2_int_ioctl_func *)ioctl_s_ctrl},    {vidioc_int_enum_framesizes_num,                (v4l2_int_ioctl_func *)ioctl_enum_framesizes},    {vidioc_int_g_chip_ident_num,                (v4l2_int_ioctl_func *)ioctl_g_chip_ident},};
一系列ioctl函数的指针数组,供应用程序调用。

static int get_device_id(void){    u8 au8RegBuf[2] = {0};    u8 u8RdVal = 0;    au8RegBuf[0] = 0x00;    if (1 != i2c_master_send(gc0308_data.i2c_client, au8RegBuf, 1)) {        pr_err("%s:write reg error:reg=%x\n",                __func__, 0xfb);        return -1;    }    if (1 != i2c_master_recv(gc0308_data.i2c_client, &u8RdVal, 1)) {        pr_err("%s:read reg error:reg=%x,val=%x\n",                __func__, 0xfb, u8RdVal);        return -1;    }    printk(KERN_INFO "u8RdVal=%x\n\n", u8RdVal);    return u8RdVal;}
读取设备ID,详细读ID的指令,依据datasheet确定。

当ID成功读到了。接下来。设置多个摄像头属性,通常做成一个数组。此时摄像头基本能工作了。

当插入驱动模块以后会在/dev/ 文件夹下产生一个videoX 设备。这时候能够使用cheese xawtv等程序进行測试。

转载于:https://www.cnblogs.com/gavanwanggw/p/6854792.html

你可能感兴趣的文章
据说有99%的人都会做错的面试题
查看>>
使用history.pushState()和popstate事件实现AJAX的前进、后退功能
查看>>
【JavaScript】一个同步于本地时间的动态时间
查看>>
js---03属性操作
查看>>
HDU 1231——最大连续子序列(DP)
查看>>
P1739 表达式括号匹配
查看>>
3.1.4 模板字符串
查看>>
redis 介绍和常用命令
查看>>
CPU的段寄存器
查看>>
linux 安装nginx
查看>>
Kettle的概念学习系列之Kettle是什么?(一)
查看>>
Qt 3D教程(二)初步显示3D的内容
查看>>
100行代码实现最简单的基于FFMPEG+SDL的视频播放器(SDL1.x)【转】
查看>>
compareTo返回值为-1 、 1 、 0 的排序问题
查看>>
Being a Good Boy in Spring Festival(杭电1850)(尼姆博弈)
查看>>
微服务间如何选择推送和拉取数据
查看>>
RecyclerView 数据刷新的几种方式 局部刷新 notify MD
查看>>
互联网+时代IT管理者的转型
查看>>
Linux系统调用--getrlimit()与setrlimit()函数详解【转】
查看>>
限制容器的 Block IO - 每天5分钟玩转 Docker 容器技术(29)
查看>>