高通平台mm-camera上电时序

背景

作为高通平台Camera知识的一种补充。

参考文档:https://blog.csdn.net/m0_37166404/article/details/64920910

介绍

高通平台对于camera的代码组织,大体上还是遵循Android的框架,即:

  • 上层应用和HAL层交互,高通平台在HAL层里面实现自己的一套管理策略;
  • 在kernel中实现sensor的底层驱动;
  • 对于最核心的sensor端的底层设置、ISP效果相关等代码则是单独进行了抽离,放在vendor中。

上电时序

时序属性

路径:vendor/qcom/proprietary/mm-camera/mm-camera2/media-controller/modules/sensors/includes/sensor_lib.h

  • 最终位于:kernel/include/media/msm_camsensor_sdk.h
struct msm_sensor_power_setting {
enum msm_sensor_power_seq_type_t seq_type;
uint16_t seq_val;
long config_val;
uint16_t delay;
void *data[10];
};

有关的时序设置

以:ov5648_q5v22e 为例。

对照规格书:

把DOVDD上电后,AVDD,DVDD,PWDNB的上电时序都大于图中规定时间。

路径:vendor/qcom/proprietary/mm-camera/mm-camera2/media-controller/modules/sensors/sensor_libs/xxx

例如:vendor/qcom/proprietary/mm-camera/mm-camera2/media-controller/modules/sensors/sensor_libs/ov5648_q5v22e当中的ov5648_q5v22e_lib.c

下面这个结构体便是上电时序

tatic struct msm_sensor_power_setting ov5648_q5v22e_power_setting[] = {
{
.seq_type = SENSOR_VREG,
.seq_val = CAM_VIO,
.config_val = 0,
.delay = 0,
},
{
.seq_type = SENSOR_VREG,
.seq_val = CAM_VANA,
.config_val = 0,
.delay = 0,
},
{
.seq_type = SENSOR_VREG,
.seq_val = CAM_VAF,
.config_val = 0,
.delay = 0,
},
{
.seq_type = SENSOR_GPIO,
.seq_val = SENSOR_GPIO_AF_PWDM,
.config_val = GPIO_OUT_LOW,
.delay = 1,
},
{
.seq_type = SENSOR_GPIO,
.seq_val = SENSOR_GPIO_AF_PWDM,
.config_val = GPIO_OUT_HIGH,
.delay = 5,
},
{
.seq_type = SENSOR_GPIO,
.seq_val = SENSOR_GPIO_RESET,
.config_val = GPIO_OUT_LOW,
.delay = 0,
},
{
.seq_type = SENSOR_GPIO,
.seq_val = SENSOR_GPIO_RESET,
.config_val = GPIO_OUT_HIGH,
.delay = 10,
},
{
.seq_type = SENSOR_GPIO,
.seq_val = SENSOR_GPIO_STANDBY,
.config_val = GPIO_OUT_LOW,
.delay = 0,
},
{
.seq_type = SENSOR_GPIO,
.seq_val = SENSOR_GPIO_STANDBY,
.config_val = GPIO_OUT_HIGH,
.delay = 5,
},
{
.seq_type = SENSOR_CLK,
.seq_val = SENSOR_CAM_MCLK,
.config_val = 24000000,
.delay = 10,
},
{
.seq_type = SENSOR_I2C_MUX,
.seq_val = 0,
.config_val = 0,
.delay = 0,
},
};

它会被下列的结构体中使用:

static struct msm_camera_sensor_slave_info sensor_slave_info = {
//...
/* power up / down setting */
.power_setting_array = {
.power_setting = ov5648_q5v22e_power_setting,
.size = ARRAY_SIZE(ov5648_q5v22e_power_setting),
.power_down_setting = power_down_setting,
.size_down = ARRAY_SIZE(power_down_setting),
},
};

这些Camera的属性具体在msm_camsensor_sdk定义。

  • 最终位于:kernel/include/media/msm_camsensor_sdk.h
struct msm_camera_sensor_slave_info {
...
struct msm_sensor_power_setting_array power_setting_array;
...
}; struct msm_sensor_power_setting {
enum msm_sensor_power_seq_type_t seq_type;
uint16_t seq_val;
long config_val;
uint16_t delay;
void *data[10];
}; struct msm_sensor_power_setting_array {
struct msm_sensor_power_setting power_setting_a[MAX_POWER_CONFIG];
struct msm_sensor_power_setting *power_setting;
uint16_t size;
struct msm_sensor_power_setting power_down_setting_a[MAX_POWER_CONFIG];
struct msm_sensor_power_setting *power_down_setting;
uint16_t size_down;
};

驱动流程解析

在此之前是ioctl,注册到v4l2子系统中。从vendor中把时序结构体的内容传递到kernel中的过程如下:

注意:vendor中的addr_type、camera_id、slave_addr等信息也是按照这样的方法从vendor中传递到kernel中的,可以加打印调试信息看这些值正确与否。

