Android MTK Camera驱动代码分析

一、Camera调用过程:
分层
     imgsensor起到承上启下的作用,在系统起来时会创建整个camera驱动运行的环境,其中主要的文件和函数如下框图所示,先设备挂载时会调用注册platform设备platform_driver_register,在匹配成功后会调用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) 上电时序控制相关:
kernel-4.9/drivers/misc/mediatek/imgsensor/src/mt6765/camera_hw/imgsenor_cfg_table.h
kernel-4.9/drivers/misc/mediatek/imgsensor/src/mt6765/camera_hw/imgsenor_cfg_table.c
上电方式控制:GPIO供电还是REGULATOR供电 查看原理图与规格书
上电时序控制结构体:

enum IMGSENSOR_SENSOR_IDX { //sensor di  MAIN = 0 SUB = 1 MAIN2 = 2
	IMGSENSOR_SENSOR_IDX_MIN_NUM = 0,
	IMGSENSOR_SENSOR_IDX_MAIN = IMGSENSOR_SENSOR_IDX_MIN_NUM,
	IMGSENSOR_SENSOR_IDX_SUB,
	IMGSENSOR_SENSOR_IDX_MAIN2,
	IMGSENSOR_SENSOR_IDX_SUB2,
	IMGSENSOR_SENSOR_IDX_MAIN3,
	IMGSENSOR_SENSOR_IDX_MAX_NUM,
	IMGSENSOR_SENSOR_IDX_NONE,
};
struct IMGSENSOR_HW_CFG {  //供电信息配置的结构体  PMIC供电 或 GPIO供电
	enum IMGSENSOR_SENSOR_IDX sensor_idx;
	enum IMGSENSOR_I2C_DEV i2c_dev;
	struct IMGSENSOR_HW_CUSTOM_POWER_INFO pwr_info[IMGSENSOR_HW_POWER_INFO_MAX];//电源信息结构体数组
};
struct IMGSENSOR_HW_CUSTOM_POWER_INFO {
	enum IMGSENSOR_HW_ID id;
	enum IMGSENSOR_HW_PIN pin;
};
struct IMGSENSOR_HW_CFG imgsensor_custom_config[] = {
	{
	IMGSENSOR_SENSOR_IDX_MAIN,
	IMGSENSOR_I2C_DEV_0,
	{
		{IMGSENSOR_HW_ID_MCLK, IMGSENSOR_HW_PIN_MCLK},
		{IMGSENSOR_HW_ID_REGULATOR, IMGSENSOR_HW_PIN_AVDD},//REGULATOR即为PMIC供电
		{IMGSENSOR_HW_ID_REGULATOR, IMGSENSOR_HW_PIN_DOVDD},
		{IMGSENSOR_HW_ID_REGULATOR, IMGSENSOR_HW_PIN_DVDD},
		{IMGSENSOR_HW_ID_REGULATOR, IMGSENSOR_HW_PIN_AFVDD},
		{IMGSENSOR_HW_ID_GPIO, IMGSENSOR_HW_PIN_AF_EN},   //GPIO即为GPIO供电
		{IMGSENSOR_HW_ID_GPIO, IMGSENSOR_HW_PIN_PDN},
		{IMGSENSOR_HW_ID_GPIO, IMGSENSOR_HW_PIN_RST},
		{IMGSENSOR_HW_ID_NONE, IMGSENSOR_HW_PIN_NONE},
	},
	},  
	...

(2)上电时序控制结构体

struct IMGSENSOR_HW_POWER_INFO {
	enum IMGSENSOR_HW_PIN pin;
	enum IMGSENSOR_HW_PIN_STATE pin_state_on;
	u32 pin_on_delay;
	enum IMGSENSOR_HW_PIN_STATE pin_state_off;
	u32 pin_off_delay;
};
struct IMGSENSOR_HW_POWER_SEQ {  //上电时序结构体
	char *name;
	struct IMGSENSOR_HW_POWER_INFO pwr_info[IMGSENSOR_HW_POWER_INFO_MAX];
	u32 _idx;
};
struct IMGSENSOR_HW_POWER_SEQ platform_power_sequence[] = {
#ifdef MIPI_SWITCH
        {
                PLATFORM_POWER_SEQ_NAME,
                {
                        {
                                IMGSENSOR_HW_PIN_MIPI_SWITCH_EN,
                                IMGSENSOR_HW_PIN_STATE_LEVEL_0,
                                0,
                                IMGSENSOR_HW_PIN_STATE_LEVEL_HIGH,
                                0
                        },
                        {
                                IMGSENSOR_HW_PIN_MIPI_SWITCH_SEL,
                                IMGSENSOR_HW_PIN_STATE_LEVEL_HIGH,
                                0,
                                IMGSENSOR_HW_PIN_STATE_LEVEL_0,
                                0
                        },
                },
                IMGSENSOR_SENSOR_IDX_SUB,
        },
        {
                PLATFORM_POWER_SEQ_NAME,
                {
                        {
                                IMGSENSOR_HW_PIN_MIPI_SWITCH_EN,
                                IMGSENSOR_HW_PIN_STATE_LEVEL_0,
                                0,
                                IMGSENSOR_HW_PIN_STATE_LEVEL_HIGH,
                                0
                        },
                        {
                                IMGSENSOR_HW_PIN_MIPI_SWITCH_SEL,
                                IMGSENSOR_HW_PIN_STATE_LEVEL_0,
                                0,
                                IMGSENSOR_HW_PIN_STATE_LEVEL_0,
                                0
                        },
                },
                IMGSENSOR_SENSOR_IDX_MAIN2,
        },
#endif
struct IMGSENSOR_HW_POWER_SEQ sensor_power_sequence[] = {
	#if defined(HI1336_MIPI_RAW)
	{
		SENSOR_DRVNAME_HI1336_MIPI_RAW,   //上电时序
		{
		{DOVDD, Vol_1800, 1}, //电压相关查看规格书配置表
		{DVDD, Vol_1100, 5},
		{AVDD, Vol_2800, 1},
		{AFVDD, Vol_2800, 1}, //马达上电相关
		{AFVDD_EN, Vol_Low, 0}, //马达上电相关
		{AFVDD_EN, Vol_High, 1}, //马达上电相关
		{SensorMCLK, Vol_High, 0},
		{RST, Vol_Low, 10},
		{RST, Vol_High, 1},
		},
	},
	#endif 
	...
	...
	 VCAMD 主要给 ISP 供电; VCAM_IO 是数字IO电源,主要给I2C供电, 
	 VCAMA 是模拟供电,主要给 感光区 和 ADC 部分供电, VCAMAF 主要给对焦马达供电;

kernel-4.9/drivers/misc/mediatek/imgsensor/src/common/v1/imgsensor_hw.c
上述的上电配置、时序最终都会在Imgsensor_hw.c中调用
├── imgsensor_power
├── imgsensor_power_sequence
├── imgsensor_hw_init
└── imgsensor_hw_release_all

三、平台设备驱动的注册加载
kernel-4.9/drivers/misc/mediatek/imgsensor/src/common/v1/imgsensor.c
kernel-4.9/drivers/misc/mediatek/imgsensor/src/common/v1/imgsensor_proc.c
kernel-4.9/drivers/base/platform.c
kernel-4.9/include/linux/of_device.h

平台设备驱动匹配的进化过程https://www.cnblogs.com/zzb-Dream-90Time/p/7250010.html
     camera 驱动先是注册 platform 平台驱动,然后注册Camera字符设备,创建class类,再通过 I2c 注册前后摄注册字符设备,封装底层方法 imgsensor_ioctl,上层访问底层驱动时候先是使用 setdriver 获取具体IC的驱动的入口,然后使用 checkisalive 对 sensorlist 中的 IC 进行上电,上电完成就通过 I2C 读取设备 ID ,到此为止,上层应用与底层驱动挂接完成,紧接着就是预览和拍照,具体 IC 驱动的实现了。
(1)设备加载 module_init加载模块,注册platform总线驱动

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
	}
};
	Platform.c调用of_driver_match_device → of_match_device(drv->of_match_table, dev)__of_match_node()去匹配,
通过把device_driver的of_match_table(of_device_id结构体的数组)和device里的of_node(device_node结构体)进行匹配,匹配方式
是分别比较两者的name、type、和compatible字符串,三者要同时相同(一般name、和type为空,只比较compatible字符串),设备树加载
的时候构建了device设备,被初始化了of_node成员,即设备树加载之后,内核会自动把设备树节点转换成 platform_device这种格式,同时把
名字放到of_node这个地方

static int imgsensor_probe(struct platform_device *pdev)
{
	/* Register char driver */
	if (imgsensor_driver_register()) {       //注册imgsensor字符设备驱动
	pr_err("[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
	imgsensor_hw_init(&pgimgsensor->hw);
	imgsensor_i2c_create();
	imgsensor_proc_init();//与proc文件系统有关  ↓↓
	atomic_set(&pgimgsensor->imgsensor_open_cnt, 0);//原子操作
	#ifdef CONFIG_MTK_SMI_EXT  //mmdevfs is set for mtk multimedia driver
		mmdvfs_register_mmclk_switch_cb(mmsys_clk_change_cb,MMDVFS_CLIENT_ID_ISP);
	#endif
	return 0;
} 
proc_create("driver/camsensor", 0664, NULL,&fcamera_proc_fops); //在proc文件夹下创建虚拟文件及其权限
static const struct file_operations fcamera_proc_fops = {
     .owner = THIS_MODULE,
     .read = seq_read,
     .open = proc_camsensor_open,
     .write = CAMERA_HW_Reg_Debug
};

(2)创建字符设备

static const struct file_operations gimgsensor_file_operations = {
	.owner = THIS_MODULE,
	.open = imgsensor_open,
	.release = imgsensor_release,
	.unlocked_ioctl = imgsensor_ioctl,// camera的控制函数 adopt_CAMERA_HW_FeatureControl 硬件初始化
	#ifdef CONFIG_COMPAT               //上调用imgsensor_set_driver()  寻找sensor进行硬件初始化 
	.compat_ioctl = imgsensor_compat_ioctl   //上调用imgsensor_i2c_init() 
	#endif                                  
};
static inline int imgsensor_driver_register(void)
{
	dev_t dev_no = MKDEV(IMGSENSOR_DEVICE_NNUMBER, 0);//申请主设备号  
	if (alloc_chrdev_region(&dev_no, 0, 1, IMGSENSOR_DEV_NAME)) {  // 主 次设备号  申请次设备号的个数  cat /proc/devices显示的名称
		pr_debug("[CAMERA SENSOR] Allocate device no failed\n");
		return -EAGAIN;
	}
/* Allocate driver */
	gpimgsensor_cdev = cdev_alloc(); //cdev 分配空间
	if (gpimgsensor_cdev == NULL) {
		unregister_chrdev_region(dev_no, 1);
		pr_debug("[CAMERA SENSOR] Allocate mem for kobject failed\n");
		return -ENOMEM;
	}
	/* Attatch file operation. */
	cdev_init(gpimgsensor_cdev, &gimgsensor_file_operations);//字符设备的操作函数
	gpimgsensor_cdev->owner = THIS_MODULE;
	/* Add to system */
	if (cdev_add(gpimgsensor_cdev, dev_no, 1)) { //初始化cdev,通过cdev_add加入到系统中
		pr_debug("Attatch file operation failed\n");
		unregister_chrdev_region(dev_no, 1);//没有add成功,需要释放设备号
		return -EAGAIN;
	}
	gpimgsensor_class = class_create(THIS_MODULE, "sensordrv");//创建类 /sys/class/
	if (IS_ERR(gpimgsensor_class)) {
		int ret = PTR_ERR(gpimgsensor_class);
		pr_debug("Unable to create class, err = %d\n", ret);
		return ret;
	}
	gimgsensor_device =device_create(gpimgsensor_class,NULL, // sys/class/sensordrv/IMGSENSOR_DEV_NAME
									dev_no,NULL,IMGSENSOR_DEV_NAME);
	return 0;
} 

(3)时钟初始化
kernel-4.9/drivers/misc/mediatek/imgsensor/src/mt6765/imgsensor_clk.c

enum IMGSENSOR_RETURN imgsensor_clk_init(struct IMGSENSOR_CLK *pclk)
{
        int i;
        struct platform_device *pplatform_dev = gpimgsensor_hw_platform_device;//extern外部
        //在imgsensor.c中 imgsensor_probe传入的platform_device*pdev赋值给gpimgsensor_hw_platform_device
        if (pplatform_dev == NULL) {
                pr_err("[%s] pdev is null\n", __func__);
                return IMGSENSOR_RETURN_ERROR;
        }
        /* get all possible using clocks */
        for (i = 0; i < IMGSENSOR_CCF_MAX_NUM; i++)//imgsensor_clk.h中enum IMGSENSOR_CCF中定义
                pclk->imgsensor_ccf[i] =           // ccf clock common framework      
                    devm_clk_get(&pplatform_dev->dev,gimgsensor_mclk_name[i]); 
        return IMGSENSOR_RETURN_SUCCESS;
}
 devm_clk_get,和clk_get一样,只是使用了device resource management,可以自动释放;在申请资源会判断是否失败,因此
 会充斥着大量繁琐的代码,设备资源管理即可driver你只管申请就行了,不用考虑释放,我设备模型帮你释放。
 clk_get,以device指针或者id字符串(可以看作name)为参数,查找clock。
     (1)dev和id的任意一个可以为空。如果id为空,则必须有device tree的支持才能获得device对应的clk;
     (2)根据具体的平台实现,id可以是一个简单的名称,也可以 是一个预先定义的、唯一的标识(一般在平台提供的头文件中定义,如mach/clk.h);
     (3)不可以在中断上下文调用。
char *gimgsensor_mclk_name[IMGSENSOR_CCF_MAX_NUM] = {
        "CLK_TOP_CAMTG_SEL",
        "CLK_TOP_CAMTG1_SEL",
        "CLK_TOP_CAMTG2_SEL",
        "CLK_TOP_CAMTG3_SEL",
        "CLK_MCLK_6M",
        "CLK_MCLK_12M",
        "CLK_MCLK_13M",
        "CLK_MCLK_24M",
        "CLK_MCLK_26M",
        "CLK_MCLK_48M",
        "CLK_MCLK_52M",
        "CLK_CAM_SENINF_CG",
        "CLK_MIPI_C0_26M_CG",
        "CLK_MIPI_C1_26M_CG",
        "CLK_MIPI_ANA_0A_CG",
        "CLK_MIPI_ANA_0B_CG",
        "CLK_MIPI_ANA_1A_CG",
        "CLK_MIPI_ANA_1B_CG",
        "CLK_MIPI_ANA_2A_CG",
        "CLK_MIPI_ANA_2B_CG",
        "CLK_TOP_CAMTM_SEL_CG",
        "CLK_TOP_CAMTM_208_CG",
        "CLK_SCP_SYS_CAM",
};

(4)电压初始化
电压
(1)依次调用GPIO/REGULATOR/MCLK的init接口;
(2)解析出imgsensor_custom_config,获取到对应sensor的对应管脚(DVDD/AVDD…)的上电方式(GPIO/REGULATOR);
kernel-4.9/drivers/misc/mediatek/imgsensor/src/common/v1/imgsensor_hw.c

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");//匹配节点,of操作之一
	      //依次调用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 = 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设备初始化 //注册前后摄像头驱动
     IMGSENSOR_I2C_DEV_MAX_NUM 通过枚举进行赋值,其值为3,说明最多可以注册的摄像头驱动为3个。因为camera 驱动是挂载在 I2C总线 上,所以通过函数 i2c_add_driver() 进行注册。gi2c_driver 结构体对应一个具体 camera 设备的驱动。
/kernel-4.9/drivers/misc/mediatek/imgsensor/src/mt6739/camera_hw/imgsensor_cfg_table.h
下方匹配的名称都使用了imgsensor_cfg_table.h中

/* 如果不使用设备树,会匹配这三个宏 */  
 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},
        {}
 }; 
#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"

kernel-4.9/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;
}
#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, },
    {}
};
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,
    }
}
#endif

