flashlight驱动和HAL分析
一.HAL层分析
Flash_cct.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\platform\mt6735\hal\aaa\flash_mgr)
1.初始化
int FlashlightDrv::init()
init_real
err = pKDrv->init(mSensorDev, mStrobeId);
//Strobe_global_driver.cpp (vendor\mediatek\proprietary\hardware\mtkcam\legacy\platform\mt6735\core\featureio\drv\strobe)
StrobeGlobalDriver::init(int sensorDev, int strobeId)
openkd_nolock(); //打开设备
mStrobeHandle = open(STROBE_DEV_NAME, O_RDWR); //打开/dev/kd_camera_flashlight
sendCommand_nolock(FLASHLIGHTIOC_X_SET_DRIVER, sensorDev, strobeId, 0);
return ioctl(mStrobeHandle, cmd, &stbArg); //发送 FLASHLIGHTIOC_X_SET_DRIVER
2.开关闪光灯
FlashlightDrv::setOnOff(int a_isOn)
err = getPreOnTimeMsDuty(m_duty, &minPreOnTime); //这里是空
err = pKDrv->sendCommand(FLASH_IOC_SET_ONOFF, mSensorDev, mStrobeId, 1); //打开闪关灯
Kd_flashlightlist.c (kernel-3.18\drivers\misc\mediatek\flashlight\src\mt6735)
1.初始化
#ifdef CONFIG_OF
static const struct of_device_id FLASHLIGHT_of_match[] = {
{.compatible = "mediatek,mt6755-flashlight"},
{},
};
#endif
static struct platform_driver flashlight_platform_driver = {
.probe = flashlight_probe,
.remove = flashlight_remove,
.shutdown = flashlight_shutdown,
.driver = {
.name = FLASHLIGHT_DEVNAME,
.owner = THIS_MODULE,
#ifdef CONFIG_OF
.of_match_table = FLASHLIGHT_of_match,
#endif
},
};
static struct platform_device flashlight_platform_device = {
.name = FLASHLIGHT_DEVNAME,
.id = 0,
.dev = {
}
};
flashlight_init
ret = platform_device_register(&flashlight_platform_device);
ret = platform_driver_register(&flashlight_platform_driver); //匹配进入flashlight_probe函数
2.flashlight_probe函数
static const struct file_operations flashlight_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = flashlight_ioctl,
.open = flashlight_open,
.release = flashlight_release,
#ifdef CONFIG_COMPAT
.compat_ioctl = my_ioctl_compat,
#endif
};
flashlight_probe
alloc_chrdev_region(&flashlight_devno, 0, 1, FLASHLIGHT_DEVNAME); //分配,名称kd_camera_flashlight
cdev_init(&flashlight_cdev, &flashlight_fops); //初始化
err = cdev_add(&flashlight_cdev, flashlight_devno, 1); //加入系统,/dev/kd_camera_flashlight
flashlight_class = class_create(THIS_MODULE, "flashlightdrv");
device_create(flashlight_class, NULL, flashlight_devno, NULL, FLASHLIGHT_DEVNAME); //sys/class/flashlightdrv/kd_camera_flashlight
init_waitqueue_head(&flashlight_private.read_wait); //初始化等待队列
/* GPIO pinctrl initial */
flashlight_gpio_init(dev); //初始化一些接口
flashlight_pinctrl = devm_pinctrl_get(&pdev->dev);
flashlight_hwen_high = pinctrl_lookup_state(flashlight_pinctrl, "hwen_high");
4.open函数
flashlight_open
globalInit();
for (i = 0; i < e_Max_Sensor_Dev_Num; i++) //e_Max_Sensor_Dev_Num = 3 ,分别是前摄,后摄,辅助后摄
for (j = 0; j < e_Max_Strobe_Num_Per_Dev; j++) { //e_Max_Strobe_Num_Per_Dev = 2 ,最多双闪
gLowBatDuty[i][j] = -1;
g_strobePartId[i][j] = 1;
for (k = 0; k < e_Max_Part_Num_Per_Dev; k++)
g_pFlashInitFunc[i][j][k] = 0;
}
5.ioctl函数
flashlight_ioctl
err = flashlight_ioctl_core(file, cmd, arg);
copyRet = copy_from_user(&kdArg, (void *)arg, sizeof(kdStrobeDrvArg)); //从用户空间拷贝参数
case FLASHLIGHTIOC_X_SET_DRIVER: //设置闪光灯驱动
i4RetValue = setFlashDrv(kdArg.sensorDev, kdArg.strobeId);
sensorDevIndex = getSensorDevIndex(sensorDev); //得到是前摄还是后摄
strobeIndex = getStrobeIndex(strobeId); //获得是单闪光还是双闪
partId = g_strobePartId[sensorDevIndex][strobeIndex]; //这里是1
partIndex = getPartIndex(partId); //数组中的位置
return partId - 1;
ppF = &g_pFlashInitFunc[sensorDevIndex][strobeIndex][partIndex]; //获得对应函数的指针结构体
constantFlashlightInit(ppF); //获取具体闪光灯的操作函数指针
*pfFunc = &constantFlashlightFunc;
(*ppF)->flashlight_open(0); //初始化闪光灯
具体闪光灯的flashlight_open
case FLASH_IOC_SET_ONOFF: //打开关闭闪关灯
pF = g_pFlashInitFunc[sensorDevIndex][strobeIndex][partIndex];
kicker_pbm_by_flash(kdArg.arg);
i4RetValue = pF->flashlight_ioctl(cmd, kdArg.arg);
具体驱动的flashlight_ioctl
三.具体闪光驱动分析
Leds_strobe.c (kernel-3.18\drivers\misc\mediatek\flashlight\src\mt6735\constant_flashlight)
1.打开接口
constant_flashlight_open
FL_init();
flashlight_gpio_set(FLASH_GPIO_EN,FLASH_GPIO_LOW); //使能脚为低
flashlight_gpio_set(FLASH_GPIO_MODEM,FLASH_GPIO_LOW); //模式脚为低
INIT_WORK(&workTimeOut, work_timeOutFunc); //初始化工作队列,单独分析1
timerInit();
g_timeOutTimeMs=1000; //1s
hrtimer_init( &g_timeOutTimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL );
g_timeOutTimer.function=ledTimeOutCallback; //设置1S的定时器,单独分析2,ledTimeOutCallback
单独分析1
work_timeOutFunc
FL_disable(); //关闭闪光灯
flashlight_gpio_set(FLASH_GPIO_EN,FLASH_GPIO_LOW);
flashlight_gpio_set(FLASH_GPIO_MODEM,FLASH_GPIO_LOW);
单独分析2
ledTimeOutCallback
schedule_work(&workTimeOut); //启动工作队列
2.ioctrl接口
constant_flashlight_ioctl
case FLASH_IOC_SET_TIME_OUT_TIME_MS: //设置开启的时间
g_timeOutTimeMs=arg;
case FLASH_IOC_SET_DUTY : //设置闪灯的段数(0--32)
g_duty=arg;
FL_dim_duty(arg);
case FLASH_IOC_SET_STEP: //设置步进
g_step=arg;
FL_step(arg);
case FLASH_IOC_SET_ONOFF : //开关闪光灯
if(arg==1) // //如果是打开,设置超时时间
ktime = ktime_set( 0, g_timeOutTimeMs*1000000 );
hrtimer_start( &g_timeOutTimer, ktime, HRTIMER_MODE_REL ); //定时器到时间会关闭闪光
FL_enable(); //打开
g_strobe_On=1;
else //如果是关闭
FL_disable(); //关闭
hrtimer_cancel( &g_timeOutTimer ); //取消定时器
g_strobe_On=0;