Camera(5) MTK camera驱动框架介绍

一、概序

前文已经介绍了camera驱动部分的内容 Camera(4) MTK camera驱动结构介绍,这里在回顾下之前的框架图。

这篇主要介绍红框部分的内容:
在这里插入图片描述
imgsensor起到承上启下的作用,在系统起来时会创建整个camera驱动运行的环境,其中主要的文件和函数如下框图所示,先通过platform_driver_register函数注册platform设备,在匹配成功后会调用probe函数进行初始相关的设备:
在这里插入图片描述
其中camera的三路电压的上电方式可以通过GPIO来控制,也可以通过PMIC(REGULATOR)的方式来进行控制,在imgsensor_hw中通过不同的pdev信息,调用不同的set函数。涉及的文件路径:

kernel-4.9/drivers/misc/mediatek/imgsensor/src/common/v1/imgsensor.c
kernel-4.9/drivers/misc/mediatek/imgsensor/src/common/v1/imgsensor_hw.c
kernel-4.9/drivers/misc/mediatek/imgsensor/src/mt6765/camera_hw/regulator/regulator.c
kernel-4.9/drivers/misc/mediatek/imgsensor/src/mt6765/camera_hw/gpio/gpio.c

二、上电相关的结构体之间的联系

(1) IMGSENSOR_HW结构体:

IMGSENSOR_HW结构体包含了pdev(gpio/regulator)的设备结构体和上电时序相关的结构体:
在这里插入图片描述

(2) 上电时序控制相关:

上电方式控制: GPIO? REGULATOR?
在这里插入图片描述
上电时序控制结构体:
在这里插入图片描述

三、系统初始化:

1、设备加载:

imgsensor和其他的驱动模块相同,也是通过module_init来初始化模块,在init中注册platform总线驱动,从而需要对应的platform_driver结构体信息:

static const struct of_device_id gimgsensor_of_device_id[] = {
   	{ .compatible = "mediatek,camera_hw", },
   	{}
};
    
static struct platform_driver gimgsensor_platform_driver = {
   	.probe      = imgsensor_probe,
   	.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
   	}
};

gimgsensor_of_device_id的信息在dtsmatch上以后回调执行到对应的probe函数,probe中主要注册了sensor drv的字符设备和初始化imgsensor的硬件信息(时钟及上电):

static int imgsensor_probe(struct platform_device *pdev)
{
   	/* Register char driver */
   	imgsensor_driver_register();
    
   	gpimgsensor_hw_platform_device = pdev;
    
   	imgsensor_clk_init(&pgimgsensor->clk);
   	imgsensor_hw_init(&pgimgsensor->hw);
   	imgsensor_i2c_create();
   	imgsensor_proc_init();
     
   	atomic_set(&pgimgsensor->imgsensor_open_cnt, 0);
   	return 0;
}

2、imgsensor_driver_register创建字符设备

//字符设备的file_operation结构体
static const struct file_operations gimgsensor_file_operations = {
   	.owner = THIS_MODULE,
   	.open = imgsensor_open,
   	.release = imgsensor_release,
   	.unlocked_ioctl = imgsensor_ioctl,
#ifdef CONFIG_COMPAT
   	.compat_ioctl = imgsensor_compat_ioctl
#endif
};
     
static inline int imgsensor_driver_register(void){
    //分配一个设备号和nanme
    alloc_chrdev_region(&dev_no, 0, 1, IMGSENSOR_DEV_NAME)
     
     /* Allocate driver */
    gpimgsensor_cdev = cdev_alloc();
     
    /* Attatch file operation. */
    cdev_init(gpimgsensor_cdev, &gimgsensor_file_operations);
     
    /* Add to system */
    cdev_add(gpimgsensor_cdev, dev_no, 1);
     
    gpimgsensor_class = class_create(THIS_MODULE, "sensordrv");
     
    device_create(gpimgsensor_class, NULL, dev_no, NULL, IMGSENSOR_DEV_NAME);
}

3、imgsensor_clk_init 时钟初始化:

enum IMGSENSOR_RETURN imgsensor_clk_init(struct IMGSENSOR_CLK *pclk)
{
   	int i;
   	struct platform_device *pplatform_dev = gpimgsensor_hw_platform_device;
    