使用MTK DrvGen生成
./out/target/product/xxx/obj/KERNEL_OBJ/arch/arm/boot/dts/xxx/cust.dtsi
xxx.dts中包含cust_mt6765_camera.dtsi中包含kd_camera_hw1节点;
cust.dtsi中也包含kd_camera_hw1节点,后者会出现下相同会进行覆盖

&i2c2 {
        #address-cells = <1>;
        #size-cells = <0>;
        clock-frequency = <400000>;
        mediatek,use-open-drain;
        camera_main_mtk:camera_main@20 {
                compatible = "mediatek,camera_main";
                reg = <0x20>;
                status = "okay";
        };

        camera_main_af_mtk:camera_main_af@0c {
                compatible = "mediatek,camera_main_af";
                reg = <0x0c>;
                status = "okay";
        };

        camera_sub_mtk:camera_sub@3c {
                compatible = "mediatek,camera_sub";
                reg = <0x3c>;
                status = "okay";
        };
};
...
...

     当内核启动后,会解析dts编译生成的dtb文件,注册里面定义的 device ,代码中设置的 of_device_id 需要分别匹配上 cust.dtsi 文件中的 compatible 节点 “mediatek,camera_main” 和 “mediatek,camera_sub” 。如果和驱动中定义 compatible 字段一致,则挂载启动。上面注册了两个platform 驱动 gi2c_driver 。如果 compatible 匹配成功会调用各自的 probe 函数 imgsensor_i2c_probe_0,imgsensor_i2c_probe_1 。