++ kernel/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_init.c
msm_sensor_init_subdev_ioctl()
msm_sensor_driver_cmd() : case VIDIOC_MSM_SENSOR_INIT_CFG
++ kernel/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c
msm_sensor_driver_probe()
copy_from_user((void *)&setting32, setting,sizeof(setting32))
// 把 vendor 的时序传递完毕
slave_info->power_setting_array.size = setting32.power_setting_array.size;
slave_info->power_setting_array.power_setting =
compat_ptr(setting32.power_setting_array.power_setting);
// 把slave_info的上电时序传递给s_ctrl结构体
msm_sensor_get_power_settings
msm_sensor_get_power_up_settings(setting, slave_info, power_info); /* 校正时序中SENSOR_VREG的seq_val,为设备树的CAM_VIO */
msm_camera_fill_vreg_params();
/* 执行真正的上电程序*/
s_ctrl->func_tbl->sensor_power_up(s_ctrl);
(msm_sensor_power_up)
由于之前有 .sensor_power_up = msm_sensor_power_up,
所以最终为: msm_sensor_power_up
++ kernel/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
//把s_ctrl的上电信息传递给power_info
power_info = &s_ctrl->sensordata->power_info;
sensor_i2c_client = s_ctrl->sensor_i2c_client;
slave_info = s_ctrl->sensordata->slave_info;
sensor_name = s_ctrl->sensordata->sensor_name; // 通过之前设置好的时序上电
rc = msm_camera_power_up(power_info,
s_ctrl->sensor_device_type,
sensor_i2c_client);

msm_camera_power_up流程分析

解析这个上电函数:

int msm_camera_power_up(struct msm_camera_power_ctrl_t *ctrl,
enum msm_camera_device_type_t device_type,
struct msm_camera_i2c_client *sensor_i2c_client)
{
struct msm_sensor_power_setting *power_setting = NULL;
//...
rc = msm_camera_request_gpio_table( //申请gpio
ctrl->gpio_conf->cam_gpio_req_tbl,
ctrl->gpio_conf->cam_gpio_req_tbl_size, 1);
//...
index = 0; index < ctrl->power_setting_size; index++) {
//把时序的节点一个一个取下来解析
power_setting = &ctrl->power_setting[index];
//判断类型
switch (power_setting->seq_type) {
case SENSOR_CLK:
if (power_setting->config_val)
ctrl->clk_info[power_setting->seq_val].clk_rate = power_setting->config_val;
//camera频率使能
rc = msm_cam_clk_enable(...1);
//...
case SENSOR_GPIO:
//...
//拉高拉低gpio口
gpio_set_value_cansleep(ctrl->gpio_conf->gpio_num_info->gpio_num[power_setting->seq_val],
(int) power_setting->config_val);
//...
case SENSOR_VREG:
//函数里面打开reg_ptr的电源控制器regulator_enable,稍后会解析
if (power_setting->seq_val < ctrl->num_vreg)
msm_camera_config_single_vreg(...,1);
//...
case SENSOR_I2C_MUX:
if (ctrl->i2c_conf && ctrl->i2c_conf->use_i2c_mux)
msm_camera_enable_i2c_mux(ctrl->i2c_conf); //打开使能i2c_mux
break;
default:
//...
}
//以下是每个时序节点解析完毕后,进行的延迟,可以没有
if (power_setting->delay > 20) {
msleep(power_setting->delay);
} else if (power_setting->delay) {
usleep_range(power_setting->delay * 1000,(power_setting->delay * 1000) + 1000);
}
}
//...
return 0;
}

两个特殊节点

SENSOR_VREG

在解析设备树节点的时候:

		//从中有一路电vio为0V
qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";//"cam_vaf";
qcom,cam-vreg-min-voltage = <1800000 0 2850000 >;//2800000>;
qcom,cam-vreg-max-voltage = <1800000 0 2850000 >;//2800000>;
qcom,cam-vreg-op-mode = <200000 0 80000 100000>;
//在kernel中对设备树节点解析的时候
for (i = 0; i < count; i++) {
vreg[i].min_voltage = vreg_array[i];}//存入结构体中

在msm_sensor_driver_probe函数中调用msm_camera_fill_vreg_params,在里面遍历上电时序节点:

for (i = 0; i < power_setting_size; i++)
{
if (power_setting[i].seq_type != SENSOR_VREG)
continue; switch (power_setting[i].seq_val) {
case CAM_VDIG:
//...
case CAM_VIO:
for (j = 0; j < num_vreg; j++) {
if (!strcmp(cam_vreg[j].reg_name, "cam_vio")) {
power_setting[i].seq_val = j; // 让seq_val 对准设备树的seq_val
break;
}
}
break;
//...
}
} // 再进入此节点上电的时候有下列的语句,中间的参数就是设备树上的电压。
msm_camera_config_single_vreg(..&ctrl->cam_vreg[power_setting->seq_val],..);

SENSOR_I2C_MUX

执行函数msm_camera_enable_i2c_mux—>可能是申请锁和一帧的内存空间

解析完毕后,最后两个节点是打开时序和I2C_MUX,如果成功上电便完成了。