   	/* get all possible using clocks */
   	for (i = 0; i < IMGSENSOR_CCF_MAX_NUM; i++)
   		pclk->imgsensor_ccf[i] =
   		    devm_clk_get(&pplatform_dev->dev, gimgsensor_mclk_name[i]);
    
   	return IMGSENSOR_RETURN_SUCCESS;
}

4、imgsensor_hw_init电压初始化:

(1) 依次调用GPIO/REGULATOR/MCLKinit接口;

(2) 解析出imgsensor_custom_config,获取到对应sensor的对应管脚(DVDD/AVDD...)的上电方式(GPIO/REGULATOR);

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];
   	struct device_node *of_node
   		= of_find_compatible_node(NULL, NULL, "mediatek,camera_hw");
    //依次调用GPIO/REGULATOR/MCLK的init接口;
   	for (i = 0; i < IMGSENSOR_HW_ID_MAX_NUM; i++) {
    	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);
    }
    //解析出imgsensor_custom_config
   	for (i = 0; i < IMGSENSOR_SENSOR_IDX_MAX_NUM; i++) {
   		psensor_pwr = &phw->sensor_pwr[i];
     
    	pcust_pwr_cfg = imgsensor_custom_config;//上电时序
    	while (pcust_pwr_cfg->sensor_idx != i)
    		pcust_pwr_cfg++;
     
   		//退出循环
   		if (pcust_pwr_cfg->sensor_idx == IMGSENSOR_SENSOR_IDX_NONE)
   			continue;
     
   		//ppwr_info对应{IMGSENSOR_HW_ID_GPIO, IMGSENSOR_HW_PIN_AVDD}
   		ppwr_info = pcust_pwr_cfg->pwr_info;
    		
    	while (ppwr_info->pin != IMGSENSOR_HW_PIN_NONE) {
    		//查询imgsensor_custom_config中ID_PIN 是否在GPIO/REGULATOR/Mclk中?
    		for (j = 0; j < IMGSENSOR_HW_ID_MAX_NUM; j++){
    			if (ppwr_info->id == phw->pdev[j]->id)
    				break;
   			 }
   			//将对应sensor的对应PIN(DVDD/AVDD...)设置为系统的ID_PIN(GPIO/REGULATOR/MCKL)
   			psensor_pwr->id[ppwr_info->pin] = j;
   			ppwr_info++;
   		}
   	}
     
   	//判断dts中是否设定对应的index为对应的name,如:cam3_enable_sensor = "gc2375hmain3_mipi_raw";
   	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;
}

5、imgsensor_i2c_create I2C设备初始化:

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;
}

6、具体类型的上电介绍(以pmic控制的regulator方式为例)

前面imgsensor_hw_init中有去调用imgsensor_hw_regulator_openregulator_init

(1) 传入对应的设备的device结构体

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;
}

(2) 调用对应的init进行初始化

因为MTK平台的PMIC上电是通过统一的REGULATOR进行统一管理的,每一种上电方式需要申请对应typeregulator控制的结构体,才可以来进行设置:

enum REGULATOR_TYPE {
   	REGULATOR_TYPE_VCAMA,
   	REGULATOR_TYPE_VCAMD,
   	REGULATOR_TYPE_VCAMIO,
   	REGULATOR_TYPE_MAX_NUM
};
     
static enum IMGSENSOR_RETURN regulator_init(void *pinstance)
{
   	struct REGULATOR *preg = (struct REGULATOR *)pinstance;
   	struct device            *pdevice;
   	struct device_node       *pof_node;
   	int j, i;
   	char str_regulator_name[LENGTH_FOR_SNPRINTF];
     
   	pdevice  = gimgsensor_device;
    
   	for (j = IMGSENSOR_SENSOR_IDX_MIN_NUM;j < IMGSENSOR_SENSOR_IDX_MAX_NUM;j++) {
   		for (i = 0; i < REGULATOR_TYPE_MAX_NUM; i++) {
   			snprintf(str_regulator_name,
   				sizeof(str_regulator_name),
   				"cam%d_%s", j,
   				regulator_control[i].pregulator_type);
   			preg->pregulator[j][i] =
   			    regulator_get(pdevice, str_regulator_name);
    
   			if (preg->pregulator[j][i] == NULL)
   				pr_err("regulator[%d][%d]  %s fail!\n",
   					j, i, str_regulator_name);
     
   			atomic_set(&preg->enable_cnt[j][i], 0);
   		}
   	}
   	pdevice->of_node = pof_node;
   	imgsensor_oc_init();
   	return IMGSENSOR_RETURN_SUCCESS;
}

