camera的开机上电分两个流程,一个是内核中camera驱动进行挂载,另一个是用户空间通过ioctrl对内核空间camera驱动进行上电。

驱动挂载:
1.module_init(imgsensor_init); module_init用来进行驱动的加载,传入函数指针imgsensor_init调用imgsensor_init()
2.platform_driver_register(&gimgsensor_platform_driver); 注册平台驱动gimgsensor_platform_driver,gimgsensor_platform_driver内部有一个节点.of_match_table:compatible = "mediatek,imgsensor",这里CONFIG_OF成立,将采用设备树的方式进行匹配,对应kd_camera_hw1,匹配到后就会进行probe操作
static struct platform_driver gimgsensor_platform_driver = {
    .probe   = imgsensor_probe,
    .remove  = imgsensor_remove,
    .suspend = imgsensor_suspend,
    .resume  = imgsensor_resume,
    .driver  = {
           .name  = "image_sensor",
           .owner = THIS_MODULE,
#ifdef CONFIG_OF
           .of_match_table = gimgsensor_of_device_id,
#endif
        }
};
kd_camera_hw1:kd_camera_hw1@1a004000 {
    compatible = "mediatek,imgsensor";
};
3.imgsensor_probe(struct platform_device *pplatform_device)
3.1.struct IMGSENSOR *pimgsensor = &gimgsensor; 创建IMGSENSOR资源
struct IMGSENSOR {
    dev_t dev_no;
    struct cdev *pcdev;
    struct class *pclass;

struct IMGSENSOR_STATUS       status;
    struct IMGSENSOR_HW           hw;
    struct IMGSENSOR_SENSOR       sensor[IMGSENSOR_SENSOR_IDX_MAX_NUM];
    struct IMGSENSOR_SENSOR_LIST *psensor_list[MAX_NUM_OF_SUPPORT_SENSOR];

atomic_t imgsensor_open_cnt;
    enum IMGSENSOR_RETURN (*mclk_set_drive_current)
        (void *pinstance,
        enum IMGSENSOR_SENSOR_IDX sensor_idx,
        enum ISP_DRIVING_CURRENT_ENUM drive_current);
3.2.struct IMGSENSOR_HW *phw = &pimgsensor->hw; 
struct IMGSENSOR_HW {
    struct IMGSENSOR_HW_DEVICE_COMMON common;    平台设备
    struct IMGSENSOR_HW_DEVICE       *pdev[IMGSENSOR_HW_ID_MAX_NUM];    上电方式,对应regulator/gpio等
    struct IMGSENSOR_HW_SENSOR_POWER
                sensor_pwr[IMGSENSOR_SENSOR_IDX_MAX_NUM];
                {
                    struct IMGSENSOR_HW_POWER_INFO *ppwr_info;    哪路供电及供电电压和时序
                    enum   IMGSENSOR_HW_ID          id[IMGSENSOR_HW_PIN_MAX_NUM]; 哪路供电
                };    上电方式及上电时序
    const char *enable_sensor_by_index[IMGSENSOR_SENSOR_IDX_MAX_NUM];
};
};
3.3.
3.4.alloc_chrdev_region(&pimgsensor->dev_no, 0, 1, IMGSENSOR_DEV_NAME) 动态分配设备号,IMGSENSOR_DEV_NAME:kd_camera_hw
3.5.pimgsensor->pcdev = cdev_alloc();    动态申请并分配一个新的字符设备
3.6.cdev_init(pimgsensor->pcdev, &gimgsensor_file_operations);    绑定字符设备及其操作函数
static const struct file_operations gimgsensor_file_operations = {
    .owner          = THIS_MODULE,
    .open           = imgsensor_open,
    .release        = imgsensor_release,
    .unlocked_ioctl = imgsensor_ioctl,
#ifdef CONFIG_COMPAT
    .compat_ioctl   = imgsensor_compat_ioctl
#endif
};
3.7.cdev_add(pimgsensor->pcdev, pimgsensor->dev_no, 1)    绑定了字符设备及其设备号并注册进系统中
3.8.pimgsensor->pclass = class_create(THIS_MODULE, "sensordrv");    态创建设备的逻辑类,在/sys/class/目录下创建一个名为"sensordrv"的文件夹
3.9.pdevice = device_create(pimgsensor->pclass, NULL, pimgsensor->dev_no, NULL, IMGSENSOR_DEV_NAME);    创建设备文件kd_camera_hw,在/dev目录下,通过这个设备文件可以进行读写操作
3.10.pdevice->of_node = of_find_compatible_node(NULL, NULL, "mediatek,imgsensor");    从根节点在设备树中查找"mediatek,imgsensor",返回要查找的节点
3.11.phw->common.pplatform_device = pplatform_device;    pplatform_device为probe传入参数,平台设备
3.12.imgsensor_hw_init(phw);    上电模块初始化
3.12.1.
struct IMGSENSOR_HW_SENSOR_POWER      *psensor_pwr;
struct IMGSENSOR_HW_CFG               *pcust_pwr_cfg;
struct IMGSENSOR_HW_CFG imgsensor_custom_config[] = {
    {
        IMGSENSOR_SENSOR_IDX_MAIN,
        IMGSENSOR_I2C_DEV_0,
        {
            {IMGSENSOR_HW_PIN_MCLK,  IMGSENSOR_HW_ID_MCLK},    ppwr_info{IMGSENSOR_HW_PIN, IMGSENSOR_HW_ID}
            {IMGSENSOR_HW_PIN_AVDD,  IMGSENSOR_HW_ID_GPIO},
            {IMGSENSOR_HW_PIN_DOVDD, IMGSENSOR_HW_ID_REGULATOR},
            {IMGSENSOR_HW_PIN_DVDD,  IMGSENSOR_HW_ID_GPIO},
            {IMGSENSOR_HW_PIN_PDN,   IMGSENSOR_HW_ID_GPIO},
            {IMGSENSOR_HW_PIN_RST,   IMGSENSOR_HW_ID_GPIO},
            {IMGSENSOR_HW_PIN_NONE,  IMGSENSOR_HW_ID_NONE},
        }
    {
    ...
}        
struct IMGSENSOR_HW_CUSTOM_POWER_INFO *ppwr_info;
    {IMGSENSOR_HW_PIN_MCLK,  IMGSENSOR_HW_ID_MCLK}
struct device_node *of_node = of_find_compatible_node(NULL, NULL, "mediatek,imgsensor");
3.12.2.遍历设置的IMGSENSOR_SENSOR_IDX_MAX_NUM,根据cameraidx依次进行上电结构体的匹配赋值
pcust_pwr_cfg = imgsensor_custom_config;    拿到imgsensor_cfg_table.c中填入的pcust_pwr_cfg = imgsensor_custom_config的地址/*这里是bringup需要客制化的地方*/,就是平台提供的各路供电接口及其上电方式,比如上面的IMGSENSOR_SENSOR_IDX_MAIN使用i2c为IMGSENSOR_I2C_DEV_0,avdd使用gpio进行供电,iovdd使用regulator进行供电。通过pcust_pwr_cfg地址+1的方式拿取第二第三颗sensor。
snprintf(str_prop_name, izeof(str_prop_name), "cam%d_pin_%s", i, imgsensor_hw_pin_names[ppwr_info->pin]);    根据ppwr_info->pin比如上面定义的IMGSENSOR_HW_PIN_AVDD得到str_prop_name="cam0_pin_vcama"。
of_property_read_string(of_node, str_prop_name, &pin_hw_id_name)    在设备树中寻找cam0_pin_vcama并返回对应的pin_hw_id_name:gpio
再循环IMGSENSOR_HW_ID_MAX_NUM(mclk/regulator/gpio),如果上面返回的pin_hw_id_name==这个检索(mclk/regulator/gpio),ppwr_info->id = 这个检索,ppwr_info->pin=3(avdd),ppwr_info->id=2(gpio)    
具体没懂3.12.2.这个操作的意义是什么,相比v1多了个对dts的检索操作,本来imgsensor_custom_config这个表格就已经将avdd和gpio匹配了
3.12.3.遍历IMGSENSOR_HW_ID_MAX_NUM(mclk/regulator/gpio)调用各自init
3.12.4.遍历设置的IMGSENSOR_SENSOR_IDX_MAX_NUM
***psensor_pwr = &phw->sensor_pwr[i];    将IMGSENSOR_HW_SENSOR_POWER赋给psensor_pwr,这个结构体实际就是将imgsensor_custom_config的每路的供电方式和这路供电的电压/延时绑定在了一起
struct IMGSENSOR_HW_SENSOR_POWER {
    struct IMGSENSOR_HW_POWER_INFO *ppwr_info;    {哪路供电,电压,延时}
    enum   IMGSENSOR_HW_ID          id[IMGSENSOR_HW_PIN_MAX_NUM];    供电方式
};
pcust_pwr_cfg = imgsensor_custom_config;    根据cameraidx依次进行上电结构体的匹配赋值
ppwr_info = pcust_pwr_cfg->pwr_info;    拿到imgsensor_custom_config中IMGSENSOR_HW_PIN和IMGSENSOR_HW_ID的匹配关系(avdd通过gpio上电)
while (ppwr_info->pin != IMGSENSOR_HW_PIN_NONE) {
    for (j = 0; j < IMGSENSOR_HW_ID_MAX_NUM && ppwr_info->id != phw->pdev[j]->id; j++) {}    遍历IMGSENSOR_HW_ID(mclk/regulator/gpio)
            psensor_pwr->id[ppwr_info->pin] = j;    ***这里保存了每一路的供电方式和这路供电的电压/延时给到&phw->sensor_pwr[i]供后续上电使用
            ppwr_info++;
}

3.12.5.在dts中读取cam0_enable_sensor返回给phw->enable_sensor_by_index    就是sensor name

3.13.imgsensor_i2c_create();    各sensor i2c注册
i2c_add_driver(&gi2c_driver[i]);
static struct i2c_driver gi2c_driver[IMGSENSOR_I2C_DEV_MAX_NUM] = {
    {
        .probe = imgsensor_i2c_probe_0,
        .remove = imgsensor_i2c_remove,
        .driver = {
        .name = IMGSENSOR_I2C_DRV_NAME_0,
        .owner = THIS_MODULE,
#ifdef CONFIG_OF
        .of_match_table = gof_device_id_0,    匹配dws中IMGSENSOR_I2C_OF_DRV_NAME_0("mediatek,camera_main"),dws中配置了camera_main的i2c地址
#endif
        },
        .id_table = gi2c_dev_id,
    },
    ...
}
3.14.imgsensor_proc_init();    创建一个proc虚拟文件,应用层通过读写该文件,即可实现与内核的交互
3.15.imgsensor_init_sensor_list();
struct IMGSENSOR             *pimgsensor   = &gimgsensor;
struct IMGSENSOR_SENSOR_LIST *psensor_list =  gimgsensor_sensor_list;    获取sensorlist,客制化地方,加入需要的sensor
of_property_read_string(of_node, "cust-sensor", &penable_sensor);    在of_node("mediatek,imgsensor")节点中寻找cust-sensor返回给penable_sensor,在gimgsensor_sensor_list中找到与penable_sensor一致的sensor,由于gimgsensor是全局的引用,所以最终一致的sensor会存在gimgsensor.psensor_list中
至此,camera驱动挂载与初始化完成

上电
camera的上电是在开机时cameraprovider起来时通过searchSensor调用的,kernel的调用从imgsensor_ioctl()开始
1.adopt_CAMERA_HW_FeatureControl()
struct IMGSENSOR_SENSOR *psensor;    包含SENSOR_INST和SENSOR_FUNCTION
psensor = imgsensor_sensor_get_inst(pFeatureCtrl->InvokeCamera);    根据上层传下来的cameraid返回底层的psensor
psensor->inst.sensor_idx = pFeatureCtrl->InvokeCamera;    拿到底层的cameraid
v1通过这里遍历去给各sensoridx上电
1.1.imgsensor_set_driver()
struct IMGSENSOR             *pimgsensor   = &gimgsensor;
struct IMGSENSOR_SENSOR_INST *psensor_inst = &psensor->inst;
v1_1通过这里遍历MAX_NUM_OF_SUPPORT_SENSOR给各sensor上电
pimgsensor->psensor_list[i]->init(&psensor->pfunc);    拿到sensor的函数指针
psensor_inst->psensor_list = pimgsensor->psensor_list[i];    将gimgsensor之前在imgsensor_init_sensor_list()拿到的sensorlist赋给psensor_inst->psensor_list
2.imgsensor_check_is_alive(psensor)
struct IMGSENSOR *pimgsensor = &gimgsensor;
struct IMGSENSOR_SENSOR_INST *psensor_inst = &psensor->inst;
2.1.imgsensor_hw_power(&pimgsensor->hw, psensor, IMGSENSOR_HW_POWER_STATUS_ON);    传入IMGSENSOR_HW_POWER_STATUS_ON为上电
2.1.1.imgsensor_hw_power_sequence(phw, sensor_idx, pwr_status, sensor_power_sequence, curr_sensor_name);    sensor_power_sequence是客制化的上电时序
struct IMGSENSOR_HW_SENSOR_POWER *psensor_pwr = &phw->sensor_pwr[sensor_idx];    获取之前拿到的上电配置(哪路电使用哪种上电方式,上电电压是多少,上电延时)
struct IMGSENSOR_HW_POWER_SEQ    *ppwr_seq = ppower_sequence;
strcmp(ppwr_seq->name, pcurr_idx)    遍历上电时序表ppower_sequence,根据传入的sensor的name,匹配一致拿取这个sensor的时序表
ppwr_info = ppwr_seq->pwr_info;
遍历需要上电模组的上电时序表ppower_sequence里的ppwr_info->pin 
pdev = phw->pdev[psensor_pwr->id[ppwr_info->pin]];    拿到之前init时保存的这个pin所对应的上电方式(id:mclk/regulator/mclk)的dev
pdev->set(pdev->pinstance, sensor_idx, ppwr_info->pin/*pin脚*/, ppwr_info->pin_state_on/*上电电压*/);    到各自上电模块dev中进行set上电
mdelay(ppwr_info->pin_on_delay);    delay延时
至此完成上电
2.2.imgsensor_sensor_feature_control(psensor, SENSOR_FEATURE_CHECK_SENSOR_ID, (MUINT8 *) &sensorID, &retLen);    调用sensor驱动get_imgsensor_id接口获取sensor id
2.3.mgsensor_hw_power(&pimgsensor->hw, psensor, IMGSENSOR_HW_POWER_STATUS_OFF);    下电

1.2.psensor_list->id = psensor->inst.psensor_list->id;
memcpy(psensor_list->name, psensor->inst.psensor_list->name, 32);

Regulator
regulator_init()
1.struct REGULATOR *preg //创建 REGULATOR,其中包含其regulator设备以及原子锁count
struct regulator {
    struct device *dev;
    struct list_head list;
    unsigned int always_on:1;
    unsigned int bypass:1;
    int uA_load;
    int min_uV;
    int max_uV;
    const char *supply_name;
    struct device_attribute dev_attr;
    struct regulator_dev *rdev;
    struct dentry *debugfs;
};
2.根据底层IMGSENSOR_SENSOR_IDX以及自身定义的regulator_control(vcama/vcamd/vcamio)获取所有的cam和三路电的排列组合,组合成str_regulator_name(cam0_vcama),regulator_get_optional通过dev以及str_regulator_name获取regulator资源regulator[idx][type]供后续上下电使用,cam0_vcama对应dtsi中的kd_camera_hw1,kd_camera_hw1将其各路电和引脚绑定,这里cam0_vcamio是regulator供电,cam0_vcamio-supply = <&mt_pmic_vcamio_ldo_reg>;其他的都是gpio供电

regulator_set()
1.imgsensor_hw.c的imgsensor_hw_power_sequence()将sensor_idx,pin哪路电和电压传入regulator_set()
2.regulator中只定义了vcama(0),vcamd(1),vcamio(2)三路电,但是在cfg_table中除了regulator上电还会有其他上电方式的enum,所以传入的上电方式enum和regulator的上电方式enum存在偏移量IMGSENSOR_HW_PIN_AVDD
reg_type_offset = REGULATOR_TYPE_VCAMA;//REGULATOR_TYPE_VCAMA为0,不知道具体作用?
pregulator = preg->pregulator[(unsigned int)sensor_idx][reg_type_offset + pin - IMGSENSOR_HW_PIN_AVDD];

regulator的上电enum:
enum REGULATOR_TYPE {
    REGULATOR_TYPE_VCAMA,
    REGULATOR_TYPE_VCAMD,
    REGULATOR_TYPE_VCAMIO,
    REGULATOR_TYPE_MAX_NUM
}
cfg_table的上电enum:
前三个对于regulator是无用的,所以偏移就为IMGSENSOR_HW_PIN_AVDD 3
enum IMGSENSOR_HW_PIN {
    IMGSENSOR_HW_PIN_NONE = 0,
    IMGSENSOR_HW_PIN_PDN,
    IMGSENSOR_HW_PIN_RST,
    IMGSENSOR_HW_PIN_AVDD,
    IMGSENSOR_HW_PIN_DVDD,
    IMGSENSOR_HW_PIN_DOVDD,
}
3.绑定了regulator后regulator_set_voltage(regulator, min voltage, max voltage),regulator_enable(pregulator)完成上电

gpio
gpio_init()
1.同样创建gpio设备
2.devm_pinctrl_get通过dev获取pinctrl资源节点
3.根据IMGSENSOR_SENSOR_IDX和gpio_pinctrl_list_cam(ldo_vcama_1)获取所有排列组合组合成str_pinctrl_name(cam0_ldo_vcama_1)
4.pinctrl_lookup_state根据pinctrl资源和str_pinctrl_name获取gpio资源gpio->ppinctrl_state_cam[j][i]供后续上下电使用,同样也是在kd_camera_hw1中

gpio_set()
1.获取传下来的电压值gpio_state,非0为GPIO_STATE_H, 0为GPIO_STATE_L
2.ppinctrl_state = pgpio->ppinctrl_state_cam[sensor_idx][((pin - IMGSENSOR_HW_PIN_PDN) << 1) + gpio_state]; //gpio的enum相较于cfg_table的多了low和high,所以会有这个移位操作?
上下电取决于gpio_state,上电获取ppinctrl_state_cam[0]的GPIO_CTRL_STATE_RST_L,下电为GPIO_CTRL_STATE_RST_H
3.pinctrl_select_state(pgpio->ppinctrl, ppinctrl_state); pinctrl_select_state通过pinctrl资源和ppinctrl_state进行状态的选择

MTK CAMERA ISP6S Kernel相关推荐