(6) imgsensor_ioctl上层用于摄像头的具体操作
kernel-4.9/drivers/misc/mediatek/imgsensor/src/common/v1/kd_sensorlist.c
kernel-4.9/drivers/misc/mediatek/imgsensor/src/common/v1/kd_sensorlist.h

#define KDIMGSENSORIOC_T_OPEN _IO(IMGSENSORMAGIC, 0)
#define KDIMGSENSORIOC_X_SET_DRIVER _IOWR(IMGSENSORMAGIC, 35, SENSOR_DRIVER_INDEX_STRUCT)
#define HI1336_SENSOR_ID 0x1336
#define SENSOR_DRVNAME_HI1336_MIPI_RAW "hi1336_mipi_raw"

kernel-4.9/drivers/misc/mediatek/imgsensor/src/common/v1/imgsensor_sensor_list.c
kernel-4.9/drivers/misc/mediatek/imgsensor/src/common/v1/imgsensor_sensor_list.h

UINT32 HI1336_MIPI_RAW_SensorInit(struct SENSOR_FUNCTION_STRUCT **pfFunc);
 最终实现在具体sensor的驱动函数中hi336mipiraw_Sensor.c,操作寄存器去完成功能 ↓↓↓
struct IMGSENSOR_INIT_FUNC_LIST kdSensorList[MAX_NUM_OF_SUPPORT_SENSOR] = {
#if defined(HI1336_MIPI_RAW)
        {HI1336_SENSOR_ID,
        SENSOR_DRVNAME_HI1336_MIPI_RAW,
        HI1336_MIPI_RAW_SensorInit},
#endif
...
       /*  ADD sensor driver before this line */
        {0, {0}, NULL}, /* end of list */
};