到这里imgsensor部分的内容,就还有对上(hal层)承接的ioctl相关的内容没有介绍,这部分的内容会在后续的整个系统调用流程中进行梳理。

  • 5
    点赞
  • 53
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: MTK平台上的camera驱动教学课程旨在教授学员有关MTK平台上如何编写、安装和调试camera驱动程序的知识和技能。在这门课程中,学员将学习如何使用MTK平台提供的相应工具和接口来开发和优化camera驱动,以实现更好的图像质量和性能。 课程的内容包括以下几个方面: 1. 理论知识:学员将了解摄像头驱动的基本原理和工作原理,包括硬件架构、设备驱动接口和底层算法等。 2. 驱动开发环境搭建:学员将学习如何在MTK平台上搭建合适的开发环境,包括操作系统、编译器和调试工具等。 3. 驱动编写:学员将学习如何编写MTK平台上的camera驱动程序,包括设备初始化、图像采集和处理等功能的实现。 4. 驱动安装与调试:学员将学习如何将开发好的驱动程序安装到MTK平台上,并进行调试和优化,以确保驱动的稳定性和性能。 5. 实践项目:学员将完成一个实际的项目,如编写一个简单的camera应用程序或实现某种特定的图像处理算法,以应用所学知识并提升实践能力。 通过这门课程,学员将掌握MTK平台上camera驱动开发的基本技能,能够独立完成camera驱动的编写、安装和调试工作,并具备进一步深入研究和优化的能力。这对于从事手机软件开发、图像处理等领域的工程师和研究人员来说,将是一门非常实用和重要的课程。 ### 回答2: MTK平台的Camera驱动教学课程是针对使用MTK芯片的开发人员设计的一门课程。该课程旨在教授学员有关MTK平台中Camera驱动的基础知识、开发技巧和调试方法。 首先,课程将介绍MTK平台和其特点,帮助学员了解MTK芯片及其应用领域。接下来,课程将重点讲解Camera驱动的原理和工作机制,涵盖Camera传感器的工作原理、图像采集和处理流程等方面的知识。 课程还将介绍Camera驱动的开发环境和工具,如MTK平台上的Camera HAL层和相应的调试工具。学员将学会如何配置和编译Camera驱动,以及如何使用调试工具进行驱动的调试和性能优化。 除了理论知识的讲解,课程还将通过实例演示和实践操作帮助学员掌握Camera驱动的开发技巧。学员将有机会参与实际的Camera驱动开发项目,通过实践来加深对课程知识的理解和应用能力。 总结起来,MTK平台的Camera驱动教学课程旨在提供一套系统化的学习资源,帮助学员全面了解和掌握MTK平台上的Camera驱动开发。通过学习这门课程,学员将能够独立进行MTK平台上Camera驱动的开发和调试工作,从而为MTK芯片应用的开发和优化提供支持。 ### 回答3: MTK平台CMOS摄像头驱动开发是一门与软硬件结合紧密的技术课程。首先,学习者需要熟悉MTK平台的基本知识,包括芯片结构、嵌入式系统以及Linux操作系统的基本原理。其次,学习者需要了解摄像头工作原理和常用的摄像头传感器类型,例如CMOS和CCD传感器。在掌握这些基础知识后,学习者可以开始学习MTK平台上的摄像头驱动开发。 在开发摄像头驱动时,学习者需要掌握如何通过MTK平台提供的驱动接口与摄像头硬件进行通信。这包括配置摄像头的分辨率、帧率、曝光时间以及白平衡等参数。此外,还需要了解如何处理摄像头的数据传输和处理,例如图像的压缩、旋转、镜像等操作。 在学习过程中,学习者可以通过阅读相关的文档和资料,参考MTK平台提供的示例代码来加深理解。同时,实际动手开发和调试也是非常重要的,可以通过连接MTK平台开发板和摄像头来调试和验证自己的驱动代码。学习者还可以通过与其他开发者交流和分享经验,提升自己的开发能力。 总之,MTK平台摄像头驱动开发是一门需要结合软硬件知识的综合性课程,通过学习掌握相关的理论知识和实践经验,可以帮助学习者深入了解摄像头驱动的工作原理和开发流程,提高自己的技术水平。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值