  1. mtk camera 移植步骤

    mtk camera 移植步骤: 1, Kernel层驱动代码文件添加 /mediatek/custom/doov92_wet_tdd/kernel/imgsensor/下添加imx179_mipi_ ...

  2. MTK Camera 基础知识

    文章目录 数字成像系统流程综述 曝光 对焦马达 镜头(lens) MIPI数据与RAW数据的转换(未完待续) ISP的主要内容和Bayer Raw的处理 RGB.YUV和YCbCr三种颜色空间 补充 ...

  3. MTK平台开机初始化时 camera驱动流程|MTK camera调试常见几十种问题处理方法

    转载:https://www.jianshu.com/p/75ab1d82bbd3 mtk的驱动多是以模块加载的方式(module_init():module_exit():)加载到内核中去的:正因为 ...

  4. MTK camera flashlight bring up

    MTK camera flashlight bring up MTK camera flashlight bring up 一查看硬件原理图 front camera rear camera key ...

  5. MTK Camera驱动移植

    对于MTK Camera驱动移植一般分为四部分: 1.硬件IO口配置: 2.Camera驱动移植: 3.上电时序: 4.修改i2c控制器: 硬件电路: 1.GPIO配置 打开 mediatek\dct ...

  6. mtk camera移植

    mtk camera 移植步骤: 1, Kernel层驱动代码文件添加 /mediatek/custom/doov92_wet_tdd/kernel/imgsensor/下添加imx179_mipi_ ...