高通平台mm-camera上电时序的更多相关文章

  1. 高通平台 lcd driver 调试小结

    一.概述 1.1 简介 本文档主要包括LCD模块的驱动流程分析.Framebuffer相关知识.Gralloc等相关内容,以及LCD调试的一些经验和相关bug的分析和讲解. 1.2  开发环境 And ...

  2. 【转】高通平台android 环境配置编译及开发经验总结

    原文网址:http://blog.csdn.net/dongwuming/article/details/12784535 1.高通平台android开发总结 1.1 搭建高通平台环境开发环境 在高通 ...

  3. 高通平台的bootloader过程【转】

    ====================基本知识=======================LK是(L)ittle (K)ernel的缩写.高通平台android普遍采用LK作为其bootloade ...

  4. 高通平台msm8909 LK 实现LCD 兼容

    前段时间小米出现红米note2 换屏门,现在我们公司也要上演了:有两个供应商提供不同IC 的LCD panel. 软件区分的办法是读取LCD IC 的ID 寄存器,下面解析高通平台LK中LCD兼容的过 ...

  5. 高通平台Bootloader启动流程【转】

    本文转载自:http://blog.csdn.net/fang_first/article/details/49615631 ====================基本知识============= ...

  6. [修改高通平台WIFI MAC 地址] & [adb over wifi]

    [修改高通平台WIFI MAC 地址]fccmd --helpfccmd startfccmd getwifimacfccmd setwifimac 74:AC:5F:F5:D7:40 [adb ov ...

  7. 高通平台Camera调试(一)【转】

    本文转载自:http://www.voidcn.com/blog/Winva/article/p-6044730.html 4.3. Camera 参考文档: 1) 80-NA157-22_PRESE ...

  8. Android : 高通平台Camera调试之SetpropKey/camxoverridesettings.txt

    高通相关网址:Createpoint: https://createpoint.qti.qualcomm.com(可下载文档,Release Note等)Chipcode: https://chipc ...

  9. android 6.0 高通平台sensor 工作机制及流程(原创)

    最近工作上有碰到sensor的相关问题,正好分析下其流程作个笔记. 这个笔记分三个部分: sensor硬件和驱动的工作机制 sensor 上层app如何使用 从驱动到上层app这中间的流程是如何 Se ...

  10. 高通平台MSM8916LCM模块移植(一)-bootloader部分

    此次移植打算分成两个模块来说,bootloader部分和kernel部分.在实际的移植调试过程中也是这么分成了两个部分分别调试. 高通平台中的bootloader叫做LK(Little Kernel, ...

随机推荐

  1. EPAI手绘建模APP常用工具栏_1

    1.常用工具栏 图 1 常用工具栏 (1) 撤销 (2) 重做 (3) 删除 (4) 复制 ① 选中场景中的模型后,复制按钮变成可用状态,否则变成禁用状态.可以选择多个模型一起复制. (5) 变换 图 ...

  2. uniapp+vue3聊天室|uni-app+vite4+uv-ui跨端仿微信app聊天语音/朋友圈

    原创研发uniapp+vue3+pinia2跨三端仿微信app聊天模板Uniapp-Wechat. uni-vue3-wchat基于uni-app+vue3+pinia2+uni-ui+uv-ui等技 ...

  3. XYCTF pwn部分题解 (部分题目详解)

    hello_world(签到) 思路: 这道题就是利用printf函数泄露libc的基地址,然后再次进行栈溢出通过system,/bin/sh来获取shell wp: invisible_flag 思 ...

  4. Unity 热更--AssetBundle学习笔记 1.0【AB包资源加载工具类的实现】

    工具类封装 通过上文中对AB包加载API的了解和简单使用,对AB包资源加载的几种方法进行封装,将其写入单例类中,如代码展示. 确保每个AB资源包只加载一次: 在LoadAssetBundleManag ...

  5. docker、docker-compose 常用命令

    1.docker 常用命令 创建容器:docker create 启动容器:docker start [id] 停止容器:docker stop [id] 停止全部运行的容器:docker stop ...

  6. 配置vscode的vue环境变量

    参考下面连接: vscode中使用beautify插件格式化vue文件(自定义快捷键) https://blog.csdn.net/jiandan1127/article/details/859589 ...

  7. C#/.NET/.NET Core优秀项目和框架2024年4月简报

    前言 公众号每月定期推广和分享的C#/.NET/.NET Core优秀项目和框架(每周至少会推荐两个优秀的项目和框架当然节假日除外),公众号推文中有项目和框架的介绍.功能特点.使用方式以及部分功能截图 ...

  8. 在线电子表格编辑器 Luckysheet

    下载地址 不知道地址正不正经,我先用着,网上找的地址,不知道是不是可信任的,疑似官网的两个地址都打不开, https://github.com/dream-num/Luckysheet zip包  h ...

  9. C# ScottPlot 绘图控件 源码阅读心得体会

    ScottPlot的介绍可以看这篇博客:https://www.cnblogs.com/myshowtime/p/15606399.html 我对代码的理解是这样的: 图像的呈现是靠bitmap,每进 ...

  10. C# Socket 封包 拆包 ProtoBuf 的使用

    //这是消息头包,消息头包大小是固定的, //每次传输都要先传消息头,在传消息体 enum EnumMsgType:消息类型 long PackgeSize:包大小 long TotalPackage ...