MTK camera驱动浅析(2)

这篇具有很好参考价值的文章主要介绍了MTK camera驱动浅析(2)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一.主要文件

kernel-4.19/drivers/misc/mediatek/imgsensor/src/common/v1/imgsensor_hw.c

1.1 主要函数

imgsensor_hw.c共计就四个函数:

  • imgsensor_hw_init
  • imgsensor_hw_power
  • imgsensor_hw_power_sequence
  • imgsensor_hw_release_all

看名字就可以知道函数实现的功能。

1.2 上电相关的结构体

MTK camera驱动浅析(2) 

  • pdev[IMGSENSOR_HW_ID_MAX_NUM]这个结构体指针数组用来保存控制上电方式的设备(gpio/regulator)和控制时钟相关的设备,这个结构主要保存了一些函数指针,用来调用设备的init、set等方法。

MTK camera驱动浅析(2) 

  • sensor_pwr[IMGSENSOR_SENSOR_IDX_MAX_NUM]用来保存上电方式和上电顺序等信息,这是一个数组,可以保存多个sensor的信息。
    ppwr_info保存pin的信息,比如状态,延迟等,指针类型,通过加减操作移动到下一个位置,和数组差不多,能保存多个pin。
    id[]数组用来保存每个pin的上电方式。

MTK camera驱动浅析(2)

 

二.上电流程

2.1 imgsensor_hw_init()

在probe()函数中已经初始化上电所需要的信息,用到了imgsensor_hw_init()函数:

enum IMGSENSOR_RETURN imgsensor_hw_init(struct IMGSENSOR_HW *phw) {
    struct IMGSENSOR_HW_SENSOR_POWER *psensor_pwr;
    struct IMGSENSOR_HW_CFG *pcust_pwr_cfg;
    struct IMGSENSOR_HW_CUSTOM_POWER_INFO *ppwr_info;
    int i, j;
    char str_prop_name[LENGTH_FOR_SNPRINTF];//LENGTH_FOR_SNPRINTF 256
    struct device_node *of_node
            = of_find_compatible_node(NULL, NULL, "mediatek,camera_hw");

    /* 初始化pdev数组,绑定上电和时钟控制设备 */
    for (i = 0; i < IMGSENSOR_HW_ID_MAX_NUM; i++) {//IMGSENSOR_HW_ID_MAX_NUM 3
        if (hw_open[i] != NULL)
            (hw_open[i])(&phw->pdev[i]);

        if (phw->pdev[i]->init != NULL)
            (phw->pdev[i]->init)(phw->pdev[i]->pinstance);
    }

    for (i = 0; i < IMGSENSOR_SENSOR_IDX_MAX_NUM; i++) {//IMGSENSOR_SENSOR_IDX_MAX_NUM 3
        psensor_pwr = &phw->sensor_pwr[i];

        pcust_pwr_cfg = imgsensor_custom_config;
        while (pcust_pwr_cfg->sensor_idx != i &&
               pcust_pwr_cfg->sensor_idx != IMGSENSOR_SENSOR_IDX_NONE)//IMGSENSOR_SENSOR_IDX_NONE 6
            pcust_pwr_cfg++;

        if (pcust_pwr_cfg->sensor_idx == IMGSENSOR_SENSOR_IDX_NONE)
            continue;

        ppwr_info = pcust_pwr_cfg->pwr_info;
        while (ppwr_info->pin != IMGSENSOR_HW_PIN_NONE) {//IMGSENSOR_HW_PIN_NONE 0
            for (j = 0; j < IMGSENSOR_HW_ID_MAX_NUM; j++)//IMGSENSOR_HW_ID_MAX_NUM 3
                if (ppwr_info->id == phw->pdev[j]->id)
                    break;

            psensor_pwr->id[ppwr_info->pin] = j;
            ppwr_info++;
        }
    }

    /* 读设备树,? */
    for (i = 0; i < IMGSENSOR_SENSOR_IDX_MAX_NUM; i++) {
        memset(str_prop_name, 0, sizeof(str_prop_name));
        snprintf(str_prop_name,
                 sizeof(str_prop_name),
                 "cam%d_%s",
                 i,
                 "enable_sensor");
        if (of_property_read_string(
                of_node,
                str_prop_name,
                &phw->enable_sensor_by_index[i]) < 0) {
            pr_info("Property cust-sensor not defined\n");
            phw->enable_sensor_by_index[i] = NULL;
        }
    }
    return IMGSENSOR_RETURN_SUCCESS;
}

分析这个函数,依次做了下面这些事:

