高通camera驱动 mm-camera部分 (一)

本文围绕Qualcomm平台的Camera Driver展开,介绍了基于mm - camera的学习内容,包括主进程调用的库、大致框架(camx和mm - camera)。着重阐述了mm - camera结构及各模块功能,详细讲解了sensor模块的硬件组成、初始化流程,还提及传感器的配置参数和分辨率设置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        想写一份关于qualcomm 平台 的camera driver 的文档 ,想讲清楚 camera 各个 module 和 camera sensor的各个sub module。

        无论是 camx 还是 mm-camera 结构, 无论是android O 还是 N 东西就那么多,就不同的写法和实现,万变不离其宗。他强由他强,清风拂山岗。一理通百里用说的就是这个道理。目前下面的是基于mm-camera的学习。有啥不对的,欢迎指正。会持续更新。

 主进程 andorid.hardware.camera.orovider@2.4-service 主要调用的库有:

              camera hal库 camera.<平台>.so ,如:高通的camera.qcom.so 在设备 vendor/lib/hw 目录下。

              camera 各个submodule库。

              备注:老版的框架调用的是mm-qcamera-deamon。

大致框架有2种:

1. camx 代码需要高通平台权限下载后放置 vendor 目录下 chi-cdk 同级目录即可。camx (没看过,待完善)对应hal,编译生成camera.qcom.so

  chi-cdk 目录下主要为各个module,eeprom sensor chromatix等主要都是通过配置xml实现的功能。吐槽:修改起来很麻烦

2. mm-camera 代码结构,主要调用的库 libmmcamera2_mct_shimlayer.so 入口函数 mct_shimlayrt_process_module_init 注意看函数注释:this function is the direct call from HAL to init all the modules present in backend.

mct_shimlayrt_module_sensor_init
mct_shimlayrt_module_init

 Old 2. 老版本mm-camera  主进程 mm-qcamera-deamon  main函数所在 server.c  server process 。(2和old2的区别及优点每个overview都重复描述,以后补充)

mm-camera 结构

    |- mct——应该就是camera的引擎 里面包含了引擎、pipiline、bus、module、stream及event等定义及封装。

    |- modules ——  这里面就是划分好的一些模块代码,各模块大致功能如下 :

        |- sensor  ——  sensor 的驱动模块(src模块)

        |- iface     ——  ISP interface模块(inter模块)

        |- isp        —— 主要是ISP的处理,其内部又包含了众多的模块(inter模块)

        |- stats    —— 一些统计算法模块,如3A,ASD,AFD,IS,GRRO等数据统计的处理(sink模块)

        |- pproc   —— post process处理(inter模块)

        |- imglib   —— 主要是图片的一些后端处理,如HDR等(sink模块)

以上各模块内部又包含了众多的模块,具体需要看代码分析。

将camera的所有功能划分为不同的模块,让模块自己来决定自己的事情(高内聚,低耦合),模块需要有统一的接口和格式。模块中有端口,通过端口把模块连接起来,又把模块挂在总线上。每一个端口的连接就是一个流,把这些流用pipeline来管理。每次启动一个camera就创建一个会话,由这个会话来管理此camera的一切事物。对于每一个会话,模块是共享的,它可以是camera的硬件资源也可以是其它资源(如一些软件算法等资源)。

 

module_list:

  • module_sensor_init << sensor module
  • module_iface_init
  • module_isp_init
  • stats_module_init
  • pproc_module_init
  • module_imglib_init

sensor module  (正题) /mmcamera/mm-camera2/media-controller_modules/sensors

sensor模块是众多模块中的一个,主要是由模组的各个硬件模块组成,包括sensor、Flash、Af、EEprom、OIS、CSI、ir_cut、ir_led 等。这个模块主要描述了模组硬件的一些工作原理及部分驱动相关部分。sensors目录及子目录下的每个module文件夹包含的都是当前目录的功能实现。

   在前面讲到的server process 或者 mct shimlayer 中提到,调用开始后会初始化各个模块,其中就包括sensor模块,sensor初始化入口函数即为module_sensor_init(...)。这个函数将创建sensor模块并返回其指针,另外将创建它的端口,填充一些功能函数等。它的主要执行流程如下:

    1.创建sensor的MCT module。  —— mct_module_create(name)

        创建完之后填充set mode、query mode、start session、stop session及set session data五个接口函数。

    2.创建module_sensro_ctrl_t结构体,此结构体包含bundle信息,用来构建前面提到的模块树(方便添加、遍历等操作)。

    3.sensor模块是source模块,所以其numsinkports应该设置为0。

    4.eebin相关的操作  << eebin_interface_init

    5.sensor的probe操作,用来probe有效的sensor。

    6.填入所有已probe到sensor的信息。 << sensor_init_probe

    7.填入所以sensor的其它信息(Actuator,Flash,CSID,OIS等)module_sensor_find_other_subdev

    8.初始化sensor模块。 <<  module_sensor_subinit(初始化子模块函数列表)

    9.创建基于CID info的端口 port_sensor_create

    10.初始化eeprom module_sensor_init_eeprom

          (1)open the eeprom sub module

         (2)load eeprom library   

         (3)powerup and parse the eeprom

         (4)read the eeprom data from kernel

        (5)format the cal data

        (6)close the eprom sub module

   11.创建chromatix的管理 module_sensor_init_chromatix

 