vendor/mediatek/proprietary/custom/mt6765/hal/imgsensor_src/sensorlist.cpp
注意Kernel层中的kdSensorList和HAL层中的sensorList的顺序必须保持一致

MSDK_SENSOR_INIT_FUNCTION_STRUCT SensorList[] =
{
#if defined(HI1336_MIPI_RAW)
    RAW_INFO(HI1336_SENSOR_ID, SENSOR_DRVNAME_HI1336_MIPI_RAW,
CAM_CALGetCalData),
#endif
/*  ADD sensor driver before this line */
    {0, 0,{0}, NULL, NULL, NULL}//end of list
};
 
UINT32 GetSensorInitFuncList(MSDK_SENSOR_INIT_FUNCTION_STRUCT
**ppSensorList)
{
    if (NULL == ppSensorList) {
        ALOGE("ERROR: NULL pSensorList\n");
        return MHAL_UNKNOWN_ERROR;
    }
    *ppSensorList = &SensorList[0];
        return MHAL_NO_ERROR;
}

kernel-4.9/drivers/misc/mediatek/imgsensor/src/common/v1/hi1336_mipi_raw/hi1336mipiraw_Sensor.c

static struct SENSOR_FUNCTION_STRUCT sensor_func = {
        open,
        get_info,
        get_resolution,
        feature_control,
        control,
        close
};
UINT32 HI1336_MIPI_RAW_SensorInit(struct SENSOR_FUNCTION_STRUCT **pfFunc)
{
        /* To Do : Check Sensor status here */
        if (pfFunc != NULL)
                *pfFunc =  &sensor_func;
        return ERROR_NONE;
}       /*      HI1336_MIPI_RAW_SensorInit      */

     Hal层发送 ioctl(m_fdSensor, KDIMGSENSORIOC_X_FEATURECONCTROL, &sensorIdx);
     Kernel 接受 KDIMGSENSORIOC_X_FEATURECONCTROL指令,调用 adopt_CAMERA_HW_FeatureControl()