1.第一个for循环初始化了pdev数组,绑定上电和时钟控制设备。程序中hw_open数组定义如下:

enum IMGSENSOR_RETURN
(*hw_open[IMGSENSOR_HW_ID_MAX_NUM])(struct IMGSENSOR_HW_DEVICE **) = {
        imgsensor_hw_regulator_open,
        imgsensor_hw_gpio_open,
        imgsensor_hw_mclk_open
};

也就是保存了三个函数指针,调用这三个函数就可以初始化pdev数组,例如imgsensor_hw_regulator_open()函数定义如下:

static struct IMGSENSOR_HW_DEVICE device = {
        .pinstance = (void *) &reg_instance,
        .init      = regulator_init,
        .set       = regulator_set,
        .release   = regulator_release,
        .id        = IMGSENSOR_HW_ID_REGULATOR
};

enum IMGSENSOR_RETURN imgsensor_hw_regulator_open(
        struct IMGSENSOR_HW_DEVICE **pdevice) {
    *pdevice = &device;
    return IMGSENSOR_RETURN_SUCCESS;
}

可以看到就是绑定了一些操作函数,通过对某个pin脚调用set函数就可以完成对它的上电操作。

2.第二个for循环是为sensor设置上电顺序,前面提到的enum IMGSENSOR_HW_ID id[IMGSENSOR_HW_PIN_MAX_NUM]数组就保存了当前sensor引脚的上电方式。 

分析代码,这里有一个数组imgsensor_custom_config[ ],它的作用是配置sensor每个引脚的上电方式,在imgsensor_cfg_table.c中:

struct IMGSENSOR_HW_CFG imgsensor_custom_config[] = {
        {
                IMGSENSOR_SENSOR_IDX_MAIN,//sensor_id
                IMGSENSOR_I2C_DEV_0,//sensor_i2c dev
                {           
                        //上电方式                                      pin脚
                        {IMGSENSOR_HW_ID_MCLK, IMGSENSOR_HW_PIN_MCLK},
                        {IMGSENSOR_HW_ID_REGULATOR, IMGSENSOR_HW_PIN_AVDD},
                        {IMGSENSOR_HW_ID_REGULATOR, IMGSENSOR_HW_PIN_DOVDD},
                        {IMGSENSOR_HW_ID_GPIO,      IMGSENSOR_HW_PIN_DVDD},
                        {IMGSENSOR_HW_ID_GPIO, IMGSENSOR_HW_PIN_PDN},
                        {IMGSENSOR_HW_ID_GPIO, IMGSENSOR_HW_PIN_RST},
                        {IMGSENSOR_HW_ID_NONE, IMGSENSOR_HW_PIN_NONE},
                },
        },
        /* 省略部分代码 */
};

首先通过第一个while循环将sensorid和当前要操作的sensor对应起来,然后通过第二个while循环来拿到imgsensor_custom_config[]中的上电方式,将这个上电方式与一开始初始化的pdev中的设备对应起来,得到pdev对应设备的索引 j ,最后通过赋值操作把上电方式和引脚保存到enum IMGSENSOR_HW_ID id[IMGSENSOR_HW_PIN_MAX_NUM]这个数组中,匹配结果如下:

MTK camera驱动浅析(2)

 3.最后一个for循环读设备树,读到的是sensor的名字,在后面imgsensor_hw_power()函数会进行字符串匹配验证,这里的作用以后在探究。

2.2imgsensor_hw_power()

就是用来上电的函数:

enum IMGSENSOR_RETURN imgsensor_hw_power(
        struct IMGSENSOR_HW *phw,
        struct IMGSENSOR_SENSOR *psensor,
        char *curr_sensor_name,
        enum IMGSENSOR_HW_POWER_STATUS pwr_status) {
    enum IMGSENSOR_SENSOR_IDX sensor_idx = psensor->inst.sensor_idx;
    char str_index[LENGTH_FOR_SNPRINTF];
    int ret = 0;

    pr_info(
            "sensor_idx %d, power %d curr_sensor_name %s, enable list %s\n",
            sensor_idx,
            pwr_status,
            curr_sensor_name,
            phw->enable_sensor_by_index[(uint32_t) sensor_idx] == NULL
            ? "NULL"
            : phw->enable_sensor_by_index[(uint32_t) sensor_idx]);

    if (phw->enable_sensor_by_index[(uint32_t) sensor_idx] &&
        !strstr(phw->enable_sensor_by_index[(uint32_t) sensor_idx], curr_sensor_name))
        return IMGSENSOR_RETURN_ERROR;


    ret = snprintf(str_index, sizeof(str_index), "%d", sensor_idx);
    if (ret == 0) {
        pr_info("Error! snprintf allocate 0");
        ret = IMGSENSOR_RETURN_ERROR;
        return ret;
    }

    imgsensor_hw_power_sequence(
            phw,
            sensor_idx,
            pwr_status,
            platform_power_sequence,
            str_index);

    imgsensor_hw_power_sequence(
            phw,
            sensor_idx,
            pwr_status,
            sensor_power_sequence,
            curr_sensor_name);

    return IMGSENSOR_RETURN_SUCCESS;
}

