Mtk Camera Hal到驱动的流程(2)
(1)Camera驱动文件结构
camera 整个驱动框架分为三个部分: hal层逻辑调用,kernel层的通用驱动 sensorlist.c 和 具体IC 的驱动, 比如 gc2385_mipi_raw.c 。
kernel 起来后不会直接去访问硬件sensor ,而是会注册相关的驱动,之后 Android系统 起来后会启动相关的服务如: camera_service ,在 camera 服务中会直接去访问 hal层 , kernel驱动 ,进而操作 camera 。这里只分析 kernel层中 camera驱动的实现。
先看一下驱动kernel文件结构:
./kernel-4.19/drivers/misc/mediatek/imgsensor/src/common/v1/
——imgsensor.c
——imgsensor_hw.c
——imgsensor_i2c.c
——imgsensor_proc.c
——imgsensor_sensor_list.c
——imgsensor_legacy.c
./kernel-4.19/drivers/misc/mediatek/imgsensor/src/mtxxxx/camera_hw/
——imgsensor_cfg_table.c
File | Decription |
---|---|
imgsensor.c | sensor 驱动适配器和驱动入口函数的实现 |
imgsensor_hw.c | sensor 电源控制的实现 |
imgsensor_i2c.c | I2C 读写函数的实现 |
imgsensor_proc.c | proc文件系统相关部分的实现 |
imgsensor_sensor_list.c | 包含所有sensor初始化函数的表单 |
imgsensor_legacy.c | sensor的旧的接口部分。主要是与I2c相关API |
imgsensor_cfg_table.c | sensor电源和I2C的配置表 |
(2)Camera驱动初始化流程(入口函数)
(A)驱动程序入口函数imgsensor_init
//imgsensor.c
module_init(imgsensor_init);
/* camera sensor入口函数 */
static int __init imgsensor_init(void)
{
PK_DBG("[camerahw_probe] start\n");
/* 注册一个平台驱动gimgsensor_platform_driver */
if (platform_driver_register(&gimgsensor_platform_driver)) {
PK_PR_ERR("failed to register CAMERA_HW driver\n");
return -ENODEV;
}
...
return 0;
}
static struct platform_driver gimgsensor_platform_driver = {
.probe = imgsensor_probe, //注册前后摄 camera 驱动
.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
}
};
#ifdef CONFIG_OF
static const struct of_device_id gimgsensor_of_device_id[] = {
{ .compatible = "mediatek,camera_hw", },
{}
};
#endif
当 platform_devices 和 platform_driver 通过 match 函数匹配上后,会调用 imgsensor_probe函数注册前后摄 camera 驱动。
(B)imgsensor_probe探测函数的实现
//imgsensor.c
/* 平台driver成功与device匹配后调用imgsensor_probe */
static int imgsensor_probe(struct platform_device *pdev)
{
/* Register char driver */
/* 分配设置注册camera驱动的字符设备文件/dev/kd_camera_hw,创建主次设备号 */
if (imgsensor_driver_register()) {
PK_DBG("[CAMERA_HW] register char device failed!\n");
return -1;
}
gpimgsensor_hw_platform_device = pdev;
#ifndef CONFIG_FPGA_EARLY_PORTING
imgsensor_clk_init(&pgimgsensor->clk);
#endif
/* camera硬件初始化,包含对power引脚的配置 */
imgsensor_hw_init(&pgimgsensor->hw);
/* 注册前后摄像头驱动 */
imgsensor_i2c_create();
imgsensor_proc_init();
atomic_set(&pgimgsensor->imgsensor_open_cnt, 0);
#ifdef CONFIG_MTK_SMI_EXT
mmdvfs_register_mmclk_switch_cb( mmsys_clk_change_cb, MMDVFS_CLIENT_ID_ISP);
#endif
return 0;
}
在 imgsensor_probe() 函数中一开始先为 camera 驱动注册了 camera 字符驱动设备,然后通过函数 imgsensor_i2c_create() 注册前后 camera 驱动。
(C)imgsensor_driver_register 注册函数的实现
//imgsensor.c
static const struct file_operations gimgsensor_file_operations = {
.owner = THIS_MODULE,
.open = imgsensor_open,
.release = imgsensor_release,
//imgsensor_ioctl 函数被赋值给 file_operations 结构体 gimgsensor_file_operations 的成员变量 .unlocked_ioctl
.unlocked_ioctl = imgsensor_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = imgsensor_compat_ioctl
#endif
};
static inline int imgsensor_driver_register(void)
{
//...
/* Attatch file operation. */
cdev_init(gpimgsensor_cdev, &gimgsensor_file_operations);
//...
gpimgsensor_class = class_create(THIS_MODULE, "sensordrv");
if (IS_ERR(gpimgsensor_class)) {
int ret = PTR_ERR(gpimgsensor_class);
PK_DBG("Unable to create class, err = %d\n", ret);
return ret;
}
gimgsensor_device =
device_create(
gpimgsensor_class,
NULL,
dev_no,
NULL,
IMGSENSOR_DEV_NAME);
return 0;
}
在 gimgsensor_file_operations 中可以发现,camera 控制函数是有 imgsensor_ioctl 实现的。
(D)imgsensor_ioctl的定义
//imgsensor.c
static long imgsensor_ioctl(
struct file *a_pstFile,
unsigned int a_u4Command,
unsigned long a_u4Param)
{
int i4RetValue = 0;
void *pBuff = NULL;
//...
switch (a_u4Command) {
case KDIMGSENSORIOC_X_GET_CONFIG_INFO:
i4RetValue = adopt_CAMERA_HW_GetInfo(pBuff);
break;
case KDIMGSENSORIOC_X_GETINFO2:
i4RetValue = adopt_CAMERA_HW_GetInfo2(pBuff);
break;
case KDIMGSENSORIOC_X_FEATURECONCTROL:
i4RetValue = adopt_CAMERA_HW_FeatureControl(pBuff);
break;
case KDIMGSENSORIOC_X_CONTROL:
i4RetValue = adopt_CAMERA_HW_Control(pBuff);
break;
case KDIMGSENSORIOC_X_SET_MCLK_PLL:
i4RetValue = imgsensor_clk_set(&pgimgsensor->clk, (ACDK_SENSOR_MCLK_STRUCT *)pBuff);
break;
case KDIMGSENSORIOC_X_GET_ISP_CLK:
/*E1(High):490, (Medium):364, (low):273*/
#define ISP_CLK_LOW 273
#define ISP_CLK_MEDIUM 364
#define ISP_CLK_HIGH 490
#ifdef CONFIG_MTK_SMI_EXT
PK_DBG("KDIMGSENSORIOC_X_GET_ISP_CLK current_mmsys_clk=%d\n", current_mmsys_clk);
if (mmdvfs_get_stable_isp_clk() == MMSYS_CLK_HIGH)
*(unsigned int *)pBuff = ISP_CLK_HIGH;
else if (mmdvfs_get_stable_isp_clk() == MMSYS_CLK_MEDIUM)
*(unsigned int *)pBuff = ISP_CLK_MEDIUM;
else
*(unsigned int *)pBuff = ISP_CLK_LOW;
#else
*(unsigned int *)pBuff = ISP_CLK_HIGH;
#endif
break;
case KDIMGSENSORIOC_X_GET_CSI_CLK:
i4RetValue = imgsensor_clk_ioctrl_handler(pBuff);
break;
case KDIMGSENSORIOC_T_OPEN:
case KDIMGSENSORIOC_T_CLOSE:
case KDIMGSENSORIOC_T_CHECK_IS_ALIVE:
case KDIMGSENSORIOC_X_SET_DRIVER:
case KDIMGSENSORIOC_X_GETRESOLUTION2:
case KDIMGSENSORIOC_X_GET_SOCKET_POS:
case KDIMGSENSORIOC_X_SET_GPIO:
case KDIMGSENSORIOC_X_SET_I2CBUS:
case KDIMGSENSORIOC_X_RELEASE_I2C_TRIGGER_LOCK:
case KDIMGSENSORIOC_X_SET_SHUTTER_GAIN_WAIT_DONE:
case KDIMGSENSORIOC_X_SET_CURRENT_SENSOR:
i4RetValue = 0;
break;
default:
PK_DBG("No such command %d\n", a_u4Command);
i4RetValue = -EPERM;
break;
}
//...
}
对 camera 硬件的初始化操作是在函数 adopt_CAMERA_HW_FeatureControl() 中实现的。
(E)adopt_CAMERA_HW_FeatureControl 的定义
//imgsensor.c
static inline int adopt_CAMERA_HW_FeatureControl(void *pBuf)
{
...
switch (pFeatureCtrl->FeatureId) {
case SENSOR_FEATURE_OPEN:
ret = imgsensor_sensor_open(psensor);
break;
case SENSOR_FEATURE_CLOSE:
ret = imgsensor_sensor_close(psensor);
/* reset the delay frame flag */
break;
case SENSOR_FEATURE_SET_DRIVER:
{
MINT32 drv_idx;
psensor->inst.sensor_idx = pFeatureCtrl->InvokeCamera;
drv_idx = imgsensor_set_driver(psensor);
memcpy(pFeaturePara, &drv_idx, FeatureParaLen);
break;
}
imgsensor_set_driver 是在 adopt_CAMERA_HW_FeatureControl 函数中被调用的,即在开机过程中,vendor 会寻找 Sensor ,并对它做些硬件初始化。
(F)imgsensor_set_driver的实现
//imgsensor.c
int imgsensor_set_driver(struct IMGSENSOR_SENSOR *psensor)
{
u32 drv_idx = 0;
int ret = -EIO;
struct IMGSENSOR_SENSOR_INST *psensor_inst = &psensor->inst;
/* kdSensorList 中包含操作具体硬件的摄像头驱动代码 */
struct IMGSENSOR_INIT_FUNC_LIST *pSensorList = kdSensorList;
#define TOSTRING(value) #value
#define STRINGIZE(stringizedName) TOSTRING(stringizedName)
char *psensor_list_config = NULL, *psensor_list = NULL;
//加载CONFIG_CUSTOM_KERNEL_IMGSENSOR驱动列表
char *sensor_configs = STRINGIZE(CONFIG_CUSTOM_KERNEL_IMGSENSOR);
static int orderedSearchList[MAX_NUM_OF_SUPPORT_SENSOR] = {-1};
static bool get_search_list = true;
int i = 0;
int j = 0;
char *driver_name = NULL;
imgsensor_mutex_init(psensor_inst);
//初始化
imgsensor_i2c_init(&psensor_inst->i2c_cfg,
imgsensor_custom_config[
(unsigned int)psensor_inst->sensor_idx].i2c_dev);
imgsensor_i2c_filter_msg(&psensor_inst->i2c_cfg, true);
//...
return ret;
}
kdSensorList 在文件 imgsensor.c 中被函数 imgsensor_set_driver() 调用获取设备信息。
(G)kdSensorList 结构体中的实现
//(1)defconfig文件修改
//kernel-4.19/arch/arm64/configs/
//k79v1_64_defconfig 和 k79v1_64_debug_defconfig
CONFIG_CUSTOM_KERNEL_IMGSENSOR="hi846_mipi_raw gc8034_mipi_raw gc5035_mipi_raw sc500cs_mipi_raw"
CONFIG_IMGSENSOR_MAIN="hi846_mipi_raw gc8034_mipi_raw"
CONFIG_IMGSENSOR_SUB="gc5035_mipi_raw sc500cs_mipi_raw"
//(2)kdSensorList列表
//imgsensor_sensor_list.c
struct IMGSENSOR_INIT_FUNC_LIST kdSensorList[MAX_NUM_OF_SUPPORT_SENSOR] = {
#if defined(HI1333_MIPI_RAW)
{HI1333_SENSOR_ID, SENSOR_DRVNAME_HI1333_MIPI_RAW, HI1333_MIPI_RAW_SensorInit},
#endif
/*IMX*/
#if defined(GC8034_MIPI_RAW)
{GC8034_SENSOR_ID,
SENSOR_DRVNAME_GC8034_MIPI_RAW,
GC8034_MIPI_RAW_SensorInit},
#endif
//...
{0, {0}, NULL},
};
(H)GC8034_MIPI_RAW_SensorInit的实现
//kernel-4.19/drivers/misc/mediatek/imgsensor/src/mtxxxx/gc8034_mipi_raw/gc8034mipi_Sensor.c
static struct SENSOR_FUNCTION_STRUCT sensor_func = {
open,
get_info,
get_resolution,
feature_control,
control,
close
};
UINT32 GC8034_MIPI_RAW_SensorInit(struct SENSOR_FUNCTION_STRUCT **pfFunc)
{
/* Check Sensor status here */
if (pfFunc != NULL)
*pfFunc = &sensor_func;
return ERROR_NONE;
}
(I)imgsensor_hw_init和imgsensor_i2c_create函数实现
这两个函数是在 imgsensor_probe() 中被调用,在其中注册了对应的 camera 驱动。
//kernel-4.19/drivers/misc/mediatek/imgsensor/src/common/v1/imgsensor_i2c.c
enum IMGSENSOR_RETURN imgsensor_i2c_create(void)
{
int i;
for (i = 0; i < IMGSENSOR_I2C_DEV_MAX_NUM; i++)
i2c_add_driver(&gi2c_driver[i]);
return IMGSENSOR_RETURN_SUCCESS;
}
IMGSENSOR_I2C_DEV_MAX_NUM 通过枚举进行赋值,其值是3,说明最多可以注册的摄像头驱动为3个。因为camera 驱动是挂载在 I2C总线 上,所以通过函数 i2c_add_driver() 进行注册,gi2c_driver 结构体对应一个具体 camera 设备的驱动。
//imgsensor_i2c.c
static const struct i2c_device_id gi2c_dev_id[] = {
{IMGSENSOR_I2C_DRV_NAME_0, 0},
{IMGSENSOR_I2C_DRV_NAME_1, 0},
{IMGSENSOR_I2C_DRV_NAME_2, 0},
{}
};
#ifdef CONFIG_OF
static const struct of_device_id gof_device_id_0[] = {
/* "mediatek,camera_main" */
{ .compatible = IMGSENSOR_I2C_OF_DRV_NAME_0, },
{}
};
static const struct of_device_id gof_device_id_1[] = {
/* "mediatek,camera_sub" */
{ .compatible = IMGSENSOR_I2C_OF_DRV_NAME_1, },
{}
};
static const struct of_device_id gof_device_id_2[] = {
/* "mediatek,camera_main_two" */
{ .compatible = IMGSENSOR_I2C_OF_DRV_NAME_2, },
{}
};
#endif
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,// "kd_camera_hw"
.owner = THIS_MODULE,
#ifdef CONFIG_OF
.of_match_table = gof_device_id_0,
#endif
},
.id_table = gi2c_dev_id,
},
{
.probe = imgsensor_i2c_probe_1,
.remove = imgsensor_i2c_remove,
.driver = {
.name = IMGSENSOR_I2C_DRV_NAME_1, // "kd_camera_hw_bus2"
.owner = THIS_MODULE,
#ifdef CONFIG_OF
.of_match_table = gof_device_id_1,
#endif
},
.id_table = gi2c_dev_id,
},
{
.probe = imgsensor_i2c_probe_2,
.remove = imgsensor_i2c_remove,
.driver = {
.name = IMGSENSOR_I2C_DRV_NAME_2, // "kd_camera_hw_bus3"
.owner = THIS_MODULE,
#ifdef CONFIG_OF
.of_match_table = gof_device_id_2,
#endif
},
.id_table = gi2c_dev_id,
}
};
上面匹配涉及到的名称是在文件 imgsensor_cfg_table.h 中定义的。
//kernel-4.19/drivers/misc/mediatek/imgsensor/src/mtxxxx/camera_hw/imgsensor_cfg_table.h
enum IMGSENSOR_I2C_DEV {
IMGSENSOR_I2C_DEV_0,
IMGSENSOR_I2C_DEV_1,
IMGSENSOR_I2C_DEV_2,
IMGSENSOR_I2C_DEV_MAX_NUM,
};
#define IMGSENSOR_I2C_DRV_NAME_0 "kd_camera_hw"
#define IMGSENSOR_I2C_DRV_NAME_1 "kd_camera_hw_bus2"
#define IMGSENSOR_I2C_DRV_NAME_2 "kd_camera_hw_bus3"
#define IMGSENSOR_I2C_OF_DRV_NAME_0 "mediatek,camera_main"
#define IMGSENSOR_I2C_OF_DRV_NAME_1 "mediatek,camera_sub"
#define IMGSENSOR_I2C_OF_DRV_NAME_2 "mediatek,camera_main_two"
(3)camera驱动文件的执行流程
/kernel-4.19/drivers/misc/mediatek/imgsensor/src/common/v1/
- 执行此目录下的imgsensor.c --> imgsensor_sensor_list.c获取camera设备信息;
- 执行 imgsensor.c --> imgsensor_hw.c --> imgsensor_cfg_table.c 获取平台的上电信息;