sub_module_init << 下列是每个子模块

  • sensor_sub_module_init << sensor/module/sensor.c (camera sensor driver)
  • chromatix_sub_module_init
  • actuator_sub_module_init
  • eeprom_sub_module_init << eeprom/module/eeprom.c (eeprom driver)
  • led_flash_sub_module_init
  • csiphy_sub_module_init
  • csid_sub_moduLe init 
  • ois_ sub_module_init
  • external_sub_module_init
  • ir_led_sub_module_init
  • ir_cut_sub_module_init
  • laser_led_sub_module_init 

sensor driver

/vendor/qcom/proprietary/mm-camera/ mm-camera2/media-controller/modules/sensors/sensor_libs/.

libs 下面的文件

Android.mk - 包含构建规则和包含路径。

<sensor> _lib.c - 包含传感器特定的逻辑和功能。

<sensor> _lib.h - 包含传感器配置和传感器处理器结构。

在power_setting_array中可以添加powerup和powerdown序列 camera_power_setting_array结构体。

.power_setting_array = {

.power_setting = power_setting,

.size = ARRAY_SIZE(power_setting),

},

power_setting指向一个数组,其中包含要用于GPIO / CLK / VREG的信息配置每个传感器。

static struct camera_power_setting power_setting[] = {

{

.seq_type = SENSOR_VREG,

.seq_val = CAM_VDIG,

.config_val = 0,

.delay = 0, //this delay is in ms

},

{

.seq_type = SENSOR_VREG,

.seq_val = CAM_VANA,

.config_val = 0,

.delay = 0, //this delay is in ms

},

这个结构用在内核中的msm_camera_power_up()中来配置传感器启动顺序。

sensor_init_params包含相机模块配置。

80-NV354-3 Rev. A

modes_supported - 屏幕显示支持的模式(2D,3D)。

position - 设置设备上的传感器位置(背面或前置摄像头)。

sensor_mount_angle - 设置相对于显示器的相机安装角度。

 

typedef struct {

sensor_output_format_t output_format;

sensor_connection_mode_t connection_mode;

sensor_raw_output_t raw_output;

sensor_filter_arrangement filter_arrangement;

} sensor_output_t;

output_format - 传感器为RAW帧传送BAYER(SENSOR_BAYER)。

connection_mode - 传输接口 - MIPI(SENSOR_MIPI_CSI)或并行。

raw_output - 传输的数据类型 - RAW10(SENSOR_10_BIT_DIRECT),

RAW12(SENSOR_12_BIT_DIRECT),RAW8(SENSOR_8_BIT_DIRECT),DPCM8等

filter_arrangement - 由传感器流出的帧的拜耳色彩图案

struct sensor_output_reg_addr_t {

unsigned short x_output;

unsigned short y_output;

unsigned short line_length_pclk;

unsigned short frame_length_lines;

};

x_output - x_output寄存器的地址。 该寄存器包含每个活动像素的数量在传感器输出中。

y_output - y_output寄存器的地址。 该寄存器包含每行的活动行数框中传感器输出。

line_length_pclk - line_length_pclk寄存器的地址。 该寄存器包含的号码传感器输出中每行的总像素数。

frame_length_lines - y_output寄存器的地址。 该寄存器包含总数传感器输出中每帧的行数。

struct sensor_exp_gain_info_t {

unsigned short coarse_int_time_addr;

unsigned short global_gain_addr;

unsigned short vert_offset;

};

coarse_int_time_addr。 该寄存器包含帧曝光次数。

global_gain_addr。 该寄存器包含帧模拟增益。 其值由传感器特定功能计算。

vert_offset - 包含max_coarse_integration_margin的值,它是一个传感器 - 具体价值。 它是曝光和帧长度之间的最大值。 曝光不能大于帧长度减去vert_offset。

max_exp <= frame_length – vert_offset

typedef struct {

float min_gain;

float max_gain;

float min_analog_gain;

float max_linecount;

}sensor_aec_data_t;

min_gain - 以标准化单位(1.00x)设置传感器增益的最低可接受值。如果没有另外指定,设置为1.00x。

max_gain - 以标准化单位(1.00x)设置增益的最高可接受值。 这是结果的模拟和数字增益。

max_analog_gain - 以标准化单位(1.00x)设置传感器的模拟增益的最高可接受值。 如果传感器没有数字增益,max_analog_gain和max_gain应该相等。

max_linecount - 设置传感器曝光的最高可接受值。 此值取决于rough_integration_time寄存器分辨率和max_coarse_integration_margin(在vert_offset中设置)。

typedef struct {

float focal_length;

float pix_size;

float f_number;

float total_f_dist;

float hor_view_angle;

float ver_view_angle;

sensor_sensing_method_type_t sensing_method;

float crop_factor; //depends on sensor physical dimentions

float min_focus_distance;

} sensor_lens_info_t;

focal_length - 设置镜头焦距。

pix_size - 设置镜头单元格尺寸。

f_number - 设置镜头的F数。

Total_f_dist - 设置总焦距。 值以米为单位。

hor_view_angle - 设置镜头的水平视角。 值以度为单位。

ver_view_angle - 设置镜头的水平视角。 值以度为单位。

sensing_method - 设置感应方式。 如果方法未知,请设置为

SENSOR_SMETHOD_NOT_DEFINED。

crop_factor - 设置镜头裁剪系数。 该值取决于镜头和传感器的物理尺寸,显示镜头是否从传感器矩阵中裁出。

min_focus_distance - 设置镜头最小移动步长。 如果镜头没有特殊的限制,设置为0.1

 

typedef struct {

float pix_width;

float pix_height;

}sensor_physical_dimensions_t;

包含有关传感器颜色的物理尺寸的信息矩阵。

pix_width - 以毫米为单位设置传感器像素阵列宽度。 (单元大小*有效像素宽度)

pix_height - 以毫米为单位设置传感器像素阵列高度。 (单元格大小*有效像素高度)

 

typedef struct {

sensor_dimension_t active_array_size;

unsigned short left_dummy;

unsigned short right_dummy;

unsigned short top_dummy;

unsigned short bottom_dummy;

} sensor_imaging_pixel_array_size;

typedef struct {

int width;

int height;

} sensor_dimention_t;

active_array_size.width - 以像素数设置传感器有源像素阵列宽度。

active_array_size.height - 设置传感器有源像素阵列高度的行数。

left_dummy - 在左侧的有效和有效像素阵列之间设置传感器缓冲区。 该值为像素数。

right_dummy - 在右侧的有效和有效像素阵列之间设置传感器缓冲区。 该值为像素数。

top_dummy - 在顶部的有效和有效像素阵列之间设置传感器缓冲区。 该值为行数。

bottom_dummy - 在底部的有效和有效像素阵列之间设置传感器缓冲区。 该值为行数。

 

typedef struct {

unsigned short white_level;

unsigned short r_pedestal;

unsigned short gr_pedestal;

unsigned short gb_pedestal;

unsigned short b_pedestal;

} sensor_color_level_info;

white_level - 将传感器DAC的值设置为白色。 这通常是最大可能的值DAC可以输出(1023为RAW10)。

r_pedestal - 设置红色通道的黑色电平/数据基座。 该值用于RAW10数据。 对于RAW12乘以4。

gr_pedestal - 设置绿色(红线)通道的黑色电平/数据基座。 值为RAW10数据。 对于RAW12乘以4。

gr_pedestal - 设置绿色(蓝线)通道的黑色电平/数据基座。 值为RAW10数据。 对于RAW12乘以4。

b_pedestal - 设置蓝色通道的黑色电平/数据基座。 该值用于RAW10数据。 对于RAW12乘以4。

 

start_settings - 寄存器设置命令传感器开始流出帧。

stop_settings - 寄存器设置命令传感器停止流出帧。

groupon_setting - 寄存器设置命令传感器设置组参数保持逻辑。

groupoff_settings - 寄存器设置命令传感器释放组参数保持逻辑。

embedded_data_enable_settings - 寄存器设置以命令传感器启用流式传输嵌入式数据。

embedded_data_disable_settings - 寄存器设置命令传感器禁用流出嵌入式数据。

 

struct camera_i2c_reg_setting {

struct camera_i2c_reg_array *reg_setting;

unsigned short size;

enum camera_i2c_reg_addr_type addr_type;

enum camera_i2c_data_type data_type;

unsigned short delay;

};

struct camera_i2c_reg_array {

unsigned short reg_addr;

unsigned short reg_data;

unsigned int delay;

};

size - 设置当前配置中设置的寄存器编号。

addr_type - 设置I2C寄存器地址长度。

data_type - 设置I2C寄存器数据长度。

delay - 设置配置完成后的等待延迟(以ms为单位)。

reg_setting.reg_addr - 设置要更新的寄存器的传感器寄存器地址。

reg_setting.reg_data - 设置需要写入传感器寄存器的数据。

reg_setting.delay - 设置注册配置完成后的等待延迟(以ms为单位)。

 

传感器分辨率设置

struct sensor_lib_reg_settings_array {

struct camera_i2c_reg_setting reg_settings[MAX_RESOLUTION_MODES];

unsigned int size;

};

传感器分辨率配置表

struct sensor_lib_out_info_array {

/* sensor output for each resolutions */

struct sensor_lib_out_info_t out_info[MAX_RESOLUTION_MODES];

/* Number of valid entries in out_info array */

unsigned short size;

};

struct sensor_lib_out_info_t {

unsigned short x_output;

unsigned short y_output;

unsigned short line_length_pclk;

unsigned short frame_length_lines;

unsigned int vt_pixel_clk;

unsigned int op_pixel_clk;

unsigned short binning_factor;

float min_fps;

float max_fps;

unsigned int mode;

unsigned int offset_x;

unsigned int offset_y;

unsigned int scale_factor;

};

size - 设置传感器模式配置的数量。大小应等于可用的配置,不能大于MAX_RESOLUTION_MODES。

out_info.x_output - 设置每行传感器输出的有效像素数。该值是像素数。

out_info.y_output - 设置每帧传感器输出的有效线数。该值是行数。

out_info.line_length_pclk - 设置每行传感器输出的像素总数。这包括有源像素和水平消隐。该值是像素数。

out_info.frame_length_lines - 设置每帧传感器输出的总线数。这包括有效行和垂直消隐。该值是行数。

out_info.vt_pixel_clk - 设置由传感器内部PLL模块生成的视频域定时时钟值。要计算其值,请使用外部时钟(EXTCLK)频率和PLL设置。传感器使用此时钟进行多项内部任务,其值控制多个传感器参数 - 快门/曝光时间,帧速率,传感器内部ISP处理等。

out_info.op_pixel_clk - 设置由传感器内部PLL模块生成的输出域定时时钟值。 要计算其值,请使用外部时钟(EXTCLK)频率和PLL设置。 传感器使用此时钟作为其输出模块。 该时钟用作MIPI / CSI_Tx速度的基础。

struct sensor_csiphy_params {

unsigned char lane_cnt;

unsigned char settle_cnt;

unsigned short lane_mask;

unsigned char combo_mode;

unsigned char csid_core;

unsigned int csiphy_clk;

};

lane_cnt - 设置CSI2车道数。 根据传感器模式配置,可以使用两个或四个通道进行流出。

sett_cnt - 对于CSI_Tx(传感器)和CRI_Rx(设备)正常工作,需要在它们之间同步的时间段。 这个时间被设置为定时器时钟滴答的数量。 它必须在由公式计算的MIN和MAX值之间:

MIN [Settle count * T(Timer clock)] > T(HS_SETTLE)_MIN

MAX [Settle count * T(Timer clock)] < T(HS-PREPARE)+T(HS_ZERO) - 4*T(Timer clock)

lane_mask - 设置在当前配置中使用哪些CSI2通道。 该值是标志的组合。

 

struct sensor_lib_crop_params_array{

struct sensor_crop_parms_t crop_params[MAX_RESOLUTION_MODES];

unsigned short size;

};

struct sensor_crop_parms_t {

unsigned short top_crop;

unsigned short bottom_crop;

unsigned short left_crop;

unsigned short right_crop;

};

crop_

params.top_crop - 从当前模式的顶端设置裁剪。

crop_params.bottom_crop - 从当前模式的底部设置裁剪。

crop_params.left_crop - 从当前模式的左侧设置裁剪。

crop_params.right_crop - 从当前模式的右侧设置裁剪。

 

struct sensor_lib_chromatix_array {

struct sensor_lib_chromatix_t sensor_lib_chromatix[MAX_RESOLUTION_MODES];

unsigned short size;

};

struct sensor_lib_chromatix_t {

char *common_chromatix;

char *camera_preview_chromatix;

char *camera_snapshot_chromatix;

char *camcorder_chromatix;

char *liveshot_chromatix;

char *cpp_chromatix;

char *cpp_snapchromatix;

char *cpp_videochromatix;

char *cpp_liveshotchromatix;

char *postproc_chromatix;

};

sensor_lib_chromatix.common_chromatix - 为当前传感器模式/分辨率设置指向公共(VFE)chromatix的指针。

sensor_lib_chromatix.camera_preview_chromatix - 设置指针以预览chromatix

用于当前的传感器模式/分辨率。当模式用于图像预览时,它被加载。

sensor_lib_chromatix.camera_snapshot_chromatix - 为当前传感器模式/分辨率设置指向快照chromatix的指针。当模式用于快照时加载。

sensor_lib_chromatix.camcorder_chromatix - 为当前传感器模式/分辨率设置指向摄像机chromatix的指针。当模式用于视频预览/录制时,它被加载。

sensor_lib_chromatix.liveshot_chromatix - 设置指向livehot chromatix的指针电流传感器模式/分辨率。在拍摄时拍摄(快照,录像)。

sensor_lib_chromatix.cpp_chromatix - 为当前传感器模式/分辨率设置指向cpp chromatix的指针。当模式用于图像预览时,将被加载。

sensor_lib_chromatix.cpp_snapchromatix - 为当前传感器模式/分辨率设置指向cpp snapshot chromatix的指针。当模式用于快照时加载。

sensor_lib_chromatix.cpp_videochromatix - 为当前传感器模式/分辨率设置指向cpp video chromatix的指针。当模式用于视频预览/录制时,它被加载。

sensor_lib_chromatix.cpp_liveshotchromatix - 设置指向cpp的照片chromatix

用于当前的传感器模式/分辨率。在拍摄时拍摄(快照,录像)。

sensor_lib_chromatix.postproc_chromatix - 为当前传感器模式/分辨率设置指向后处理chromatix的指针。它用于软件后处理。

<think>好的,我现在需要回答用户的问题:“高通camera驱动 开机后会注册驱动几次”。首先,我需要回忆高通相机驱动的注册流程,特别是在Android或Linux系统中的驱动加载机制。 首先,高通的相机驱动通常分为几个部分:传感器驱动(camsensor)、ISP驱动(如qcom_cpp、qcom_isp)、以及可能的子模块(如EIS、PD对焦等)。用户的问题主要关注的是“驱动注册次数”,所以需要明确“注册”在这里指的是驱动模块的初始化和向内核或HAL的注册过程。 在Linux内核中,驱动的注册通常由模块的初始化函数(如`module_init`)触发,般情况下,每个驱动模块只会注册次,除非有特殊的设计(如热插拔)。但高通的相机驱动可能涉及多个设备节点或多个传感器,这可能影响注册次数。 接下来,考虑传感器驱动的注册。高通的传感器驱动通常以平台驱动(platform driver)的形式存在,通过设备树(Device Tree)中的节点匹配。如果设备树中定义了多个传感器节点(例如主摄、超广角、长焦等),每个传感器对应的驱动会分别注册次。例如,如果设备树中有三个传感器节点(sensor0, sensor1, sensor2),那么传感器驱动可能会为每个节点注册次,导致多次注册。 另外,ISP驱动(如图像信号处理器驱动)通常作为单驱动注册,因为硬件中可能只有个ISP单元。但如果有多个ISP实例(如某些高端芯片),可能会有多次注册,但这种情况较少。 还需要考虑驱动的热插拔机制。如果相机支持热插拔(如外接USB相机),驱动可能在检测到设备插入时再次注册,但高通的内置相机传感器通常是固定的,开机时只注册次。 此外,驱动的注册可能涉及多个阶段:比如先注册基础框架(如qcom_camera2),然后注册具体的传感器和子模块。但每个具体的驱动模块(如传感器驱动)的`probe`函数通常只会被调用次 per device。 总结可能的情况:如果设备有N个相机传感器(由设备树定义),则传感器驱动会注册N次;ISP等其他驱动通常注册次。因此,开机后驱动注册的次数取决于硬件中相机设备的数量(传感器数量)以及驱动的设计。 需要验证这点,可能需要参考高通的相机驱动代码,例如`camsensor`驱动的`probe`函数是否会被多次调用,对应设备树中的每个传感器节点。通常,平台驱动通过`of_match_table`匹配设备树节点,每个匹配的节点会触发次`probe`,即注册次。 因此,用户的问题答案可能是:高通相机驱动(主要指传感器驱动)的注册次数取决于设备树中定义的相机传感器数量,每个传感器节点会触发驱动注册;ISP等其他驱动通常注册次。 </think>在高通(Qualcomm)平台的Linux/Android系统中,相机驱动的注册次数主要取决于**硬件架构设计**和**设备树(Device Tree)中的相机设备节点数量**。通常,开机后驱动的注册次数与**物理相机传感器的数量**直接相关,以下是具体分析: ### 驱动注册的核心机制 高通相机驱动采用**Linux平台驱动模型**(Platform Driver Model),驱动通过`platform_driver`结构体注册,并通过设备树(`.dts`/`.dtsi`)中的设备节点(`device node`)匹配触发注册。 - **驱动注册入口**:驱动的`probe`函数(探测函数)会在设备树节点与驱动的`of_match_table`(设备匹配表)匹配时被调用,完成驱动初始化和硬件注册。 - **关键结论**:**每匹配个设备树中的相机设备节点,驱动的`probe`函数就会执行次,即完成驱动注册**。 ### 二、注册次数的决定因素:设备树中的相机节点数量 高通平台的设备树通常会为每个物理相机传感器(如主摄、超广角、长焦、ToF等)定义独立的设备节点。例如,个包含3个传感器的手机,设备树中可能有以下节点: ```dts /* 设备树示例(简化) */ camera@0 { /* 主摄,ID=0 */ compatible = "qcom,camera-sensor"; reg = <0>; /* 传感器I2C地址或ID */ ... }; camera@1 { /* 超广角,ID=1 */ compatible = "qcom,camera-sensor"; reg = <1>; ... }; camera@2 { /* 长焦,ID=2 */ compatible = "qcom,camera-sensor"; reg = <2>; ... }; ``` 每个`camera@X`节点会触发次传感器驱动的`probe`函数调用,因此**注册次数等于设备树中定义的相机传感器节点数量**。 ### 三、典型场景下的注册次数 #### 1. 单摄像头设备 若设备仅包含1个物理传感器(如入门级手机的单摄),设备树中仅有1个`camera`节点,驱动的`probe`函数执行1次,**注册1次**。 #### 2. 多摄像头设备(主流手机) 当前主流手机通常配备2~4个物理传感器(主摄+超广角+长焦+微距/ToF),设备树中对应2~4个`camera`节点,驱动的`probe`函数会**依次触发2~4次注册**(顺序由设备树节点顺序或内核枚举顺序决定)。 #### 3. ISP等辅助驱动的注册 除传感器驱动外,高通相机系统还包含ISP(图像信号处理器)、CPP(摄像头预处理)等辅助驱动。这些驱动通常对应硬件中的单模块(如芯片级ISP),因此设备树中仅定义1个节点,**仅注册1次**。 ### 四、特殊情况:重复注册或异常 #### 1. 驱动兼容性问题 若设备树中的多个节点错误地使用了相同的`compatible`属性(如均为`qcom,camera-sensor`),且驱动未正确区分设备ID(如`reg`值),可能导致驱动对同传感器重复注册(如`probe`函数被多次调用)。 #### 2. 热插拔场景 部分特殊设备(如支持外接相机的平板)可能通过USB或其他接口支持热插拔相机。此时,当外接相机插入时,内核会检测到新的设备节点,触发驱动的`probe`函数再次执行,**额外注册**。但高通内置相机(如手机主摄)通常不涉及热插拔,开机仅注册次。 ### 五、验证方法 通过内核日志(`dmesg`)可直接观察驱动注册次数。例如,传感器驱动的`probe`函数通常会打印调试日志(如`camsensor_probe: sensor 0 probed`): ```bash dmesg | grep -i "camsensor.*probed" # 查看传感器驱动probe日志 ``` 日志中每条记录对应驱动注册,数量即为设备树中的相机节点数。 ### 总结 高通相机驱动(主要指传感器驱动)的注册次数由设备树中定义的相机传感器节点数量决定,每匹配个节点触发次注册。主流多摄设备通常注册2~4次,单摄设备注册1次;ISP等辅助驱动仅注册1次。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值