MT6739 camera AF驱动移植

1. 工程配置ProjectConfig

1.1 配置ProjectConfig.mk

文件路径device/mediateksample/k39tv1_bsp/ProjectConfig.mk(device/mediatekprojects//ProjectConfig.mk)

  1. 在全局定义中添加CUSTOM_HAL_LENS、CUSTOM_KERNEL_LENS、CUSTOM_KERNEL_MAIN_LENS,如果已经存在,则不需要额外配置
AUTO_ADD_GLOBAL_DEFINE_BY_VALUE = CUSTOM_HAL_LENS CUSTOM_KERNEL_LENS CUSTOM_KERNEL_MAIN_LENS
  1. 添加lens driver CUSTOM_HAL_LENS、CUSTOM_KERNEL_LENS、CUSTOM_KERNEL_MAIN_LENS
CUSTOM_HAL_LENS = dw9714af dummy_lens /* CUSTOM_HAL_LENS 一般默认存在,只需修改右边内容即可 */
CUSTOM_HAL_MAIN_LENS = dw9714af /* CUSTOM_HAL_MAIN_LENS 一般默认存在,只需修改右边内容即可 */
CUSTOM_KERNEL_LENS = dw9714af dummy_lens /* CUSTOM_KERNEL_LENS 一般默认存在,只需修改右边内容即可 */
CUSTOM_KERNEL_MAIN_LENS = dw9714af /* CUSTOM_KERNEL_MAIN_LENS 一般默认存在,只需修改右边内容即可 */

1.2 配置k39tv1_bsp.dws([ProjectName].dws)

文件路径
1. kernel-4.4/drivers/misc/mediatek/dws/mt6739/k39tv1_bsp.dws
2. out/target/product/k39tv1_bsp/obj/KERNEL_OBJ/arch/arm/boot/dts/k39tv1_bsp/cust.dtsi

  1. 使用txt打开,或者使用内核提供的dct工具打开dws文件k39tv1_bsp.dws,在dws中添加lens设备节点,编译时会内置到cust.dtsi中,一般情况下不需要修改。
  2. Dct工具路径: vendor/mediatek/proprietary/scripts/dct
    在这里插入图片描述
  3. 工具界面显示,打开->选则dws文件->选择I2C。
    在这里插入图片描述
  4. dct编译生成的cust.dtsi中对应的内容
&i2c2 {
	#address-cells = <1>;
	#size-cells = <0>;
	clock-frequency = <400000>;
	mediatek,use-open-drain;
	camera_main_mtk:camera_main@10 {
		compatible = "mediatek,camera_main";
		reg = <0x10>;
		status = "okay";
	};

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

	camera_sub_mtk:camera_sub@36 {
		compatible = "mediatek,camera_sub";
		reg = <0x36>;
		status = "okay";
	};

	camera_main_two_mtk:camera_main_two@6c {
		compatible = "mediatek,camera_main_two";
		reg = <0x6c>;
		status = "okay";
	};

	camera_main_eeprom_mtk:camera_main_eeprom@50 {
		compatible = "mediatek,camera_main_eeprom";
		reg = <0x50>;
		status = "okay";
	};

};

在这里插入图片描述

1.3 配置AF power

文件路径out/target/product/k39tv1_bsp/obj/KERNEL_OBJ/arch/arm/boot/dts/k39tv1_bsp/cust.dtsi
k39tv1_bsp: ProjectName

  1. 电源部分一般不需要改动
&kd_camera_hw1 {
	vcama-supply = <&mt_pmic_vcama_ldo_reg>;
	vcama_sub-supply = <&mt_pmic_vcama_ldo_reg>;
	vcama_main2-supply = <&mt_pmic_vcama_ldo_reg>;
	vcamd-supply = <&mt_pmic_vcamd_ldo_reg>;
	vcamd_sub-supply = <&mt_pmic_vcamd_ldo_reg>;
	vcamd_main2-supply = <&mt_pmic_vcamd_ldo_reg>;
	vcamio-supply = <&mt_pmic_vcamio_ldo_reg>;
	vcamio_sub-supply = <&mt_pmic_vcamio_ldo_reg>;
	vcamio_main2-supply = <&mt_pmic_vcamio_ldo_reg>;
	vcamaf-supply = <&mt_pmic_vldo28_ldo_reg>;
	status = "okay";
};

2. kernel driver

2.1 kernel层驱动架构

文件路径kernel-4.4/drivers/misc/mediatek/lens
main: 主摄
sub: 副摄
main2: 主摄2
在这里插入图片描述
在这里插入图片描述

2.2 修改lens_list.h

文件路径kernel-4.4/drivers/misc/mediatek/lens/main/inc/lens_list.h

  1. 添加接口名称宏定义和接口声明
/* dw9714 */
#define DW9714AF_SetI2Cclient DW9714AF_SetI2Cclient_Main
#define DW9714AF_Ioctl DW9714AF_Ioctl_Main
#define DW9714AF_Release DW9714AF_Release_Main
#define DW9714AF_PowerDown DW9714AF_PowerDown_Main
extern int DW9714AF_SetI2Cclient(struct i2c_client *pstAF_I2Cclient,
				spinlock_t *pAF_SpinLock, int *pAF_Opened);
extern long DW9714AF_Ioctl(struct file *a_pstFile, unsigned int a_u4Command,
				unsigned long a_u4Param);
extern int DW9714AF_Release(struct inode *a_pstInode, struct file *a_pstFile);
extern int DW9714AF_PowerDown(struct i2c_client *pstAF_I2Cclient,
							int *pAF_Opened);

2.3 修改lens_info.h

文件路径kernel-4.4/drivers/misc/mediatek/lens/main/inc/lens_info.h

  1. 添加VCM驱动名称
/* AFDRV_XXXX be the same as AF_DRVNAME in (*af).c */
#define AFDRV_DW9714AF "DW9714AF"
#define AFDRV_DW9714AF "DW9714AF"

2.4 添加VCM驱动文件

文件路径kernel-4.4/drivers/misc/mediatek/lens/main/common/
在这里插入图片描述

2.5 添加驱动列表DrvList[i]

文件路径kernel-4.4/drivers/misc/mediatek/lens/main/main_lens.c

  1. 列表中添加驱动接口名称,注意#define MAX_NUM_OF_LENS 32
static struct stAF_DrvList g_stAF_DrvList[MAX_NUM_OF_LENS] = {
	#ifdef CONFIG_MTK_LENS_DW9714AF_SUPPORT
	{1, AFDRV_DW9714AF, DW9714AF_SetI2Cclient, DW9714AF_Ioctl, DW9714AF_Release, NULL},
	#endif
	......
}

2.6 修改Kconfig & Makefile

文件路径kernel-4.4/drivers/misc/mediatek/lens/Kconfig

config MTK_LENS_DW9714AF_SUPPORT
	bool "DW9714AF Lens Driver"
	default y
	help
	  DW9714AF Lens Driver
	  This config is used to enable the corresponding
	  lens driver for the camera sensor module
	  Set as y if the driver is used in this project

文件路径kernel-4.4/drivers/misc/mediatek/lens/main/Makefile

MAIN_CFILES += main_lens.c

MAIN_CFILES  += common/dw9714af/DW9714AF.c
MAIN_CFILES  += common/dw9800af/DW9800AF.c
......
obj-y  += main_lens.o
obj-y  += common/dw9714af/
obj-y  += common/dw9800af/

2.7 驱动中AF上电

文件路径kernel-4.4/drivers/misc/mediatek/lens/main/main_lens.c

  1. AF上下点主要由接口AFRegulatorCtrl实现
void AFRegulatorCtrl(int Stage)
{
	LOG_INF("AFIOC_S_SETPOWERCTRL regulator_put %p\n", regVCAMAF);

	if (Stage == 0) {
		if (regVCAMAF == NULL) {
			struct device_node *node, *kd_node;

			/* check if customer camera node defined */
			node = of_find_compatible_node(NULL, NULL, "mediatek,CAMERA_MAIN_AF");

			if (node) {
				kd_node = lens_device->of_node;
				lens_device->of_node = node;

				if (strncmp(CONFIG_ARCH_MTK_PROJECT, "k71v1_64_bsp_fhdp", 17) == 0)
					regVCAMAF = regulator_get(lens_device, "vldo28");
				else
					regVCAMAF = regulator_get(lens_device, "vcamaf");

				LOG_INF("[Init] regulator_get %p\n", regVCAMAF);

				lens_device->of_node = kd_node;
			}
		}
	} else if (Stage == 1) {
		if (regVCAMAF != NULL && g_regVCAMAFEn == 0) {
			int Status = regulator_is_enabled(regVCAMAF);

			LOG_INF("regulator_is_enabled %d\n", Status);

			if (!Status) {
				Status = regulator_set_voltage(regVCAMAF, 2800000, 2800000);
	......
}
  1. 掉电接口AF_PowerDown
    文件路径kernel-4.4/drivers/misc/mediatek/lens/main/main_lens.c
    由于相机关闭后,系统会使整颗模组掉电,所以在有些地方已经弃用该接口。
void AF_PowerDown(void)
{
	if (g_pstAF_I2Cclient != NULL) {
		LOG_INF("CONFIG_MTK_PLATFORM : %s\n", CONFIG_MTK_PLATFORM);
		#ifdef CONFIG_MTK_LENS_DW9714AF_SUPPORT
		DW9714AF_SetI2Cclient(g_pstAF_I2Cclient, &g_AF_SpinLock, &g_s4AF_Opened);
		DW9714AF_PowerDown();
		#endif

或者采用另外一种形式

void AF_PowerDown(void)
{
	if (g_pstAF_I2Cclient != NULL) {
		LOG_INF("CONFIG_MTK_PLATFORM : %s\n", CONFIG_MTK_PLATFORM);
		#ifdef CONFIG_MTK_LENS_AW86014AF_SUPPORT
		DW9714AF_PowerDown(struct i2c_client *pstAF_I2Cclient, int *pAF_Opened)
		#endif

3. hal层适配

3.1 添加lens list

文件路径vendor/mediatek/proprietary/custom/mt6739/hal/lens/src/lenslist.cpp

#if defined(DW9714AF)
extern PFUNC_GETLENSDEFAULT pDW9714AF_getDefaultData;
#endif

#if defined(DW9714AF)
{S5K4H8_SENSOR_ID, DW9714AF_LENS_ID, "DW9714AF", pDW9714AF_getDefaultData},
#endif

3.2 添加lens ID

文件路径vendor/mediatek/proprietary/custom/mt6739/hal/inc/camera_custom_lens.h

#define MAX_NUM_OF_SUPPORT_LENS                 16
#define DUMMY_SENSOR_ID                      0xFFFF
/* LENS ID */
#define DW9714AF_LENS_ID                     0x9714

3.2 添加效果参数文件

文件路径vendor/mediatek/proprietary/custom/mt6739/hal/lens/

lens_para_DW9714AF.CPP
lens_para_DW9714AF_xx.CPP

3.3 HAL 层代码执行逻辑

在这里插入图片描述

3.3.1 获取lens的初始化列表流程

文件路径:\vendor\mediatek\proprietary\hardware\mtkcam\legacy\platform\mt6739\core\featureio\drv\lens\mcu_drv.cpp
(1)camera设备的宏定义

/* vendor\mediatek\proprietary\hardware\mtkcam\legacy\platform\mt6739\core\featureio\drv\inc\mcu_drv.h */
enum {
    MCU_DEV_NONE    = 0x00,        /*!<No camera device*/
    MCU_DEV_MAIN    = 0x01,        /*!<Main camera device or Rear camera device*/
    MCU_DEV_SUB     = 0x02,        /*!<Sub camera device or Front camera device*/
    MCU_DEV_MAIN_2  = 0x04,        /*!<Main2 camera device (used in 3D scenario) */
    MCU_DEV_MAIN_3D = 0x05,        /*!<3D camera device (Main+Main2)*/
    MCU_DEV_SUB_2   = 0x08,    /*!<Sub2 camera device or Front camera device*/
};

(2)搜索设备列表

int
MCUDrv::lensSearch( unsigned int a_u4CurrSensorDev, unsigned int a_u4CurrSensorId)
{
    INT32 i;
    MCU_DRV_DBG("[CurrSensorDev]0x%04x [CurrSensorId]0x%04x\n", a_u4CurrSensorDev, a_u4CurrSensorId);

    LensCustomInit(a_u4CurrSensorDev); /* ☆☆☆获取lens的列表,解析如下面《解析1》 */
    if (a_u4CurrSensorDev == MCU_DEV_MAIN )
    {
    	/* 将LensCustomInit中获取的数组复制到m_LensInitFunc_main */
        LensCustomGetInitFunc(&MCUDrv::m_LensInitFunc_main[0]);

        MCUDrv::m_u4CurrLensIdx_main = 0; /* 给索引编号一个初始值 */

        for (i=0; i<MAX_NUM_OF_SUPPORT_LENS; i++)
        {
            if (MCUDrv::m_LensInitFunc_main[i].LensId == DUMMY_LENS_ID)
            {
                MCUDrv::m_u4CurrLensIdx_main = i;
            }
        }

        // force assign LensIdx if SensorId != DUMMY_SENSOR_ID (to support backup lens/new lens driver)
        for (i=0; i<MAX_NUM_OF_SUPPORT_LENS; i++)
        {
            if ((MCUDrv::m_LensInitFunc_main[i].SensorId == a_u4CurrSensorId) && (a_u4CurrSensorId!=0xFFFF) && (a_u4CurrSensorId!=0x0))
            {
                //MCU_DRV_DBG("[%d] Lens Name %s", i, MCUDrv::m_LensInitFunc_main[i].LensDrvName);
                int fdMCU = open("/dev/MAINAF", O_RDWR);
                if (fdMCU >= 0)
                {
                    mcuMotorName motorName;
                    memcpy(motorName.uMotorName, MCUDrv::m_LensInitFunc_main[i].LensDrvName, 32);
                    int err = ioctl(fdMCU, mcuIOC_S_SETDRVNAME, &motorName);
                    close(fdMCU);
                    if (err > 0)
                    {
                         MCUDrv::m_u4CurrLensIdx_main = i;
                         break;
                    }
                }
            }
        }
        LensCustomSetIndex(MCUDrv::m_u4CurrLensIdx_main);
        MCU_DRV_DBG("[CurrLensIdx]%d", MCUDrv::m_u4CurrLensIdx_main);

    }
    else if( a_u4CurrSensorDev == MCU_DEV_MAIN_2) {
    		/* 与 a_u4CurrSensorDev == MCU_DEV_MAIN逻辑相同 */
    } else if( a_u4CurrSensorDev == MCU_DEV_SUB) {
			/* 与 a_u4CurrSensorDev == MCU_DEV_MAIN逻辑相同 */
	} else if( a_u4CurrSensorDev == MCU_DEV_SUB_2) {
			/* 与 a_u4CurrSensorDev == MCU_DEV_MAIN逻辑相同 */
	} else {
			 return MCU_INVALID_DRIVER;
	}

    return MCU_NO_ERROR;
}

《解析1》 关于LensCustomInit(a_u4CurrSensorDev); 的分析:

/* vendor\mediatek\proprietary\custom\mt6739\hal\camera_3a\camera_custom_msdk.cpp */
MUINT32 LensCustomInit(unsigned int a_u4CurrSensorDev)
{
    GetLensInitFuncList(&LensInitFunc[0], a_u4CurrSensorDev); /* 解析在下面,如《解析1.1》 */
	/* 打印出所有的sensor ID和lens ID */
    for( MUINT32 i=0; i<MAX_NUM_OF_SUPPORT_LENS; i++)
    {
        CAM_MSDK_LOG("[LensCustomInit] DEV %d: (%d) 0x%x, 0x%x", a_u4CurrSensorDev, i, LensInitFunc[i].SensorId, LensInitFunc[i].LensId);
    }
    return 0;
}

《解析1.1》 关于GetLensInitFuncList(&LensInitFunc[0], a_u4CurrSensorDev);的分析:
(1)结构体PMSDK_LENS_INIT_FUNCTION_STRUCT 定义:

/* vendor\mediatek\proprietary\custom\mt6739\hal\inc\camera_custom_lens.h */
typedef struct
{
    UINT32 SensorId;
    UINT32 LensId;
    UINT8  LensDrvName[32];
    UINT32 (*getLensDefault)(VOID *pDataBuf, UINT32 size);

} MSDK_LENS_INIT_FUNCTION_STRUCT, *PMSDK_LENS_INIT_FUNCTION_STRUCT;

(2)宏定义#define MAX_NUM_OF_SUPPORT_LENS 16

/* vendor\mediatek\proprietary\custom\mt6739\hal\lens\src\lenslist.cpp */
/* 结构体数组LensList_main[0]定义: */
MSDK_LENS_INIT_FUNCTION_STRUCT LensList_main[MAX_NUM_OF_SUPPORT_LENS] =
{
    {DUMMY_SENSOR_ID, DUMMY_LENS_ID, "Dummy", pDummy_getDefaultData},

#if defined(FM50AF)
    {DUMMY_SENSOR_ID, FM50AF_LENS_ID, "FM50AF", pFM50AF_getDefaultData},
	{S5K3L8_SENSOR_ID, FM50AF_LENS_ID, "FM50AF", pFM50AF_getDefaultData},
	{GC5025MIPI_SENSOR_ID, FM50AF_LENS_ID, "FM50AF", pFM50AF_getDefaultData},
#endif

#if defined(DW9714AF)
    {IMX135_SENSOR_ID, DW9714AF_LENS_ID, "DW9714AF", pDW9714AF_getDefaultData},
#endif
};
......
/* 复制lens列表的全部内容 */
UINT32 GetLensInitFuncList(PMSDK_LENS_INIT_FUNCTION_STRUCT pLensList, unsigned int a_u4CurrSensorDev)
{
    if(a_u4CurrSensorDev==2) //sub
        memcpy(pLensList, &LensList_sub[0], sizeof(MSDK_LENS_INIT_FUNCTION_STRUCT)* MAX_NUM_OF_SUPPORT_LENS);
    else if(a_u4CurrSensorDev==4) //main 2
        memcpy(pLensList, &LensList_main2[0], sizeof(MSDK_LENS_INIT_FUNCTION_STRUCT)* MAX_NUM_OF_SUPPORT_LENS);
    else  // main or others
        memcpy(pLensList, &LensList_main[0], sizeof(MSDK_LENS_INIT_FUNCTION_STRUCT)* MAX_NUM_OF_SUPPORT_LENS);

    return 0;
}
  • 4
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值