这个函数主要就调用了imgsensor_hw_power_sequence(),这里调用了两次,主要是第四个参数不同,platform_power_sequence[]配置的是平台上电顺序,sensor_power_sequence[]配置的是sensor上电顺序,它们都在imgsensor_cfg_table.c中。在某个sensor上电的时候会匹配上其中一种进行上电。

2.3 imgsensor_hw_power_sequence()

static enum IMGSENSOR_RETURN imgsensor_hw_power_sequence(
        struct IMGSENSOR_HW *phw,
        enum IMGSENSOR_SENSOR_IDX sensor_idx,
        enum IMGSENSOR_HW_POWER_STATUS pwr_status,
        struct IMGSENSOR_HW_POWER_SEQ *ppower_sequence,
        char *pcurr_idx) {
    struct IMGSENSOR_HW_SENSOR_POWER *psensor_pwr =
            &phw->sensor_pwr[sensor_idx];

    struct IMGSENSOR_HW_POWER_SEQ *ppwr_seq = ppower_sequence;
    struct IMGSENSOR_HW_POWER_INFO *ppwr_info;
    struct IMGSENSOR_HW_DEVICE *pdev;
    int pin_cnt = 0;

    /* 匹配上电的方式,是platform还是sensor */
    while (ppwr_seq < ppower_sequence + IMGSENSOR_HW_SENSOR_MAX_NUM &&
           ppwr_seq->name != NULL) {
        if (!strcmp(ppwr_seq->name, PLATFORM_POWER_SEQ_NAME)) {
            if (sensor_idx == ppwr_seq->_idx)
                break;
        } else {
            if (!strcmp(ppwr_seq->name, pcurr_idx))
                break;
        }
        ppwr_seq++;
    }

    if (ppwr_seq->name == NULL) {
        return IMGSENSOR_RETURN_ERROR;
    }

    ppwr_info = ppwr_seq->pwr_info;

    /* 依次为pin上电 */
    while (ppwr_info->pin != IMGSENSOR_HW_PIN_NONE &&
           ppwr_info < ppwr_seq->pwr_info + IMGSENSOR_HW_POWER_INFO_MAX) {

        if (pwr_status == IMGSENSOR_HW_POWER_STATUS_ON &&
            ppwr_info->pin != IMGSENSOR_HW_PIN_UNDEF) {
            /* 匹配上电的设备,是gpio还是regulator等等 */
            pdev = phw->pdev[psensor_pwr->id[ppwr_info->pin]];

            if (pdev->set != NULL)
                /* 调用设备的set()进行上电 */
                pdev->set(
                        pdev->pinstance,
                        sensor_idx,
                        ppwr_info->pin,
                        ppwr_info->pin_state_on);

            mdelay(ppwr_info->pin_on_delay);
        }

        ppwr_info++;
        pin_cnt++;
    }
    
    /* 下电方式类似 */
    if (pwr_status == IMGSENSOR_HW_POWER_STATUS_OFF) {
        while (pin_cnt) {
            ppwr_info--;
            pin_cnt--;

            if (ppwr_info->pin != IMGSENSOR_HW_PIN_UNDEF) {
                pdev =
                        phw->pdev[psensor_pwr->id[ppwr_info->pin]];
                mdelay(ppwr_info->pin_on_delay);

                if (pdev->set != NULL)
                    pdev->set(
                            pdev->pinstance,
                            sensor_idx,
                            ppwr_info->pin,
                            ppwr_info->pin_state_off);
            }
        }
    }

    /* wait for power stable */
    if (pwr_status == IMGSENSOR_HW_POWER_STATUS_ON)
        mdelay(5);
    return IMGSENSOR_RETURN_SUCCESS;
}

这里匹配上电的设备就用到了上面那个id[]数组,通过pin的序号拿到其上电所需要的对应的设备,然后set即可完成上电。

暂时写到这里,别的后面在写,希望大家提出意见,共同学习。文章来源地址https://www.toymoban.com/news/detail-435763.html

