【Mtk Camera Hal到驱动的流程(2)】

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
FileDecription
imgsensor.csensor 驱动适配器和驱动入口函数的实现
imgsensor_hw.csensor 电源控制的实现
imgsensor_i2c.cI2C 读写函数的实现
imgsensor_proc.cproc文件系统相关部分的实现
imgsensor_sensor_list.c包含所有sensor初始化函数的表单
imgsensor_legacy.csensor的旧的接口部分。主要是与I2c相关API
imgsensor_cfg_table.csensor电源和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_devicesplatform_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 获取平台的上电信息;
一、 手机CAMERA的物理结构: ........................................................................................ - 4 - 二、 CAMERA的成像原理: ................................................................................................. - 4 - 三、 CAMERA常见的数据输出格式:.................................................................................. - 5 - 四、 阅读CAMERA的规格书(以TRULY模组OV5647_RAW为例): ........................... - 6 - 五、 CAMERA的硬件原理图及引脚 ..................................................................................... - 7 - 1、 电源部分:.................................................................................................................... - 7 - 2、 SENSOR INPUT部分: ................................................................................................... - 7 - 3、 SENSOR OUTPUT部分: ............................................................................................... - 7 - 4、 I2C部分:SCL,I2C时钟信号线和SDA,I2C数据信号线。 .................................. - 7 - 六、 MTK平台CAMERA驱动架构: .................................................................................. - 8 - 七、 MTK平台CAMERA相关代码文件(以下代码均为MTK6575平台): .................... - 9 - 1、 CAMERASENSOR驱动相关文件 .................................................................................... - 9 - 2、 SENSOR ID 和一些枚举类型的定义 ............................................................................. - 9 - 3、 SENSOR供电 .................................................................................................................. - 9 - 4、 KERNEL SPACE的SENSORLIST,IMGSENSOR模块注册 ............................................... - 9 - 5、 USER SPACE的SENSORLIST,向用户空间提供支持的SENSORLIST ......................... - 10 - 6、 SENSOR 效果调整的接口 ............................................................................................ - 10 - 八、 CAMERA模块驱动、设备与总线结构: ..................................................................... - 11 - A) 驱动的注册: .................................................................................................................. - 11 - B) 设备的注册: .................................................................................................................. - 11 - C) 总线的匹配: .................................................................................................................. - 12 - 九、 CAMERA驱动工作流程: ............................................................................................- 13 - 十、 CAMERA驱动添加、调试流程:.......
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值