20. FlashLight調試日誌

零、閃光燈配置步驟(以真閃IC:DIO5151爲例):
1. 查看硬件原理圖,得知閃關燈IC接在cpu的哪兩個GPIO上:
	main_flashlight:(後閃)
		enable	: GPIO43
		mode	: GPIO80(H-flashlight模式  L-torch手電筒模式)
	sub_flashlight:(前攝)
		enable	: GPIO42

2. dws配置pin腳:
			EintMode|Def.Mode	M0|M1|M2|M3|M4|M5|M6|M7|InPull En|InPull SelHigh|Def.Dir|In|Out|OutHigh|VarName1
	GPIO42	NC		// 有點奇怪NC也能控制?
	GPIO43			0:GPIO43	1  0  0  1  1  0  1  0  1		  0				 OUT	 0	1	0		GPIO_CAMERA_FLASH_EN_PIN
	GPIO80			0:GPIO80	1  0  0  0  0  0  0  0  1		  0				 OUT	 0	1	0		GPIO_CAMERA_FLASH_MOOD_PIN

3. dts配置gpio控制接口:
	3.1 mt6580.dtsi:
		+	strobe: strobe {
		+		compatible = "mediatek,mt6580-strobe";
		+	};
	
	3.2 k80hd_bsp_fwv_512m.dts
	
		+	/* STROBE GPIO standardization */
		+	&pio {
		+		strobe_intpin_default: strobedefaultcfg {
		+		};
		+		main_strobe_oh: mainstrobe@1 {
		+			pins_cmd_dat {
		+				pins = <PINMUX_GPIO43__FUNC_GPIO43>;
		+				slew-rate = <1>;
		+				output-high;
		+			};
		+		};
		+
		+		main_strobe_ol: mainstrobe@2 {
		+			pins_cmd_dat {
		+				pins = <PINMUX_GPIO43__FUNC_GPIO43>;
		+				slew-rate = <1>;
		+				output-low;
		+			};
		+		};
		+		main_strobe_mode_oh: mainstrobemode@1 {
		+			pins_cmd_dat {
		+				pins = <PINMUX_GPIO80__FUNC_GPIO80>;
		+				slew-rate = <1>;
		+				output-high;
		+			};
		+		};
		+		main_strobe_mode_ol: mainstrobemode@2 {
		+			pins_cmd_dat {
		+				pins = <PINMUX_GPIO80__FUNC_GPIO80>;
		+				slew-rate = <1>;
		+				output-low;
		+			};
		+		};
		+		sub_strobe_oh: substrobe@1 {
		+			pins_cmd_dat {
		+				pins = <PINMUX_GPIO42__FUNC_GPIO42>;
		+				slew-rate = <1>;
		+				output-high;
		+			};
		+		};
		+		sub_strobe_ol: substrobe@2 {
		+			pins_cmd_dat {
		+				pins = <PINMUX_GPIO42__FUNC_GPIO42>;
		+				slew-rate = <1>;
		+				output-low;
		+			};
		+		};
		+	};
		+
		+	&strobe {
		+		pinctrl-names = "default", "main_strobe_oh", "main_strobe_ol", "main_strobe_mode_oh", "main_strobe_mode_ol", "sub_strobe_oh", "sub_strobe_ol";
		+		pinctrl-0 = <&strobe_intpin_default>;
		+		pinctrl-1 = <&main_strobe_oh>;
		+		pinctrl-2 = <&main_strobe_ol>;
		+		pinctrl-4 = <&main_strobe_mode_ol>;
		+		pinctrl-5 = <&sub_strobe_oh>;
		+		pinctrl-6 = <&sub_strobe_ol>;
		+		status = "okay";
		+	};
		+	/* STROBE GPIO end */


	3.3 alps/kernel-3.18/drivers/misc/mediatek/flashlight/inc/kd_flashlight.h
		+	int strobe_gpio_init(struct platform_device *pdev);
		+	#ifdef CONFIG_KST_SUB_STROBE_SUPPORT
		+		int sub_strobe_gpio_init(struct platform_device *pdev);
		+	#endif
		
	3.4 alps/kernel-3.18/drivers/misc/mediatek/flashlight/src/mt6580/kd_flashlightlist.c
		+	#ifdef CONFIG_OF
		+	#include <linux/of.h>
		+	#include <linux/of_address.h>
		+	#include <linux/of_irq.h>
		+	#endif
	
		+	#ifdef CONFIG_OF
		+	static const struct of_device_id strobe_of_ids[] = {
		+		{.compatible = "mediatek,mt6580-strobe",},
		+		{}
		+	};
		+	#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 = strobe_of_ids,
		+	#endif
					   },
			};
		+	#ifndef CONFIG_OF
			static struct platform_device flashlight_platform_device = {
				.name = FLASHLIGHT_DEVNAME,
				.id = 0,
				.dev = {
					}
			};
		+	#endif
			static int __init flashlight_init(void)
			{
				int ret = 0;

				logI("[flashlight_probe] start ~");
		+	#ifndef CONFIG_OF
				ret = platform_device_register(&flashlight_platform_device);
				if (ret) {
					logI("[flashlight_probe] platform_device_register fail ~");
					return ret;
				}
		+	#endif
		
			static int flashlight_probe(struct platform_device *dev)
			{
				int ret = 0, err = 0;

				logI("[flashlight_probe] start ~");
		+	#ifdef CONFIG_OF	
		+		strobe_gpio_init(dev);
		+	#endif
		
		-	#ifdef WIN32
		+	#if 0 //#ifdef WIN32

	3.5 alps/kernel-3.18/drivers/misc/mediatek/flashlight/src/mt6580/constant_flashlight/leds_strobe.c
		+	struct pinctrl *strobectrl = NULL;
		+	struct pinctrl_state *main_strobe_oh = NULL;
		+	struct pinctrl_state *main_strobe_ol = NULL;
		+	#ifdef CONFIG_KST_REAL_FLASH_MODE
		+	struct pinctrl_state *main_strobe_mode_oh = NULL;
		+	struct pinctrl_state *main_strobe_mode_ol = NULL;
		+	#endif
		+	static DEFINE_MUTEX(main_strobe_gpio_mutex);
		+	int strobe_gpio_init(struct platform_device *pdev)
		+	{
		+		int ret = 0;
		+
		+		strobectrl = devm_pinctrl_get(&pdev->dev);
		+		if (IS_ERR(strobectrl)) {
		+			dev_err(&pdev->dev, "Cannot find strobe pinctrl!");
		+			ret = PTR_ERR(strobectrl);
		+		}
		+
		+		main_strobe_oh = pinctrl_lookup_state(strobectrl, "main_strobe_oh");
		+		if (IS_ERR(main_strobe_oh)) {
		+			ret = PTR_ERR(main_strobe_oh);
		+			pr_debug("%s : pinctrl err, main_strobe_oh\n", __func__);
		+		}
		+		
		+		main_strobe_ol = pinctrl_lookup_state(strobectrl, "main_strobe_ol");
		+		if (IS_ERR(main_strobe_ol)) {
		+			ret = PTR_ERR(main_strobe_ol);
		+			pr_debug("%s : pinctrl err, main_strobe_ol\n", __func__);
		+		}
		+	#ifdef CONFIG_KST_REAL_FLASH_MODE
		+		main_strobe_mode_oh = pinctrl_lookup_state(strobectrl, "main_strobe_mode_oh");
		+		if (IS_ERR(main_strobe_mode_oh)) {
		+			ret = PTR_ERR(main_strobe_mode_oh);
		+			pr_debug("%s : pinctrl err, main_strobe_mode_oh\n", __func__);
		+		}
		+		main_strobe_mode_ol = pinctrl_lookup_state(strobectrl, "main_strobe_mode_ol");
		+		if (IS_ERR(main_strobe_mode_ol)) {
		+			ret = PTR_ERR(main_strobe_mode_ol);
		+			pr_debug("%s : pinctrl err, main_strobe_mode_ol\n", __func__);
		+		}
		+	#endif
		+
		+		return ret;
		+	}
		+
		+	void strobe_gpio_set(int level)
		+	{
		+		mutex_lock(&main_strobe_gpio_mutex);
		+		if (level == 0)
		+			pinctrl_select_state(strobectrl, main_strobe_ol);
		+		else
		+			pinctrl_select_state(strobectrl, main_strobe_oh);
		+		mutex_unlock(&main_strobe_gpio_mutex);
		+	}
		+
		+	#ifdef CONFIG_KST_REAL_FLASH_MODE
		+	void strobe_mode_gpio_set(int level)
		+	{
		+		mutex_lock(&main_strobe_gpio_mutex);
		+		if (level == 0)
		+			pinctrl_select_state(strobectrl, main_strobe_mode_ol);
		+		else
		+			pinctrl_select_state(strobectrl, main_strobe_mode_oh);
		+		mutex_unlock(&main_strobe_gpio_mutex);
		+	}
		+	#endif

		+	#ifdef CONFIG_KST_REAL_FLASH_MODE
		+		#define LEDS_TORCH_MODE 		0
		+		#define LEDS_FLASH_MODE 		1
		+		#define LEDS_CUSTOM_MODE_THRES 	0
		+		static int flash_mode_pin = 0;
		+		#ifdef EN_PWM_CTRL
		+			static int g_timePWMOutTimeMs=0;
		+			static struct hrtimer g_timePWMOutTimer;
		+			void timerPWMInit(void);
		+			static bool g_enble_led=false;
		+			ktime_t ktime;
		+			enum hrtimer_restart ledPWMTimeOutCallback(struct hrtimer *timer)
		+			{    
		+				if(g_enble_led == true) {
		+					strobe_gpio_set(0);
		+					#ifdef CONFIG_KST_FLASHLIGHT_CURRENT_DOWN
		+					g_timePWMOutTimeMs=9;
		+					#else
		+					g_timePWMOutTimeMs=2;
		+					#endif
		+					ktime = ktime_set( 0, g_timePWMOutTimeMs*1000000 ); //1s
		+					g_enble_led = false;
		+				}
		+				else if(g_enble_led == false) {
		+					strobe_gpio_set(1);
		+					#ifdef CONFIG_KST_FLASHLIGHT_CURRENT_DOWN
		+					g_timePWMOutTimeMs=1;
		+					#else
		+					g_timePWMOutTimeMs=8;
		+					#endif
		+					ktime = ktime_set( 0, g_timePWMOutTimeMs*1000000 ); //1s
		+					g_enble_led = true;
		+				}
		+				hrtimer_forward(&g_timePWMOutTimer, g_timePWMOutTimer.base->get_time(), ktime);
		+				return HRTIMER_RESTART;
		+			}
		+			void timerPWMInit(void)
		+			{
		+				g_timePWMOutTimeMs=5;
		+				hrtimer_init( &g_timePWMOutTimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL );
		+				g_timePWMOutTimer.function=ledPWMTimeOutCallback;
		+			}
		+		#endif
		+	#endif
		
			int FL_Enable(void)
			{
		+	#if 0
				...
		+	#else
		+		strobe_gpio_set(1);
		+		
		+		#ifdef EN_PWM_CTRL   
		+			ktime = ktime_set( 0, g_timePWMOutTimeMs*1000000 ); //1s
		+			hrtimer_start( &g_timePWMOutTimer, ktime, HRTIMER_MODE_REL );
		+			g_enble_led=true;
		+		#endif
		+		
		+	#endif
				return 0;
			}
		
			int FL_Disable(void)
			{
		+	#if 0
				...
		+	#else
		+		#ifdef EN_PWM_CTRL
		+			hrtimer_cancel( &g_timePWMOutTimer );
		+			g_enble_led=false;	
		+		#endif
		+		strobe_gpio_set(0);
		+	#endif
				return 0;
			}
			
			int FL_dim_duty(kal_uint32 duty)
			{
				PK_DBG(" FL_dim_duty line=%d\n", __LINE__);
				g_duty = duty;
				
		+	#ifdef CONFIG_KST_REAL_FLASH_MODE
		+		PK_DBG("FL_dim_duty %d, thres %d", duty, LEDS_CUSTOM_MODE_THRES);
		+		
		+		flash_mode_pin = 0;
		+		if(duty < LEDS_CUSTOM_MODE_THRES)
		+			strobe_mode_gpio_set(LEDS_TORCH_MODE);
		+		else {
		+			flash_mode_pin = 1;
		+			strobe_mode_gpio_set(LEDS_FLASH_MODE);
		+		}
		+
		+		if((g_timeOutTimeMs == 0) && (duty > LEDS_CUSTOM_MODE_THRES))
		+		{
		+			PK_DBG("FL_dim_duty %d > thres %d, FLASH mode but timeout %d", duty, LEDS_CUSTOM_MODE_THRES, g_timeOutTimeMs);
		+			strobe_mode_gpio_set(LEDS_TORCH_MODE);
		+			flash_mode_pin = 0;
		+		}
		+	#endif
				
				return 0;
			}

			int FL_Init(void)
			{
				...
		+	#ifdef EN_PWM_CTRL
		+		timerPWMInit();
		+	#endif

	3.6 alps/kernel-3.18/drivers/misc/mediatek/flashlight/src/mt6580/sub_strobe.c
		+	#ifdef CONFIG_KST_SUB_STROBE_SUPPORT	// 此宏包括全部爲新加
		+		static DEFINE_SPINLOCK(g_strobeSMPLock);
				static DEFINE_MUTEX(sub_strobe_gpio_mutex);
				struct pinctrl *substrobectrl = NULL;
				struct pinctrl_state *sub_strobe_oh = NULL;
				struct pinctrl_state *sub_strobe_ol = NULL;

				static u32 strobe_Res = 0;
				static u32 strobe_Timeus = 0;

				static int g_duty=-1;
				static int g_timeOutTimeMs=0;

				static DEFINE_MUTEX(g_strobeSem);

				static struct work_struct workTimeOut;

				int sub_strobe_gpio_init(struct platform_device *pdev)
				{
					int ret = 0;

					substrobectrl = devm_pinctrl_get(&pdev->dev);
					if (IS_ERR(substrobectrl)) {
						dev_err(&pdev->dev, "Cannot find sub strobe pinctrl!");
						ret = PTR_ERR(substrobectrl);
					}

					sub_strobe_oh = pinctrl_lookup_state(substrobectrl, "sub_strobe_oh");
					if (IS_ERR(sub_strobe_oh)) {
						ret = PTR_ERR(sub_strobe_oh);
						pr_debug("%s : pinctrl err, sub_strobe_oh\n", __func__);
					}
					
					sub_strobe_ol = pinctrl_lookup_state(substrobectrl, "sub_strobe_ol");
					if (IS_ERR(sub_strobe_ol)) {
						ret = PTR_ERR(sub_strobe_ol);
						pr_debug("%s : pinctrl err, sub_strobe_ol\n", __func__);
					}

					return ret;
				}

				void sub_strobe_gpio_set(int level)
				{
					mutex_lock(&sub_strobe_gpio_mutex);
					if (level == 0)
						pinctrl_select_state(substrobectrl, sub_strobe_ol);
					else
						pinctrl_select_state(substrobectrl, sub_strobe_oh);
					mutex_unlock(&sub_strobe_gpio_mutex);
				}

				int SUB_FL_Enable(void)
				{
					sub_strobe_gpio_set(1);
					
					PK_DBG(" SUB_FL_Enable line=%d\n",__LINE__);
				  return 0;
				}

				int SUB_FL_Disable(void)
				{
					sub_strobe_gpio_set(0);

					PK_DBG(" SUB_FL_Disable line=%d\n",__LINE__);
				  return 0;
				}

				int SUB_FL_dim_duty(kal_uint32 duty)
				{
					PK_DBG(" SUB_FL_dim_duty line=%d\n",__LINE__);
					g_duty = duty;
					return 0;
				}

				int SUB_FL_Init(void)
				{
				  PK_DBG(" SUB_FL_Init line=%d\n",__LINE__);
				  return 0;
				}

				int SUB_FL_Uninit(void)
				{
					SUB_FL_Disable();
					return 0;
				}

				static void Sub_work_timeOutFunc(struct work_struct *data)
				{
					SUB_FL_Disable();
					PK_DBG("ledTimeOut_callback\n");
				}

				enum hrtimer_restart Sub_ledTimeOutCallback(struct hrtimer *timer)
				{
					schedule_work(&workTimeOut);
					return HRTIMER_NORESTART;
				}

				static struct hrtimer g_timeOutTimer;
				void Sub_timerInit(void)
				{
				  INIT_WORK(&workTimeOut, Sub_work_timeOutFunc);
					g_timeOutTimeMs=1000; //1s
					hrtimer_init( &g_timeOutTimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL );
					g_timeOutTimer.function=Sub_ledTimeOutCallback;

				}

				static int Sub_constant_flashlight_flashlight_ioctl(unsigned int cmd, unsigned long arg)
				{
					int i4RetValue = 0;
					int ior_shift;
					int iow_shift;
					int iowr_shift;
					ior_shift = cmd - (_IOR(FLASHLIGHT_MAGIC,0, int));
					iow_shift = cmd - (_IOW(FLASHLIGHT_MAGIC,0, int));
					iowr_shift = cmd - (_IOWR(FLASHLIGHT_MAGIC,0, int));
					PK_DBG("LM3642 Sub_constant_flashlight_flashlight_ioctl() line=%d ior_shift=%d, iow_shift=%d iowr_shift=%d arg=%d\n",__LINE__, ior_shift, iow_shift, iowr_shift,(int)arg);
					switch(cmd)
					{

						case FLASH_IOC_SET_TIME_OUT_TIME_MS:
							PK_DBG("FLASH_IOC_SET_TIME_OUT_TIME_MS: %d\n",(int)arg);
							g_timeOutTimeMs=arg;
						break;

						case FLASH_IOC_SET_DUTY :
							PK_DBG("FLASHLIGHT_DUTY: %d\n",(int)arg);
							SUB_FL_dim_duty(arg);
							break;

						case FLASH_IOC_SET_STEP:
							PK_DBG("FLASH_IOC_SET_STEP: %d\n",(int)arg);

							break;

						case FLASH_IOC_SET_ONOFF :
							PK_DBG("FLASHLIGHT_ONOFF: %d\n",(int)arg);
							if(arg==1)
							{
								int s;
								int ms;
								if(g_timeOutTimeMs>1000)
								{
									s = g_timeOutTimeMs/1000;
									ms = g_timeOutTimeMs - s*1000;
								}
								else
								{
									s = 0;
									ms = g_timeOutTimeMs;
								}

								if(g_timeOutTimeMs!=0)
								{
									ktime_t ktime;
									ktime = ktime_set( s, ms*1000000 );
									hrtimer_start( &g_timeOutTimer, ktime, HRTIMER_MODE_REL );
								}
								SUB_FL_Enable();
							}
							else
							{
								SUB_FL_Disable();
								hrtimer_cancel( &g_timeOutTimer );
							}
							break;
						default :
							PK_DBG(" No such command \n");
							i4RetValue = -EPERM;
							break;
					}
					return i4RetValue;
				}

				static int Sub_constant_flashlight_open(void *pArg)
				{
					int i4RetValue = 0;
					PK_DBG("Sub_constant_flashlight_open line=%d\n", __LINE__);

					if (0 == strobe_Res)
					{
						SUB_FL_Init();
						Sub_timerInit();
					}
					PK_DBG("Sub_constant_flashlight_open line=%d\n", __LINE__);
					spin_lock_irq(&g_strobeSMPLock);

					if(strobe_Res)
					{
						PK_ERR(" busy!\n");
						i4RetValue = -EBUSY;
					}
					else
					{
						strobe_Res += 1;
					}

					spin_unlock_irq(&g_strobeSMPLock);
					PK_DBG("Sub_constant_flashlight_open line=%d\n", __LINE__);

					return i4RetValue;

				}

				static int Sub_constant_flashlight_release(void *pArg)
				{
					PK_DBG(" Sub_constant_flashlight_release\n");

					if (strobe_Res)
					{
						spin_lock_irq(&g_strobeSMPLock);

						strobe_Res = 0;
						strobe_Timeus = 0;

						spin_unlock_irq(&g_strobeSMPLock);

						SUB_FL_Uninit();
					}

					PK_DBG(" Done\n");

					return 0;
				}

				FLASHLIGHT_FUNCTION_STRUCT	Sub_constantFlashlightFunc=
				{
					Sub_constant_flashlight_open,
					Sub_constant_flashlight_release,
					Sub_constant_flashlight_flashlight_ioctl
				};

				MUINT32 subStrobeInit(PFLASHLIGHT_FUNCTION_STRUCT *pfFunc)
				{
					if (pfFunc != NULL)
					{
						*pfFunc = &Sub_constantFlashlightFunc;
					}
					return 0;
				}
		+	// 以上全部爲新加
		+	#else

				...
				MUINT32 subStrobeInit(PFLASHLIGHT_FUNCTION_STRUCT *pfFunc)
				{
					if (pfFunc != NULL)
						*pfFunc = &subStrobeFunc;
					return 0;
				}
		+	#endif

	============sub strobe需要配置修改hal層,以下爲hal層=======================
	3.7 alps/vendor/mediatek/proprietary/custom/mt6580/hal/flashlight/flash_tuning_custom2.h
		+	#ifdef KST_SUB_FLASH_SUPPORT
		+		#define SUB_FLASH_SUPPORT 1
		+	#else
				#define SUB_FLASH_SUPPORT 0
		+	#endif

	3.8 alps/vendor/mediatek/proprietary/custom/mt6580/hal/imgsensor_metadata/common/config_static_metadata_common.h
			STATIC_METADATA_BEGIN(DEVICE, CAMERA, COMMON)
				switch  (rInfo.getDeviceId()){
				case 0:
				case 1:
		+	#if defined(KST_SUB_FLASH_SUPPORT)		
		+			CONFIG_ENTRY_VALUE(MTK_FLASH_INFO_AVAILABLE_TRUE, MUINT8)
		+	#else
					CONFIG_ENTRY_VALUE(MTK_FLASH_INFO_AVAILABLE_FALSE, MUINT8)
		+	#endif						
					CONFIG_METADATA_END()
					break;
				default:
	

	3.9 配置: alps\kernel-3.18\arch\arm64\configs\xxx_debug_defconfig
		CONFIG_MTK_FLASHLIGHT=y
		CONFIG_KST_SUB_STROBE_SUPPORT=y		// 前閃配置
		CONFIG_KST_REAL_FLASH_MODE=y		// 後真閃配置 - 有一個模式引腳
		CONFIG_CUSTOM_KERNEL_FLASHLIGHT="constant_flashlight"

	3.10 配置: alps\device\xxx\xxx\ProjectConfig.mk
		+	AUTO_ADD_GLOBAL_DEFINE_BY_VALUE = KST_MISC_CUSTOM // 添加:KST_MISC_CUSTOM
		
		+	KST_MISC_CUSTOM	= KST_SUB_FLASH_SUPPORT		// 前閃配置
			
			CUSTOM_KERNEL_FLASHLIGHT=constant_flashlight
			CUSTOM_HAL_FLASHLIGHT=constant_flashlight


零一、mt6739平臺(kernel-4.4 ):
	1. dws配置pin腳:
			EintMode|Def.Mode	M0|M1|M2|M3|M4|M5|M6|M7|InPull En|InPull SelHigh|Def.Dir|In|Out|OutHigh|VarName1
	GPIO42	NC		// 有點奇怪NC也能控制?
	GPIO10			0:GPIO10	1  0  0  1  1  0  1  0  1		  0				 OUT	 0	1	0		GPIO_FLASH_LED_EN
	GPIO13	NC		// 有點奇怪NC也能控制?
	
	2. dts配置gpio控制接口:
		2.1 mt6580.dtsi:
		-	flashlights_rt4505: flashlights_rt4505 {
		-		compatible = "mediatek,flashlights_rt4505";
		-	};
			
		+	strobe: strobe {
		+		compatible = "mediatek,flashlights_dummy_gpio";
				decouple = <0>;
				channel@1 {
						type = <0>;
						ct = <0>;
						part = <0>;
				};
				channel@2 {
						type = <1>;
						ct = <0>;
						part = <0>;
		+		};
		+	};
		
		2.2 k39tv1_bsp_1g.dts
			+	/* FLASHLIGHT GPIO standardization */
			+	&strobe {
					pinctrl-names = "xxx_high", "xxx_low", "sub_xxx_high", "sub_xxx_low";
					pinctrl-0 = <&xxx_high>;
					pinctrl-1 = <&xxx_low>;
					pinctrl-2 = <&sub_xxx_high>;
					pinctrl-3 = <&sub_xxx_low>;
					status = "okay";
				};

				&pio {
					xxx_high: xxx_high {
						pins_cmd_dat {
							pins = <PINMUX_GPIO10__FUNC_GPIO10>;
							slew-rate = <1>;
							output-high;
						};
					};

					xxx_low: xxx_low {
						pins_cmd_dat {
							pins = <PINMUX_GPIO10__FUNC_GPIO10>;
							slew-rate = <1>;
							output-low;
						};
					};
					
					sub_xxx_high: sub_xxx_high {
						pins_cmd_dat {
							pins = <PINMUX_GPIO13__FUNC_GPIO13>;
							slew-rate = <1>;
							output-high;
						};
					};

					sub_xxx_low: sub_xxx_low {
						pins_cmd_dat {
							pins = <PINMUX_GPIO13__FUNC_GPIO13>;
							slew-rate = <1>;
							output-low;
						};
					};

			+	};
			+	/* FLASHLIGHT end */
		
		3. kernel-4.4/drivers/misc/mediatek/flashlight/flashlights-dummy-gpio.c
				#define DUMMY_PINCTRL_PIN_XXX 0
				#define DUMMY_PINCTRL_PINSTATE_LOW 0
				#define DUMMY_PINCTRL_PINSTATE_HIGH 1
				#define DUMMY_PINCTRL_STATE_XXX_HIGH "xxx_high"
				#define DUMMY_PINCTRL_STATE_XXX_LOW  "xxx_low"
				static struct pinctrl *dummy_pinctrl;
				static struct pinctrl_state *dummy_xxx_high;
				static struct pinctrl_state *dummy_xxx_low;

			+	#ifdef CONFIG_KST_SUB_STROBE_SUPPORT
			+	#define SUB_DUMMY_PINCTRL_PIN_XXX 1
			+	#define SUB_DUMMY_PINCTRL_PINSTATE_LOW 0
			+	#define SUB_DUMMY_PINCTRL_PINSTATE_HIGH 1
			+	#define SUB_DUMMY_PINCTRL_STATE_XXX_HIGH "sub_xxx_high"
			+	#define SUB_DUMMY_PINCTRL_STATE_XXX_LOW  "sub_xxx_low"
			+	static struct pinctrl_state *sub_dummy_xxx_high;
			+	static struct pinctrl_state *sub_dummy_xxx_low;
			+	#endif
			
				static int dummy_pinctrl_init(struct platform_device *pdev)
				{
					int ret = 0;

					/* get pinctrl */
					dummy_pinctrl = devm_pinctrl_get(&pdev->dev);
					if (IS_ERR(dummy_pinctrl)) {
						pr_err("Failed to get flashlight pinctrl.\n");
						ret = PTR_ERR(dummy_pinctrl);
					}

					/* TODO: Flashlight XXX pin initialization */
					dummy_xxx_high = pinctrl_lookup_state(dummy_pinctrl, DUMMY_PINCTRL_STATE_XXX_HIGH);
					if (IS_ERR(dummy_xxx_high)) {
						pr_err("Failed to init (%s)\n", DUMMY_PINCTRL_STATE_XXX_HIGH);
						ret = PTR_ERR(dummy_xxx_high);
					}
					dummy_xxx_low = pinctrl_lookup_state(dummy_pinctrl, DUMMY_PINCTRL_STATE_XXX_LOW);
					if (IS_ERR(dummy_xxx_low)) {
						pr_err("Failed to init (%s)\n", DUMMY_PINCTRL_STATE_XXX_LOW);
						ret = PTR_ERR(dummy_xxx_low);
					}
			+		#ifdef CONFIG_KST_SUB_STROBE_SUPPORT
			+		/* TODO: sub Flashlight XXX pin initialization */
			+		sub_dummy_xxx_high = pinctrl_lookup_state(dummy_pinctrl, SUB_DUMMY_PINCTRL_STATE_XXX_HIGH);
			+		if (IS_ERR(sub_dummy_xxx_high)) {
			+			pr_err("Failed to init (%s)\n", SUB_DUMMY_PINCTRL_STATE_XXX_HIGH);
			+			ret = PTR_ERR(sub_dummy_xxx_high);
			+		}
			+		sub_dummy_xxx_low = pinctrl_lookup_state(dummy_pinctrl, SUB_DUMMY_PINCTRL_STATE_XXX_LOW);
			+		if (IS_ERR(sub_dummy_xxx_low)) {
			+			pr_err("Failed to init (%s)\n", SUB_DUMMY_PINCTRL_STATE_XXX_LOW);
			+			ret = PTR_ERR(sub_dummy_xxx_low);
			+		}
			+		#endif

					return ret;
				}

				static int dummy_pinctrl_set(int pin, int state)
				{
					...
					switch (pin) {
					case DUMMY_PINCTRL_PIN_XXX:
						if (state == DUMMY_PINCTRL_PINSTATE_LOW && !IS_ERR(dummy_xxx_low))
							pinctrl_select_state(dummy_pinctrl, dummy_xxx_low);
						else if (state == DUMMY_PINCTRL_PINSTATE_HIGH && !IS_ERR(dummy_xxx_high))
							pinctrl_select_state(dummy_pinctrl, dummy_xxx_high);
						else
							pr_err("set err, pin(%d) state(%d)\n", pin, state);
						break;
			+		#ifdef CONFIG_KST_SUB_STROBE_SUPPORT
			+		case SUB_DUMMY_PINCTRL_PIN_XXX:
			+			if (state == SUB_DUMMY_PINCTRL_PINSTATE_LOW && !IS_ERR(sub_dummy_xxx_low))
			+				pinctrl_select_state(dummy_pinctrl, sub_dummy_xxx_low);
			+			else if (state == SUB_DUMMY_PINCTRL_PINSTATE_HIGH && !IS_ERR(sub_dummy_xxx_high))
			+				pinctrl_select_state(dummy_pinctrl, sub_dummy_xxx_high);
			+			else
			+				pr_err("set err, pin(%d) state(%d)\n", pin, state);
			+			break;
			+		#endif	
					...
				}
				
				static int dummy_enable(void)
				{
					int pin = 0, state = 1; //0;
					return dummy_pinctrl_set(pin, state);
				}

				/* flashlight disable function */
				static int dummy_disable(void)
				{
					int pin = 0, state = 0;
					return dummy_pinctrl_set(pin, state);
				}

			+	#ifdef CONFIG_KST_SUB_STROBE_SUPPORT
			+	static int sub_dummy_enable(void)
			+	{
			+		int pin = 1, state = 1;
			+		return dummy_pinctrl_set(pin, state);
			+	}

			+	static int sub_dummy_disable(void)
			+	{
			+		int pin = 1, state = 0;
			+		return dummy_pinctrl_set(pin, state);
			+	}
			+	#endif

				static int dummy_ioctl(unsigned int cmd, unsigned long arg)
				{
					struct flashlight_dev_arg *fl_arg;
					int channel;
					ktime_t ktime;

					fl_arg = (struct flashlight_dev_arg *)arg;
					channel = fl_arg->channel;

					switch (cmd) {
						...
					case FLASH_IOC_SET_ONOFF:
						pr_debug("FLASH_IOC_SET_ONOFF(%d): %d\n",
								channel, (int)fl_arg->arg);
						if (fl_arg->arg == 1) {
							if (dummy_timeout_ms) {
								ktime = ktime_set(dummy_timeout_ms / 1000,
										(dummy_timeout_ms % 1000) * 1000000);
								hrtimer_start(&dummy_timer, ktime, HRTIMER_MODE_REL);
							}
				+			#ifdef CONFIG_KST_SUB_STROBE_SUPPORT
				+			if(channel == 0)
				+				dummy_enable();
				+			else if(channel == 1)
				+				sub_dummy_enable();
				+			#else
							dummy_enable();
				+			#endif
						} else {
				+			#ifdef CONFIG_KST_SUB_STROBE_SUPPORT
				+			if(channel == 0)
				+				dummy_disable();
				+			else if(channel == 1)
				+				sub_dummy_disable();
				+			#else
							dummy_disable();
				+			#endif
							hrtimer_cancel(&dummy_timer);
						}
						break;
						...
				}

		4.vendor/mediatek/proprietary/custom/mt6739/hal/flashlight/flash_tuning_custom2.h
			-	#if MTKCAM_SUB_FLASHLIGHT_SUPPORT
			+	#ifdef KST_SUB_FLASH_SUPPORT		// 改成用我們的宏控制,這個宏配置在ProjectConfig.mk
				#define SUB_FLASH_SUPPORT 1
				#else
				#define SUB_FLASH_SUPPORT 0
				#endif

		5. vendor/mediatek/proprietary/hardware/mtkcam/legacy/platform/mt6739/core/featureio/drv/strobe/flashlight_drv.cpp
				int FlashlightDrv::setOnOff(int a_isOn)
				{
					...
					if(m_duty > mOnDuty)
						mOnDuty = m_duty;
					int minPreOnTime;
			-		err = getPreOnTimeMsDuty(m_duty, &minPreOnTime);
			+		getPreOnTimeMsDuty(m_duty, &minPreOnTime);

			
如若閃光燈還是無功能: 檢查驅動代碼,最好是先找一個ok的工程,從那邊移植過來


一、FlashLight(strobe)概要
	1.FlashLiht分爲真閃和假閃,
		真閃: 需要一個IC - 查bom可知v618上貼的是DIO5151(10pin)
		假閃: 由一個三極管實現電流放大
		兼容: 通常硬件上對真閃假閃做了兼容,即真假閃的電路都實現,二者使能腳爲同一引腳,
			  貼ic爲真閃,不貼即爲假閃(軟件不需要作區分)
		
	2.真閃可以選擇模式(閃光燈/手電筒),通過對ic的GPIO_FLASH_STROBE引腳操作(HIGH - 閃光燈  LOW - 手電筒)
		閃關燈: 電流可爲500mA
		手電筒: 電流應該限制爲100mA
		怎切換:	HIGH - 閃光燈  LOW - 手電筒
		
	3.驅動中實現了一個定時器來控制閃光燈的時長,閃光燈亮20s就自動滅,
		實測: camera拍照閃光燈的關閉由上層ioctl關閉(log顯示)
		實測: 手電筒不會20s自動滅 - ???

二、調試
	1.真假閃均可以通過PWM的佔空比控制閃光的亮度 - 已驗證ok
		alps\kernel-3.18\drivers\misc\mediatek\flashlight\src\mt6735\constant_flashlight\leds_strobe.c
			enum hrtimer_restart ledPWMTimeOutCallback(struct hrtimer *timer)
			{    
				if(g_enble_led == true) {
					strobe_gpio_set(0);
					g_timePWMOutTimeMs=2;		// 低電平(滅燈)佔空比2/10
					ktime = ktime_set( 0, g_timePWMOutTimeMs*800000 ); //1s
					g_enble_led = false;
				}
				else if(g_enble_led == false) {
					strobe_gpio_set(1);		
					g_timePWMOutTimeMs=8;		// 高電平(亮燈)佔空比8/10
					ktime = ktime_set( 0, g_timePWMOutTimeMs*800000 ); //1s
					g_enble_led = true;
				}
				hrtimer_forward(&g_timePWMOutTimer, g_timePWMOutTimer.base->get_time(), ktime);
				return HRTIMER_RESTART;
			}

	2. 方便測量電流 - 控制循環閃爍
		alps\kernel-3.18\drivers\misc\mediatek\flashlight\src\mt6735\constant_flashlight\leds_strobe.c
	
	case FLASH_IOC_SET_ONOFF:
		PK_DBG("FLASHLIGHT_ONOFF: %d\n", (int)arg);
		printk("201707 [%s] [%d] FLASH_IOC_SET_ONOFF: %d \n", __func__, __LINE__, (int)arg);
		if (arg == 1) {

			int s;
			int ms;
			/*
			//==============================

			int i  = 0;
			for(i = 0 ; i < 3; i++){
				printk("201707 [%s] [%d] set(LEDS_TORCH_MODE) \n", __func__, __LINE__);
				strobe_mode_gpio_set(LEDS_TORCH_MODE);		// 手電筒模式
				mdelay(5);
				strobe_gpio_set(1);			// 輸出1 - 亮
				mdelay(10000);
				strobe_gpio_set(0);			// 輸出0 - 滅
				mdelay(1000);

				printk("201707 [%s] [%d] set(LEDS_FLASH_MODE) \n", __func__, __LINE__);
				strobe_mode_gpio_set(LEDS_FLASH_MODE);		// 閃光燈模式
				mdelay(5);
				strobe_gpio_set(1);			// 輸出1 - 亮
				mdelay(4000);
				strobe_gpio_set(0);			// 輸出0 - 滅
				mdelay(1000);
			}
			
			//==============================
			*/
	
案例一:	真閃IC:DIO5151(10pin) - 400ma的閃光燈電流只持續400ms,過後自動變小
			更換pin對pin的另一個閃光燈IC(SGM3141B), 電流正常
		
	
案例二: 39平臺實現前後閃光燈

1. mt6739上mtk默認的閃光燈是使用rt4505這個ic來控制的,而當前我們的硬件電路的前後閃光燈的是假閃
	修改k39tv1_bsp_1g_defconfig
	-	#CONFIG_MTK_FLASHLIGHT_RT4505=y
	+	CONFIG_MTK_FLASHLIGHT_DUMMY_GPIO=y
	
2. 在mt6739.dts中這樣添加閃光燈的配置
	+	strobe: strobe {
	+		compatible = "mediatek,flashlights_dummy_gpio";
	+	};
	
	使之和flashlights-dummy-gpio.c相匹配
		#define DUMMY_DTNAME "mediatek,flashlights_dummy_gpio"
		static const struct of_device_id dummy_gpio_of_match[] = {
			{.compatible = DUMMY_DTNAME},
			{},
		};

3. flashlights-dummy-gpio.c雖然加載起來了,但在攝像頭界面打開閃光燈,或者點擊手電筒圖標時,
	並不會執行FLASH_IOC_SET_ONOFF這個case來操作GPIO控制語句
		static int dummy_ioctl(unsigned int cmd, unsigned long arg)
		{
		……
			case FLASH_IOC_SET_ONOFF:
				pr_debug("FLASH_IOC_SET_ONOFF(%d): %d\n",	// log未打印
		……
		}

4. 查看閃光燈從hal層往kernel端的調用流程
	使用git grep -n "FLASH_IOC_SET_ONOFF" alps/vendor/mediatek/proprietary/命令,查找FLASH_IOC_SET_ONOFF是從哪個hal的cpp代碼下發到驅動的,發現在如下代碼內有調用
	
	alps/vendor/mediatek/proprietary/hardware/mtkcam/legacy/platform/mt6739/core/featureio/drv/strobe/flashlight_drv.cpp
		int FlashlightDrv::setOnOff(int a_isOn)
		{
			int hasHw;
			hasHw = hasFlashHw();
			if(hasHw != 1)
				return 0;

			logI("setOnOff() isOn = %d\n",a_isOn);
			if(checkValid()!=0)
				return StrobeDrv::STROBE_UNKNOWN_ERROR;

			int err = 0;

			StrobeGlobalDriver* pKDrv;
			pKDrv = StrobeGlobalDriver::getInstance();

			if (a_isOn == 1) {
				if(m_isOn == 0) {
					mTurnOnTime = getMs();
					mOnDuty = m_duty;
				}

				if(m_duty > mOnDuty)
					mOnDuty = m_duty;

				int minPreOnTime;
				err = getPreOnTimeMsDuty(m_duty, &minPreOnTime);
		//在此處添加調試信息,發現err是小於0的,追蹤getPreOnTimeMsDuty的函數定義。
				if (minPreOnTime > 100)
					minPreOnTime = 100;
				else if (minPreOnTime < 0)
					minPreOnTime = -1;

				if (err < 0) {
					logI("no preon");
				} else {
					if(minPreOnTime == -1) {
						logI("no preon(preontime=-1)");
					} else {
						logI("preon support %d",m_preOnTime);
						if (m_preOnTime == -1) {
							setPreOn();
							sleepMs(minPreOnTime);
						} else {
							int curTime;
							int sleepTimeMs;
							curTime = getMs();
							sleepTimeMs = (minPreOnTime-(curTime-m_preOnTime));
							logI("preon sleep %d ms", sleepTimeMs);

							if(sleepTimeMs > minPreOnTime)
								sleepTimeMs = minPreOnTime;

							if(sleepTimeMs > 0) {
								sleepMs( sleepTimeMs);
							}
						}
					}
				}
				err = pKDrv->sendCommand(FLASH_IOC_SET_ONOFF, mTypeId, mCtId, 1);
		//在此處添加調試信息,發現並未打印信息出來,在前面的語句添加調試信息。
			} else if(a_isOn == 0) {
				if (m_isOn == 1) {
					mTurnOffTime= getMs();
					if((mTurnOffTime-mTurnOnTime > mTimeOutTime) && (mTimeOutTime != 0))
						logE("TimeOut");
				}
				m_preOnTime=-1;

				err = pKDrv->sendCommand(FLASH_IOC_SET_ONOFF, mTypeId, mCtId, 0);
		//在此處添加調試信息,發現並未打印信息出來,在前面的語句添加調試信息。
			} else {
				err = STROBE_ERR_PARA_INVALID;
			}

			if (err < 0) {
				logE("setOnOff() err=%d\n", err);
			}

			if(!err)
				m_isOn = a_isOn;

			return err;
		}
	
5. FLASH_IOC_GET_PRE_ON_TIME_MS_DUTY 和 FLASH_IOC_GET_PRE_ON_TIME_MS 未在flashlights-dummy-gpio.c定義,
	hal層通過ioctl未獲取到返回值,導致flashlight_drv.cpp
	未執行到
	err = pKDrv->sendCommand(FLASH_IOC_SET_ONOFF, mTypeId, mCtId, 1);
	err = pKDrv->sendCommand(FLASH_IOC_SET_ONOFF, mTypeId, mCtId, 0);
	
	alps/vendor/mediatek/proprietary/hardware/mtkcam/legacy/platform/mt6739/core/featureio/drv/strobe/flashlight_drv.cpp
		int FlashlightDrv::getPreOnTimeMsDuty(int duty, int* ms)
		{
			logI("getPreOnTimeMsDuty()");

			StrobeGlobalDriver* pKDrv;
			pKDrv = StrobeGlobalDriver::getInstance();

			int err;
			err = pKDrv->sendCommand(FLASH_IOC_GET_PRE_ON_TIME_MS_DUTY, mTypeId, mCtId, (long)duty);
			err = pKDrv->sendCommandRet(FLASH_IOC_GET_PRE_ON_TIME_MS, mTypeId, mCtId, ms);
			logI("getPreOnTimeMs=%d err=%d", *ms, err);

			return err;
		}

		git grep -n "sendCommand" alps/vendor/mediatek/proprietary/hardware/mtkcam/legacy/platform/mt6739/

		alps/vendor/mediatek/proprietary/hardware/mtkcam/legacy/platform/mt6739/core/featureio/drv/strobe/strobe_global_driver.cpp

		int StrobeGlobalDriver::sendCommandRet(int cmd, int typeId, int ctId, int *arg)
		{
			Mutex::Autolock lock(mLock);
			return sendCommandRet_nolock(cmd, typeId, ctId, arg);
		}

		int StrobeGlobalDriver::sendCommandRet_nolock(int cmd, int typeId, int ctId, int *arg)
		{

			if (mStrobeHandle < 0) {
				logE("sendCommand() mStrobeHandle <= 0 ~");
				return StrobeDrv::STROBE_UNKNOWN_ERROR;
			}

			/* setup arguments */
			/* TODO: redefine ioctl argument */
			struct flashlight_user_arg stbArg;
			stbArg.type_id = typeId;
			stbArg.ct_id = ctId;
			stbArg.arg = 0;

			/* send ioctl */
			int ret;
			ret = ioctl(mStrobeHandle, cmd, &stbArg);
			*arg = stbArg.arg;

			return ret;
		}

		int StrobeGlobalDriver::sendCommand(int cmd, int typeId, int ctId, int arg)
		{
			Mutex::Autolock lock(mLock);
			return sendCommand_nolock(cmd, typeId, ctId, arg);
		}

		int StrobeGlobalDriver::sendCommand_nolock(int cmd, int typeId, int ctId, int arg)
		{

			if (mStrobeHandle < 0) {
				logE("sendCommand() mStrobeHandle <= 0 ~");
				return StrobeDrv::STROBE_UNKNOWN_ERROR;
			}

			/* setup arguments */
			struct flashlight_user_arg stbArg;
			stbArg.type_id = typeId;
			stbArg.ct_id = ctId;
			stbArg.arg = arg;

			/* send ioctl */
			return ioctl(mStrobeHandle, cmd, &stbArg);
		}
	
6. 不做getPreOnTimeMsDuty返回值的判斷就能進行對FLASH_IOC_SET_ONOFF的ioctl調用
	alps/vendor/mediatek/proprietary/hardware/mtkcam/legacy/platform/mt6739/core/featureio/drv/strobe/flashlight_drv.cpp
		int FlashlightDrv::setOnOff(int a_isOn)
		{
		……
			int err = 0;

			StrobeGlobalDriver* pKDrv;
			pKDrv = StrobeGlobalDriver::getInstance();

			if (a_isOn == 1) {
				if(m_isOn == 0) {
					mTurnOnTime = getMs();
					mOnDuty = m_duty;
				}

				if(m_duty > mOnDuty)
					mOnDuty = m_duty;

				int minPreOnTime;
				/*err = */getPreOnTimeMsDuty(m_duty, &minPreOnTime);
		//在此處不把getPreOnTimeMsDuty的返回值賦給err即可。
				if (minPreOnTime > 100)
					minPreOnTime = 100;
				else if (minPreOnTime < 0)
					minPreOnTime = -1;

				if (err < 0) {
					logI("no preon");
				} else {

		……
		}
	
7. 代碼修改
	7.1 mt6739.dts
		strobe: strobe {
			compatible = "mediatek,flashlights_dummy_gpio";
			decouple = <0>;
			channel@1 {
					type = <0>;
					ct = <0>;
					part = <0>;
			};
			channel@2 {
					type = <1>;
					ct = <0>;
					part = <0>;
			};
		};
		
	7.2 k39tv1_bsp_1g.dts
		&strobe {
			pinctrl-names = "xxx_high", "xxx_low", "sub_xxx_high", "sub_xxx_low";
			pinctrl-0 = <&xxx_high>;
			pinctrl-1 = <&xxx_low>;
			pinctrl-2 = <&sub_xxx_high>;
			pinctrl-3 = <&sub_xxx_low>;
			status = "okay";
		};

		&pio {
			xxx_high: xxx_high {
				pins_cmd_dat {
					pins = <PINMUX_GPIO10__FUNC_GPIO10>;
					slew-rate = <1>;
					output-high;
				};
			};

			xxx_low: xxx_low {
				pins_cmd_dat {
					pins = <PINMUX_GPIO10__FUNC_GPIO10>;
					slew-rate = <1>;
					output-low;
				};
			};
			
			sub_xxx_high: sub_xxx_high {
				pins_cmd_dat {
					pins = <PINMUX_GPIO13__FUNC_GPIO13>;
					slew-rate = <1>;
					output-high;
				};
			};

			sub_xxx_low: sub_xxx_low {
				pins_cmd_dat {
					pins = <PINMUX_GPIO13__FUNC_GPIO13>;
					slew-rate = <1>;
					output-low;
				};
			};

		};
		
	7.3 flashlights-dummy-gpio.c
		static int dummy_ioctl(unsigned int cmd, unsigned long arg)
		{
		……
			case FLASH_IOC_SET_ONOFF:
				pr_debug("FLASH_IOC_SET_ONOFF(%d): %d\n",
						channel, (int)fl_arg->arg);
				if (fl_arg->arg == 1) {
					if (dummy_timeout_ms) {
						ktime = ktime_set(dummy_timeout_ms / 1000,
								(dummy_timeout_ms % 1000) * 1000000);
						hrtimer_start(&dummy_timer, ktime, HRTIMER_MODE_REL);
					}
					#ifdef CONFIG_KST_SUB_STROBE_SUPPORT
					if(channel == 0)
						dummy_enable();	//支持前後假閃的後閃使用pinctrl的方式使能對應GPIO
					else if(channel == 1)
						sub_dummy_enable();	//支持前後假閃的後閃使用pinctrl的方式使能對應GPIO
					#else
					dummy_enable();	//只支持後假閃的後閃使用pinctrl的方式使能對應GPIO
					#endif
				} else {
					#ifdef CONFIG_KST_SUB_STROBE_SUPPORT
					if(channel == 0)
						dummy_disable();	//支持前後假閃的後閃使用pinctrl的方式關閉對應GPIO
					else if(channel == 1)
						sub_dummy_disable();	//支持前後假閃的後閃使用pinctrl的方式關閉對應GPIO
					#else
					dummy_disable();	//只支持後假閃的後閃使用pinctrl的方式關閉對應GPIO
					#endif
					hrtimer_cancel(&dummy_timer);
				}
				break;
		……
		}
		
	xxx.mk中配置是否支持前假閃的宏
	#主板型號及內核宏定義配置 
	KST_KERNEL_BOARD_CUSTOM00 = KST_BOARD_V630K
	KST_KERNEL_BOARD_CUSTOM01 = KST_SUB_STROBE_SUPPORT	// 作用在kernel config
	KST_KERNEL_BOARD_CUSTOM02 = 
	KST_KERNEL_BOARD_CUSTOM03 = 
	KST_KERNEL_BOARD_CUSTOM04 = 
	KST_KERNEL_BOARD_CUSTOM05 = 
	KST_KERNEL_BOARD_CUSTOM06 = 
	KST_KERNEL_BOARD_CUSTOM07 = 
	KST_KERNEL_BOARD_CUSTOM08 = 
	KST_KERNEL_BOARD_CUSTOM09 = 

	#Misc 配置
	KST_MISC_CUSTOM= KST_SUB_FLASH_SUPPORT // 作用在ProjectConfig.mk





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章