zoukankan      html  css  js  c++  java
  • 摄像头(Ov965x)驱动分析

    本人喜欢用代码+伪代码的方式写笔记。文中的花括号可能是方便记录而已。

    如:

    hw_get_module(LED_HARDWARE_MODULE_ID, (const hw_module_t**)&module)
    {
        问:怎么获得模块信息的?
        答:hardware\libhardware\Hardware.c

        ...........

    }

    原创分析, 转载请注明出处:http://www.cnblogs.com/langlang/

    作者email: dayhappyhappy@163.com

    module_init(s3c_fimc_register)
        platform_driver_register(&s3c_fimc_driver)  //.name    = "s3c-fimc",
        {
            //1  控制器
            s3c_fimc_register_controller(pdev)
            {
                struct s3c_fimc_control *ctrl;
                ctrl->vd = &s3c_fimc_video_device[id];    //s3c_fimc_video_device中包含了操作函数
                   s3c_fimc_video_device[id]
                    {
                        .fops = &s3c_fimc_fops,//fops对应的是针对v4l2设备的基本操作
                            {
                                .read = s3c_fimc_read
                                {
                                    struct s3c_fimc_control *ctrl = filp->private_data;
                                    end = min_t(size_t, ctrl->out_frame.buf_size, count);
                                    copy_to_user(buf, s3c_fimc_get_current_frame(ctrl), end)
                                     {           
                                        struct s3c_fimc_out_frame *frame = &ctrl->out_frame;
                                        return frame->addr[frame->cfn].virt_y;
                                    }
                                }
                                .open = s3c_fimc_open
                                {
                                    struct s3c_fimc_control *ctrl;
                                    ctrl = &s3c_fimc.ctrl[id];
                                    s3c_fimc_reset(ctrl); //底层寄存器操作
                                    filp->private_data = ctrl;
                                }
                            }
                        .ioctl_ops = &s3c_fimc_v4l2_ops,//是对v4l2的所有ioctl操作集合的描述
                   }
            }
            /*2  时钟设置 fimc source clock */
            //3  DMA初始化
            s3c_fimc_init_global(pdev)
            {
                //DMA设置
                s3c_fimc.dma_start = s3c_get_media_memory(S3C_MDEV_FIMC);
                s3c_fimc.dma_total = s3c_get_media_memsize(S3C_MDEV_FIMC);
                s3c_fimc.dma_current = s3c_fimc.dma_start;
                /* test pattern */
                s3c_fimc.camera[test_pattern.id] = &test_pattern; 
                {
                    问:  这个参数在什么时候用到?
                    s3c_fimc_register_camera(struct s3c_fimc_camera *cam)  ① s3c_fimc_register_camera给谁调用
                    {
                        for (i = 0; i < S3C_FIMC_MAX_CTRLS; i++)  
                            s3c_fimc.ctrl[i].in_cam = s3c_fimc.camera[cam->id];
                    }
                    s3c_fimc_set_active_camera(struct s3c_fimc_control *ctrl, int id)
                    {
                        ctrl->in_cam = s3c_fimc.camera[id];
                        s3c_fimc_select_camera(ctrl);
                    }
                }
            }
            //4  创建文件节点  /dev下看到三个video设备节点,video0,video1,video2
            video_register_device(ctrl->vd, VFL_TYPE_GRABBER, ctrl->id)
            {
                INIT_LIST_HEAD(&vdev->fh_list);
                /* Part 1: check device type */
                /* Part 2: find a free minor, device node number and device index. */    
                /* Part 3: Initialize the character device 创建字符设备*/  
                vdev->cdev = cdev_alloc();
                vdev->cdev->ops = &v4l2_fops;
                cdev_add(vdev->cdev, MKDEV(VIDEO_MAJOR, vdev->minor), 1);
                
                /* Part 4: register the device with sysfs */
                vdev->dev.devt = MKDEV(VIDEO_MAJOR, vdev->minor);
                vdev->dev.class = &video_class;//创建类
                device_register(&vdev->dev);
                video_device[vdev->minor] = vdev;
            }
        }
        
    ① 文件 drivers\media\video\samsung\fimc\Ov965x.c  也就是我们要写的文件
    ov965x_probe(struct i2c_client *c, const struct i2c_device_id *id)
    {
        s3c_fimc_register_camera(&ov965x_data)
        {
            参数:这里面的信息描述了OV9650相关的所有信息。
            static struct s3c_fimc_camera ov965x_data = {
                .id         = CONFIG_VIDEO_FIMC_CAM_CH,
                .type        = CAM_TYPE_ITU,             //type代表摄像头是ITU的接口
                .mode        = ITU_601_YCBCR422_8BIT,    //mode代表摄像头输出的格式是ITU_601_YCBCR422_8BIT
                .order422    = CAM_ORDER422_8BIT_YCBYCR, //order422代表YUV三个分量的顺序是YCRYCB,
                .clockrate    = 24000000,                    //时钟源的信息
                .width        = 640,//800,
                .height        = 480,//600,
                .offset        = {
                    .h1 = 0,
                    .h2 = 0,
                    .v1 = 0,
                    .v2 = 0,
                },
            
                .polarity    = { //Polarity代表信号的极性,具体的设置要和摄像头本身的设置一致
                    .pclk    = 0,
                    .vsync    = 1,
                    .href    = 0,
                    .hsync    = 0,
                },
            
                .initialized    = 0,
            }
        }
    }
     Ov965x.c分析
     __init int ov965x_init(void)
     {
        //添加驱动
        i2c_add_driver(&ov965x_i2c_driver)  
        {
            ov965x_i2c_driver =  {.probe        = ov965x_probe}
            ov965x_probe(struct i2c_client *c, const struct i2c_device_id *id){
                s3c_fimc_register_camera(&ov965x_data);
                for (i = 0; i < OV965X_INIT_REGS; i++) //用IIC发送数据
                    ret = i2c_smbus_write_byte_data(c, OV965X_init_reg[i].subaddr, OV965X_init_reg[i].value);
            }
        }
     } 
  • 相关阅读:
    os模块
    sys模块
    psutil模块
    subprocess模块
    time模块
    argparse模块
    tcp端口扫描(python多线程)
    基于http的软件仓库
    SRE思想
    redis哨兵模式
  • 原文地址:https://www.cnblogs.com/langlang/p/2454271.html
Copyright © 2011-2022 走看看