到了这里,关于MTK camera驱动浅析(2)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【项目 计网6】 4.17 TCP三次握手 4.18滑动窗口 4.19TCP四次挥手

    TCP 是一种 面向连接 的单播协议,在发送数据前,通信双方必须在彼此间建立一条连接。所谓的“连接”,其实是客户端和服务器的内存里保存的一份关于对方的信息,如 IP 地址、端口号等。 TCP 可以看成是一种字节流,它会处理 IP 层或以下的层的丢包、重复以及错误问题。

    2024年02月10日
    浏览(43)
  • mtk log、kernel log、adb log的详细使用

    打印MTK log,里面就包含了kernel层的log,像我们adb log打印的是上层应用的log,mtk log打印的则是更底层的log。 那么什么时候需要用到mtk log 呢? 就比如你想抓一些从关机到开机的log,这个kernel log也可以抓的到,但是adb log抓不到。 那mtk log和kernel log和adb log有什么区别呢? mtkl

    2024年02月09日
    浏览(34)
  • 【MTK平台】根据kernel log分析wifi scan的时候流程

    一 概要: 本文主要讲解根据kernel log分析下 当前路径下(vendor/mediatek/kernel_modules/connectivity/wlan/core/gen4m/)wifi scan的时候代码流程 二. Log分析: 先看Log: 2.1)在Framework层WifiManager.java 方法中,做了一个标记,可以精准的确认时间 这段log可以看出11:03:14.979502时候设置界面开始扫

    2024年02月10日
    浏览(77)
  • Android 12.0 MTK Camera2 设置默认拍照尺寸功能实现

    在12.0的系统rom定制化开发中,在mtk平台的camera2关于拍照的一些功能修改中,在一些平台默认需要设置最大的分辨率 来作为拍照的分辨率,所以就需要了解拍照尺寸设置流程,然后来实现相关的功能 如图:

    2024年02月20日
    浏览(78)
  • Android 11.0 MTK Camera2 设置默认拍照尺寸功能实现

    在11.0的系统rom定制化开发中,在mtk平台的camera2关于拍照的一些功能修改中,在一些平台默认需要设置最大的分辨率 来作为拍照的分辨率,所以就需要了解拍照尺寸设置流程,然后来实现相关的功能 如图: Camera API中主要涉及以下几个关键类 CameraManager:相机的实际管理者,调

    2024年01月21日
    浏览(62)
  • 第1讲 Camera Sensor Driver课程简介

    更多资源: 资源 描述 在线课程 极客笔记在线课程 知识星球 星球名称:深入浅出Android Camera 星球ID: 17296815 Wechat 极客笔记圈 目标: 课程主要帮助大家理解camera sensor基本概念及原理知识,理解高通camera sensor驱动框架,通过学习完本视频课程后,可以掌握高通平台上的sensor

    2024年02月11日
    浏览(45)
  • mtk sensor 驱动调试

      MTK Sensor 分为AP和SCP两大部分,AP是主芯片,SCP是协处理器,都可以负责处理sensor数据。所以在MTK在驱动调试时经常会说sensor是挂AP侧还是挂scp侧。    在AP侧的sensor的调试不是很复杂,一般的步骤是找器件原厂对应的驱动,描述清楚是MTK的哪颗芯片,内核时什么版本。我之前

    2024年02月01日
    浏览(37)
  • 高通平台&MTK平台驱动开发流程

    高通(Qualcomm)是全球领先的无线通信技术解决方案提供商,尤其在移动通信领域有深远的影响。高通的Snapdragon系列处理器广泛应用于智能手机、平板电脑、智能手表等多种设备中。Snapdragon处理器以其优异的性能、高效的能耗比以及强大的图形和视频处理能力而著称。高通平

    2024年04月13日
    浏览(47)
  • 驱动开发---cc1: error: code model kernel does not support PIC mode(改文件Unhelp?try it)

          问题描述:在编译内核时出现 cc1: error: code model kernel does not support PIC mode的问题。                  linux版本:3.14       问题分析:这极大原因是系统调用了默认的编译器导致的。      问题解决:在进行make编译的时候,加上ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- 

    2024年02月11日
    浏览(58)
  • 三维模型3DTILE格式轻量化压缩主要技术方法浅析

    三维模型3DTILE格式轻量化压缩主要技术方法浅析 随着三维地理空间数据的应用日益广泛,为了更快速地传输和存储这些大规模数据,3DTile格式的轻量化压缩显得尤为重要。本文将浅析关于三维模型3DTile格式轻量化压缩的主要技术方法。 首先,我们需要理解3DTile的结构,它是

    2024年02月09日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包