static long imgsensor_ioctl(struct file *a_pstFile,unsigned int a_u4Command,unsigned long a_u4Param)
{//还有一个函数imgsensor_compat_ioctl具体用于操作什么还未分析
        int i4RetValue = 0;
        void *pBuff = NULL;
 
        if (_IOC_DIR(a_u4Command) != _IOC_NONE) {    //_IOC_xx都是宏解析相关的        
                pBuff = kmalloc(_IOC_SIZE(a_u4Command), GFP_KERNEL);
                if (pBuff == NULL) {
                        pr_debug("[CAMERA SENSOR] ioctl allocate mem failed\n");
                        i4RetValue = -ENOMEM;
                        goto CAMERA_HW_Ioctl_EXIT;
                }
 
                if (_IOC_WRITE & _IOC_DIR(a_u4Command)) {
                        if (copy_from_user(pBuff, (void *)a_u4Param, _IOC_SIZE(a_u4Command))) {
                                kfree(pBuff);
                                pr_debug(
                                    "[CAMERA SENSOR] ioctl copy from user failed\n");
                                i4RetValue =  -EFAULT;
                                goto CAMERA_HW_Ioctl_EXIT;
                        }
                }
        } else {
                i4RetValue =  -EFAULT;
                goto CAMERA_HW_Ioctl_EXIT;
        }
 
        switch (a_u4Command) {
        case KDIMGSENSORIOC_X_GET_CONFIG_INFO:
				i4RetValue = adopt_CAMERA_HW_GetInfo(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,
                    (struct ACDK_SENSOR_MCLK_STRUCT *)pBuff);
                break;
        case KDIMGSENSORIOC_T_OPEN:
        case KDIMGSENSORIOC_T_CLOSE:
        case KDIMGSENSORIOC_T_CHECK_IS_ALIVE:
        case KDIMGSENSORIOC_X_SET_DRIVER:
        ...
        default:
                pr_debug("No such command %d\n", a_u4Command);
                i4RetValue = -EPERM;
                break;
 }
        if ((_IOC_READ & _IOC_DIR(a_u4Command)) &&
                    copy_to_user((void __user *) a_u4Param, pBuff,_IOC_SIZE(a_u4Command))) {
                kfree(pBuff);
                pr_debug("[CAMERA SENSOR] ioctl copy to user failed\n");
                i4RetValue =  -EFAULT;
                goto CAMERA_HW_Ioctl_EXIT;
        }
        kfree(pBuff);
CAMERA_HW_Ioctl_EXIT:          //goto操作
        return i4RetValue;   
}
static inline int adopt_CAMERA_HW_FeatureControl(void *pBuf)
{
        struct ACDK_SENSOR_FEATURECONTROL_STRUCT *pFeatureCtrl;
        struct IMGSENSOR_SENSOR *psensor;
        unsigned int FeatureParaLen = 0;
        void *pFeaturePara = NULL;
        struct ACDK_KD_SENSOR_SYNC_STRUCT *pSensorSyncInfo = NULL;
        signed int ret = 0;
 
        pFeatureCtrl = (struct ACDK_SENSOR_FEATURECONTROL_STRUCT *)pBuf;
        if (pFeatureCtrl  == NULL) {
                pr_err(" NULL arg.\n");
                return -EFAULT;
        }
        psensor = imgsensor_sensor_get_inst(pFeatureCtrl->InvokeCamera);
        if (psensor == NULL) {
                pr_err("[adopt_CAMERA_HW_FeatureControl] NULL psensor.\n");
                return -EFAULT;
        }
 
        if (pFeatureCtrl->FeatureId == SENSOR_FEATURE_SINGLE_FOCUS_MODE ||
                pFeatureCtrl->FeatureId == SENSOR_FEATURE_CANCEL_AF ||
                pFeatureCtrl->FeatureId == SENSOR_FEATURE_CONSTANT_AF ||
                pFeatureCtrl->FeatureId == SENSOR_FEATURE_INFINITY_AF) {
                /* YUV AF_init and AF_constent and AF_single has no params */
        } else {
                if (pFeatureCtrl->pFeaturePara == NULL ||
                    pFeatureCtrl->pFeatureParaLen == NULL) {
                        pr_err(" NULL arg.\n");
                        return -EFAULT;
                }
                if (copy_from_user((void *)&FeatureParaLen,
                                (void *) pFeatureCtrl->pFeatureParaLen, sizeof(unsigned int))) {
                        pr_err(" ioctl copy from user failed\n");
                        return -EFAULT;
                }
                if (FeatureParaLen > FEATURE_CONTROL_MAX_DATA_SIZE ||
                        FeatureParaLen == 0)
                        return -EINVAL;
                ret = check_length_of_para(pFeatureCtrl->FeatureId, FeatureParaLen);
                if (ret != 0)
                        return ret;
                pFeaturePara = kmalloc(FeatureParaLen, GFP_KERNEL);
                if (pFeaturePara == NULL)
                        return -ENOMEM;
                memset(pFeaturePara, 0x0, FeatureParaLen);
        }
        /* copy from user */
        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;
        }
        case SENSOR_FEATURE_CHECK_IS_ALIVE:
                imgsensor_check_is_alive(psensor);
                break;
    ....
       case SENSOR_FEATURE_SET_PDAF:
       case SENSOR_FEATURE_GET_PDAF_INFO:
        ...
       case SENSOR_FEATURE_SET_STREAMING_RESUME:
                if (copy_from_user(
                    (void *)pFeaturePara,
                    (void *) pFeatureCtrl->pFeaturePara,
                    FeatureParaLen)) {
                        kfree(pFeaturePara);
                        pr_err(
                            "[CAMERA_HW][pFeaturePara] ioctl copy from user failed\n");
                        return -EFAULT;
                }
                break;
/    * keep the information to wait Vsync synchronize */
                pSensorSyncInfo =
                    (struct ACDK_KD_SENSOR_SYNC_STRUCT *)pFeaturePara;
                FeatureParaLen = 2;
        	    imgsensor_sensor_feature_control(
                    psensor,
                    SENSOR_FEATURE_SET_GAIN,
                    (unsigned char *)&pSensorSyncInfo->u2SensorNewGain,
                    (unsigned int *) &FeatureParaLen);
                break;
    }
     kfree(pFeaturePara);
        if (copy_to_user(
            (void __user *) pFeatureCtrl->pFeatureParaLen,
            (void *)&FeatureParaLen,
            sizeof(unsigned int))) {
                pr_debug(
                    "[CAMERA_HW][pFeatureParaLen] ioctl copy to user failed\n"); 
                return -EFAULT;
        }
        return ret;
 }

http://blog.csdn.net/LinuxArmbiggod/article/details/91884229
https://www.it610.com/article/1282418947416670208.htm
https://blog.csdn.net/u010783226/article/details/105658842
https://blog.csdn.net/LinuxArmbiggod/article/details/91884229
https://blog.csdn.net/wuye110/article/details/78536322/

一、 手机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驱动添加、调试流程:.......
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值