  7. 【Mtk Camera Hal到驱动的流程(1)】

    Mtk Camera Hal到驱动的流程(1) (1)架构介绍 (A)Camera 的框架分为 Kernel 部分和 Hal 部分 Kernel部分: image sensor driver -- 负 ...

  8. Camera4 MTK camera驱动结构介绍

    一.概述: MTK  camera主要的内容在hal层,现在有hal1/hal3,当下主流的使用的是hal3,驱动主要负责sensor 电源的控制以及sensor相关寄存器的操作,MTK采用设备和驱动 ...

  9. Mtk Camera中Hal1/Hal3的Picture size和Preview size配置

    在进行camera系统开发时,总会碰到产品需要,需要一个添加一个多少多少M的照片大小,比如产品经理说我们也要添加一个1:1,添加一个18:9的照片大小.这个情况很常见了,所以这篇文章总结一下平常工作中 ...

最新文章

  1. hdu 5087(LIS变形)
  2. OSPF地址汇总配置
  3. 算法-低位优先的字符串排序
  4. rbf java_RBF网络
  5. 保存特定模式的snp文件
  6. 开源的项目管理软件——OpenProj
  7. vue实现中英文切换
  8. 香槟分校计算机研究生专业,伊利诺伊大学香槟分校计算机科学专业各大方向介绍...
  9. 怎么用计算机直接截图,电脑怎么截图?使用电脑截图的多种方法
  10. 10电脑睡眠后自动关机怎么回事 win_win10睡眠变自动关机怎么办
  11. 【Recsys2021】推荐系统论文整理和导读
  12. 单工通信、半双工通信、全双工通信 的概念
  13. java 调用麦克风录音_Java 实现麦克风自动录音
  14. js刻度尺插件_js滑块刻度尺插件
  15. 网络钓鱼技术解析与安全防护措施
  16. 正态分布随机数是什么
  17. 矿产资源利用现状调查成果与矿产资源储量库衔接软件
  18. 了解报表开发证书——FCRP
  19. 常用电子元器件的特性及使用办法
  20. (一)计算机网络课程设计教学大纲

热门文章

  1. origin绘图软件安装包下载安装,Origin软件2022版特色功能使用
  2. 董明珠直播从翻车到3小时卖3亿是其半生写照:极度渴望成功,愿付非凡代价
  3. 给局域网中的计算机发消息,要如何给局域网电脑发消息的方法
  4. 原生JavaScript实现选项卡
  5. iot物联网_使用IoT原型板开始物联网
  6. 2020压力管道巡检维护考试软件及压力管道巡检维护操作证考试
  7. 华为又来黑马招聘了!薪资待遇令人眼馋!
  8. 5G+工业互联网丨DolphinDB携手诺基亚贝尔打造高精度实时计算平台
  9. 2022-2028全球与中国海底歧管市场现状及未来发展趋势
  10. mysql 表空间修改_mysql8 参考手册--调整系统表空间