stmvl6180_old.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978
  1. /*
  2. * stmvl6180.c - Linux kernel modules for STM VL6180 FlightSense Time-of-Flight sensor
  3. *
  4. * Copyright (C) 2014 STMicroelectronics Imaging Division.
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19. */
  20. #include <linux/i2c.h>
  21. #include <linux/delay.h>
  22. #include <linux/platform_device.h>
  23. #include <linux/cdev.h>
  24. #include <linux/uaccess.h>
  25. #include <linux/fs.h>
  26. #include <asm/atomic.h>
  27. #ifdef CONFIG_COMPAT
  28. #include <linux/compat.h>
  29. #endif
  30. #include "vl6180x_api.h"
  31. #include "vl6180x_def.h"
  32. #include "vl6180x_platform.h"
  33. #include "stmvl6180.h"
  34. #if defined(CONFIG_MTK_LEGACY)
  35. #define I2C_CONFIG_SETTING 1
  36. #elif defined(CONFIG_OF)
  37. #define I2C_CONFIG_SETTING 2 /* device tree */
  38. #else
  39. #define I2C_CONFIG_SETTING 1
  40. #endif
  41. #ifndef ABS
  42. #define ABS(x) (((x) > 0) ? (x) : (-(x)))
  43. #endif
  44. #define VL6180_OFFSET_CALIB 0x02
  45. #define VL6180_XTALK_CALIB 0x03
  46. #define VL6180_MAGIC 'A'
  47. #define VL6180_IOCTL_INIT _IO(VL6180_MAGIC, 0x01)
  48. #define VL6180_IOCTL_GETOFFCALB _IOR(VL6180_MAGIC, VL6180_OFFSET_CALIB, int)
  49. #define VL6180_IOCTL_GETXTALKCALB _IOR(VL6180_MAGIC, VL6180_XTALK_CALIB, int)
  50. #define VL6180_IOCTL_SETOFFCALB _IOW(VL6180_MAGIC, 0x04, int)
  51. #define VL6180_IOCTL_SETXTALKCALB _IOW(VL6180_MAGIC, 0x05, int)
  52. #define VL6180_IOCTL_GETDATA _IOR(VL6180_MAGIC, 0x0a, int)
  53. #if I2C_CONFIG_SETTING == 1
  54. #define LENS_I2C_BUSNUM 0
  55. #define I2C_REGISTER_ID 0x52
  56. #endif
  57. #define LASER_DRVNAME "laser"
  58. #define I2C_SLAVE_ADDRESS 0x52
  59. #define PLATFORM_DRIVER_NAME "laser_actuator_stmvl6180"
  60. #define LASER_DRIVER_CLASS_NAME "actuatordrv_stmvl6180"
  61. #if I2C_CONFIG_SETTING == 1
  62. static struct i2c_board_info kd_laser_dev __initdata = {
  63. I2C_BOARD_INFO(LASER_DRVNAME, I2C_REGISTER_ID)
  64. };
  65. #endif
  66. #define AF_DEBUG
  67. #ifdef AF_DEBUG
  68. #define LOG_INF(format, args...) pr_info(LASER_DRVNAME " [%s] " format, __func__, ##args)
  69. #else
  70. #define LOG_INF(format, args...)
  71. #endif
  72. static spinlock_t g_Laser_SpinLock;
  73. static struct i2c_client * g_pstLaser_I2Cclient = NULL;
  74. static dev_t g_Laser_devno;
  75. static struct cdev * g_pLaser_CharDrv = NULL;
  76. static struct class *actuator_class = NULL;
  77. static int g_s4Laser_Opened = 0;
  78. static int g_Laser_OffsetCalib = 0xFFFFFFFF;
  79. static int g_Laser_XTalkCalib = 0xFFFFFFFF;
  80. /////////////////////////////////////////
  81. stmvl6180x_dev vl6180x_dev = NULL;
  82. int s4VL6180_ReadRegByte(u16 addr, u8 *data)
  83. {
  84. u8 pu_send_cmd[2] = {(u8)(addr >> 8) , (u8)(addr & 0xFF) };
  85. g_pstLaser_I2Cclient->addr = (I2C_SLAVE_ADDRESS) >> 1;
  86. if (i2c_master_send(g_pstLaser_I2Cclient, pu_send_cmd, 2) < 0)
  87. {
  88. //LOG_INF("I2C read 1 failed!! \n");
  89. return -1;
  90. }
  91. if (i2c_master_recv(g_pstLaser_I2Cclient, data , 1) < 0)
  92. {
  93. //LOG_INF("I2C read 2 failed!! \n");
  94. return -1;
  95. }
  96. //LOG_INF("I2C read addr 0x%x data 0x%x\n", addr,*data );
  97. return 0;
  98. }
  99. int s4VL6180_WriteRegByte(u16 addr, u8 data)
  100. {
  101. u8 puSendCmd[3] = { (u8)((addr >> 8)&0xFF),
  102. (u8)( addr &0xFF),
  103. (u8)( data &0xFF)};
  104. g_pstLaser_I2Cclient->addr = (I2C_SLAVE_ADDRESS) >> 1;
  105. if (i2c_master_send(g_pstLaser_I2Cclient, puSendCmd , 3) < 0)
  106. {
  107. //LOG_INF("I2C write failed!! \n");
  108. return -1;
  109. }
  110. //LOG_INF("I2C write addr 0x%x data 0x%x\n", addr, data );
  111. return 0;
  112. }
  113. int s4VL6180_ReadRegWord(u16 addr, u16 *data)
  114. {
  115. u8 pu_send_cmd[2] = {(u8)(addr >> 8) , (u8)(addr & 0xFF) };
  116. u16 vData;
  117. g_pstLaser_I2Cclient->addr = (I2C_SLAVE_ADDRESS) >> 1;
  118. if (i2c_master_send(g_pstLaser_I2Cclient, pu_send_cmd, 2) < 0)
  119. {
  120. //LOG_INF("I2C read 1 failed!! \n");
  121. return -1;
  122. }
  123. if (i2c_master_recv(g_pstLaser_I2Cclient, data , 2) < 0)
  124. {
  125. //LOG_INF("I2C read 2 failed!! \n");
  126. return -1;
  127. }
  128. vData = *data;
  129. *data = ( (vData & 0xFF) << 8 ) + ( (vData >> 8) & 0xFF ) ;
  130. //LOG_INF("I2C read addr 0x%x data 0x%x\n", addr,*data );
  131. return 0;
  132. }
  133. int s4VL6180_WriteRegWord(u16 addr, u16 data)
  134. {
  135. char puSendCmd[4] = { (u8)((addr >> 8)&0xFF),
  136. (u8)( addr &0xFF),
  137. (u8)((data >> 8)&0xFF),
  138. (u8)( data &0xFF)};
  139. g_pstLaser_I2Cclient->addr = (I2C_SLAVE_ADDRESS) >> 1;
  140. if (i2c_master_send(g_pstLaser_I2Cclient, puSendCmd , 4) < 0)
  141. {
  142. //LOG_INF("I2C write failed!! \n");
  143. return -1;
  144. }
  145. //LOG_INF("I2C write addr 0x%x data 0x%x\n", addr, data );
  146. return 0;
  147. }
  148. int s4VL6180_ReadRegDWord(u16 addr, u32 *data)
  149. {
  150. u8 pu_send_cmd[2] = {(u8)(addr >> 8) , (u8)(addr & 0xFF) };
  151. u32 vData;
  152. g_pstLaser_I2Cclient->addr = (I2C_SLAVE_ADDRESS) >> 1;
  153. if (i2c_master_send(g_pstLaser_I2Cclient, pu_send_cmd, 2) < 0)
  154. {
  155. //LOG_INF("I2C read 1 failed!! \n");
  156. return -1;
  157. }
  158. if (i2c_master_recv(g_pstLaser_I2Cclient, data , 4) < 0)
  159. {
  160. //LOG_INF("I2C read 2 failed!! \n");
  161. return -1;
  162. }
  163. vData = *data;
  164. *data= ( (vData &0xFF) <<24) +
  165. (((vData>> 8)&0xFF) <<16) +
  166. (((vData>>16)&0xFF) << 8) +
  167. (((vData>>24)&0xFF) );
  168. //LOG_INF("I2C read addr 0x%x data 0x%x\n", addr,*data );
  169. return 0;
  170. }
  171. int s4VL6180_WriteRegDWord(u16 addr, u32 data)
  172. {
  173. char puSendCmd[6] = { (u8)((addr >> 8)&0xFF),
  174. (u8)( addr &0xFF),
  175. (u8)((data >> 24)&0xFF),
  176. (u8)((data >> 16)&0xFF),
  177. (u8)((data >> 8)&0xFF),
  178. (u8)( data &0xFF)};
  179. g_pstLaser_I2Cclient->addr = (I2C_SLAVE_ADDRESS) >> 1;
  180. if (i2c_master_send(g_pstLaser_I2Cclient, puSendCmd , 6) < 0)
  181. {
  182. //LOG_INF("I2C write failed!! \n");
  183. return -1;
  184. }
  185. //LOG_INF("I2C write addr 0x%x data 0x%x\n", addr, data );
  186. return 0;
  187. }
  188. // TODO: Wrong Case - If the range value has kept the same , we can't use it. In Calibration mode, the range value maybe keep the same.
  189. int VL6180x_RangeCheckMeasurement(int RangeValue)
  190. {
  191. static int RangeArray[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  192. static int ArrayCnt = 0;
  193. int Idx = 0;
  194. int CheckRes = 0;
  195. for( Idx = 0; Idx < 16; Idx++ )
  196. {
  197. if( RangeArray[Idx] == RangeValue )
  198. {
  199. CheckRes++;
  200. }
  201. }
  202. RangeArray[ArrayCnt] = RangeValue;
  203. ArrayCnt++;
  204. ArrayCnt &= 0xF;
  205. if( CheckRes == 16 )
  206. {
  207. RangeValue = 765;
  208. LOG_INF("Laser Check Data Failed \n");
  209. }
  210. return RangeValue;
  211. }
  212. extern void VL6180x_SetOffset(VL6180xDev_t dev, int8_t offset);
  213. void VL6180x_SystemInit(int Scaling, int EnWAF, int CalibMode)
  214. {
  215. //VL6180x_WaitDeviceBooted(vl6180x_dev);
  216. VL6180x_InitData(vl6180x_dev);
  217. VL6180x_Prepare(vl6180x_dev);
  218. VL6180x_UpscaleSetScaling(vl6180x_dev, Scaling);
  219. VL6180x_FilterSetState(vl6180x_dev, EnWAF); // turn on wrap around filter
  220. VL6180x_RangeConfigInterrupt(vl6180x_dev, CONFIG_GPIO_INTERRUPT_NEW_SAMPLE_READY);
  221. VL6180x_RangeClearInterrupt(vl6180x_dev);
  222. //Calibration Data
  223. if( CalibMode == VL6180_OFFSET_CALIB )
  224. {
  225. VL6180x_WrWord(vl6180x_dev, SYSRANGE_PART_TO_PART_RANGE_OFFSET, 0);
  226. VL6180x_WrWord(vl6180x_dev, SYSRANGE_CROSSTALK_COMPENSATION_RATE, 0);
  227. g_Laser_OffsetCalib = 0xFFFFFFFF;
  228. }
  229. else if( CalibMode == VL6180_XTALK_CALIB )
  230. {
  231. VL6180x_WrWord(vl6180x_dev, SYSRANGE_CROSSTALK_COMPENSATION_RATE, 0);
  232. g_Laser_XTalkCalib = 0xFFFFFFFF;
  233. }
  234. if( g_Laser_OffsetCalib != 0xFFFFFFFF )
  235. {
  236. VL6180x_SetOffset(vl6180x_dev, g_Laser_OffsetCalib);
  237. LOG_INF("VL6180 Set Offset Calibration: Set the offset value as %d\n", g_Laser_OffsetCalib);
  238. }
  239. if( g_Laser_XTalkCalib != 0xFFFFFFFF )
  240. {
  241. VL6180x_SetXTalkCompensationRate(vl6180x_dev, g_Laser_XTalkCalib);
  242. LOG_INF("VL6180 Set XTalk Calibration: Set the XTalk value as %d\n", g_Laser_XTalkCalib);
  243. }
  244. VL6180x_RangeSetSystemMode(vl6180x_dev, MODE_START_STOP|MODE_SINGLESHOT);
  245. }
  246. int VL6180x_GetRangeValue(VL6180x_RangeData_t *Range/*int *RangeValue, int *SingleRate*/)
  247. {
  248. int Result = 1;
  249. int ParamVal = 765;
  250. u8 u8status=0;
  251. #if 0
  252. VL6180x_RangeGetInterruptStatus(vl6180x_dev, &u8status);
  253. if (u8status == RES_INT_STAT_GPIO_NEW_SAMPLE_READY)
  254. {
  255. VL6180x_RangeGetMeasurement(vl6180x_dev, Range);
  256. VL6180x_RangeSetSystemMode(vl6180x_dev, MODE_START_STOP | MODE_SINGLESHOT);
  257. ParamVal = Range->range_mm;
  258. /*if( ParamVal < 400 )
  259. {
  260. ParamVal = VL6180x_RangeCheckMeasurement(ParamVal);
  261. }*/
  262. //LOG_INF("Laser Range : %d / %d \n", Range->range_mm, Range->DMax);
  263. }
  264. else
  265. {
  266. ParamVal = 765;
  267. LOG_INF("Laser Get Data Failed \n");
  268. }
  269. #else
  270. int Count = 0;
  271. while(1)
  272. {
  273. VL6180x_RangeGetInterruptStatus(vl6180x_dev, &u8status);
  274. if ( u8status == RES_INT_STAT_GPIO_NEW_SAMPLE_READY )
  275. {
  276. VL6180x_RangeGetMeasurement(vl6180x_dev, Range);
  277. ParamVal = Range->range_mm;
  278. VL6180x_RangeClearInterrupt(vl6180x_dev);
  279. break;
  280. }
  281. if( Count > 10 )
  282. {
  283. ParamVal = 765;
  284. LOG_INF("Laser Get Data Failed \n");
  285. VL6180x_RangeClearInterrupt(vl6180x_dev);
  286. break;
  287. }
  288. msleep(3);
  289. Count++;
  290. }
  291. VL6180x_RangeSetSystemMode(vl6180x_dev, MODE_START_STOP | MODE_SINGLESHOT);
  292. #endif
  293. if( ParamVal == 765 )
  294. {
  295. Result = 0;
  296. }
  297. return Result;
  298. }
  299. #define N_MEASURE_AVG 20
  300. #define OFFSET_CALIB_TARGET_DISTANCE 100 // 100mm
  301. #define XTALK_CALIB_TARGET_DISTANCE 400 // 400mm
  302. ////////////////////////////////////////////////////////////////
  303. static long Laser_Ioctl(
  304. struct file * a_pstFile,
  305. unsigned int a_u4Command,
  306. unsigned long a_u4Param)
  307. {
  308. long i4RetValue = 0;
  309. switch(a_u4Command)
  310. {
  311. case VL6180_IOCTL_INIT: /* init. */
  312. if( g_s4Laser_Opened == 1 )
  313. {
  314. u8 Device_Model_ID = 0;
  315. s4VL6180_ReadRegByte(VL6180_MODEL_ID_REG, &Device_Model_ID);
  316. LOG_INF("STM VL6180 ID : %x\n", Device_Model_ID);
  317. if( Device_Model_ID != 0xb4 )
  318. {
  319. LOG_INF("Not found STM VL6180\n");
  320. return -1;
  321. }
  322. #if 0
  323. //VL6180x_WaitDeviceBooted(vl6180x_dev);
  324. VL6180x_InitData(vl6180x_dev);
  325. VL6180x_Prepare(vl6180x_dev);
  326. VL6180x_UpscaleSetScaling(vl6180x_dev, 3);
  327. VL6180x_FilterSetState(vl6180x_dev, 0/*1*/); // turn on wrap around filter
  328. VL6180x_RangeConfigInterrupt(vl6180x_dev, CONFIG_GPIO_INTERRUPT_NEW_SAMPLE_READY);
  329. VL6180x_RangeClearInterrupt(vl6180x_dev);
  330. VL6180x_RangeSetSystemMode(vl6180x_dev, MODE_START_STOP|MODE_SINGLESHOT);
  331. #endif
  332. /*spin_lock(&g_Laser_SpinLock);
  333. g_s4Laser_Opened = 2;
  334. spin_unlock(&g_Laser_SpinLock);*/
  335. }
  336. break;
  337. case VL6180_IOCTL_GETDATA:
  338. if( g_s4Laser_Opened == 1 )
  339. {
  340. #if 1
  341. VL6180x_SystemInit(3, 1, 0);
  342. #else
  343. //VL6180x_WaitDeviceBooted(vl6180x_dev);
  344. VL6180x_InitData(vl6180x_dev);
  345. VL6180x_Prepare(vl6180x_dev);
  346. VL6180x_UpscaleSetScaling(vl6180x_dev, 3);
  347. VL6180x_FilterSetState(vl6180x_dev, 1); // turn on wrap around filter
  348. VL6180x_RangeConfigInterrupt(vl6180x_dev, CONFIG_GPIO_INTERRUPT_NEW_SAMPLE_READY);
  349. VL6180x_RangeClearInterrupt(vl6180x_dev);
  350. VL6180x_RangeSetSystemMode(vl6180x_dev, MODE_START_STOP|MODE_SINGLESHOT);
  351. #endif
  352. spin_lock(&g_Laser_SpinLock);
  353. g_s4Laser_Opened = 2;
  354. spin_unlock(&g_Laser_SpinLock);
  355. }
  356. else if( g_s4Laser_Opened == 2 )
  357. {
  358. void __user *p_u4Param = (void __user *)a_u4Param;
  359. int ParamVal;
  360. VL6180x_RangeData_t Range;
  361. #if 1
  362. VL6180x_GetRangeValue(&Range);
  363. ParamVal = Range.range_mm;
  364. //LOG_INF("Laser Range : %d / %d \n", Range.range_mm, Range.DMax);
  365. #else
  366. u8 u8status=0, u8ResultPos=0;
  367. VL6180x_RangeData_t Range;
  368. VL6180x_RangeGetInterruptStatus(vl6180x_dev, &u8status);
  369. if (u8status == RES_INT_STAT_GPIO_NEW_SAMPLE_READY)
  370. {
  371. VL6180x_RangeGetMeasurement(vl6180x_dev, &Range);
  372. VL6180x_RangeSetSystemMode(vl6180x_dev, MODE_START_STOP | MODE_SINGLESHOT);
  373. ParamVal = Range.range_mm;
  374. if( ParamVal < 400 )
  375. {
  376. ParamVal = VL6180x_RangeCheckMeasurement(ParamVal);
  377. }
  378. //LOG_INF("Laser Range : %d / %d \n", Range.range_mm, Range.DMax);
  379. }
  380. else
  381. {
  382. ParamVal = 765;
  383. LOG_INF("Laser Get Data Failed \n");
  384. }
  385. #endif
  386. if(copy_to_user(p_u4Param , &ParamVal , sizeof(unsigned int)))
  387. {
  388. LOG_INF("copy to user failed when getting motor information \n");
  389. }
  390. //spin_unlock(&g_Laser_SpinLock); //system breakdown
  391. }
  392. break;
  393. case VL6180_IOCTL_GETOFFCALB: //Offset Calibrate place white target at 100mm from glass
  394. {
  395. void __user *p_u4Param = (void __user *)a_u4Param;
  396. int i = 0;
  397. int RangeSum =0,RangeAvg=0;
  398. int OffsetInt =0;
  399. VL6180x_RangeData_t Range;
  400. spin_lock(&g_Laser_SpinLock);
  401. g_s4Laser_Opened = 3;
  402. spin_unlock(&g_Laser_SpinLock);
  403. VL6180x_SystemInit(3, 1, VL6180_OFFSET_CALIB);
  404. for( i = 0; i < N_MEASURE_AVG; )
  405. {
  406. if( VL6180x_GetRangeValue(&Range) )
  407. {
  408. LOG_INF("VL6180 Offset Calibration Orignal: %d - RV[%d] - SR[%d]\n", i, Range.range_mm, Range.signalRate_mcps);
  409. i++;
  410. RangeSum += Range.range_mm;
  411. }
  412. }
  413. RangeAvg = RangeSum / N_MEASURE_AVG;
  414. if( RangeAvg >= ( OFFSET_CALIB_TARGET_DISTANCE - 3 ) && RangeAvg <= ( OFFSET_CALIB_TARGET_DISTANCE + 3) )
  415. {
  416. LOG_INF("VL6180 Offset Calibration: Original offset is OK, finish offset calibration\n");
  417. }
  418. else
  419. {
  420. LOG_INF("VL6180 Offset Calibration: Start offset calibration\n");
  421. VL6180x_SystemInit(1, 0, VL6180_OFFSET_CALIB);
  422. RangeSum = 0;
  423. for( i = 0; i < N_MEASURE_AVG; )
  424. {
  425. if( VL6180x_GetRangeValue(&Range) )
  426. {
  427. LOG_INF("VL6180 Offset Calibration: %d - RV[%d] - SR[%d]\n", i, Range.range_mm, Range.signalRate_mcps);
  428. i++;
  429. RangeSum += Range.range_mm;
  430. }
  431. msleep(50);
  432. }
  433. RangeAvg = RangeSum / N_MEASURE_AVG;
  434. LOG_INF("VL6180 Offset Calibration: Get the average Range as %d\n", RangeAvg);
  435. OffsetInt = OFFSET_CALIB_TARGET_DISTANCE - RangeAvg;
  436. LOG_INF("VL6180 Offset Calibration: Set the offset value(pre-scaling) as %d\n", OffsetInt);
  437. if( ABS(OffsetInt) > 127 ) // offset value : ~128 ~ 127
  438. {
  439. OffsetInt = 0xFFFFFFFF;
  440. i4RetValue = -1;
  441. }
  442. g_Laser_OffsetCalib = OffsetInt;
  443. //VL6180x_SetOffset(vl6180x_dev, OffsetInt);
  444. VL6180x_SystemInit(3, 1, 0);
  445. LOG_INF("VL6180 Offset Calibration: End\n");
  446. }
  447. spin_lock(&g_Laser_SpinLock);
  448. g_s4Laser_Opened = 2;
  449. spin_unlock(&g_Laser_SpinLock);
  450. if(copy_to_user(p_u4Param , &OffsetInt , sizeof(int)))
  451. {
  452. LOG_INF("copy to user failed when getting VL6180_IOCTL_GETOFFCALB \n");
  453. }
  454. }
  455. break;
  456. case VL6180_IOCTL_SETOFFCALB:
  457. {
  458. int OffsetInt =(int)a_u4Param;
  459. #if 1
  460. g_Laser_OffsetCalib = OffsetInt;
  461. LOG_INF("g_Laser_OffsetCalib : %d\n", g_Laser_OffsetCalib);
  462. #else
  463. VL6180x_RangeSetSystemMode(vl6180x_dev, MODE_START_STOP);
  464. VL6180x_RangeClearInterrupt(vl6180x_dev);
  465. VL6180x_SystemInit(3, 1, 0);
  466. LOG_INF("OffsetInt : %d\n", OffsetInt);
  467. VL6180x_SetOffset(vl6180x_dev,(int)OffsetInt);
  468. #endif
  469. }
  470. break;
  471. case VL6180_IOCTL_GETXTALKCALB: // Place a dark target at 400mm ~ Lower reflectance target recommended, e.g. 17% gray card.
  472. {
  473. void __user *p_u4Param = (void __user *)a_u4Param;
  474. int i=0;
  475. int RangeSum =0;
  476. int RateSum = 0;
  477. int XtalkInt =0;
  478. VL6180x_RangeData_t Range;
  479. spin_lock(&g_Laser_SpinLock);
  480. g_s4Laser_Opened = 3;
  481. spin_unlock(&g_Laser_SpinLock);
  482. VL6180x_SystemInit(3, 1, VL6180_XTALK_CALIB);
  483. for( i = 0; i < N_MEASURE_AVG; )
  484. {
  485. if( VL6180x_GetRangeValue(&Range) )
  486. {
  487. RangeSum += Range.range_mm;
  488. RateSum += Range.signalRate_mcps;
  489. LOG_INF("VL6180 XTalk Calibration: %d - RV[%d] - SR[%d]\n", i, Range.range_mm, Range.signalRate_mcps);
  490. i++;
  491. }
  492. }
  493. XtalkInt = ( RateSum * ( N_MEASURE_AVG * XTALK_CALIB_TARGET_DISTANCE - RangeSum ) ) /( N_MEASURE_AVG * XTALK_CALIB_TARGET_DISTANCE * N_MEASURE_AVG) ;
  494. g_Laser_XTalkCalib = XtalkInt;
  495. // TODO: If g_Laser_XTalkCalib is negative, laser don't get range.
  496. if( g_Laser_XTalkCalib < 0 )
  497. {
  498. i4RetValue = -1;
  499. g_Laser_XTalkCalib = 0xFFFFFFFF;
  500. }
  501. //VL6180x_SetXTalkCompensationRate(vl6180x_dev, g_Laser_XTalkCalib);
  502. VL6180x_SystemInit(3, 1, 0);
  503. LOG_INF("VL6180 XTalk Calibration: End\n");
  504. spin_lock(&g_Laser_SpinLock);
  505. g_s4Laser_Opened = 2;
  506. spin_unlock(&g_Laser_SpinLock);
  507. if(copy_to_user(p_u4Param , &XtalkInt , sizeof(int)))
  508. {
  509. LOG_INF("copy to user failed when getting VL6180_IOCTL_GETOFFCALB \n");
  510. }
  511. }
  512. break;
  513. case VL6180_IOCTL_SETXTALKCALB:
  514. {
  515. int XtalkInt =(int)a_u4Param;
  516. #if 1
  517. g_Laser_XTalkCalib = XtalkInt;
  518. LOG_INF("g_Laser_XTalkCalib : %d\n", g_Laser_XTalkCalib);
  519. #else
  520. VL6180x_SystemInit(3, 1, 0);
  521. LOG_INF("XtalkInt : %d\n", XtalkInt);
  522. VL6180x_SetXTalkCompensationRate(vl6180x_dev, XtalkInt);
  523. #endif
  524. }
  525. break;
  526. default :
  527. LOG_INF("No CMD \n");
  528. i4RetValue = -EPERM;
  529. break;
  530. }
  531. return i4RetValue;
  532. }
  533. //Main jobs:
  534. // 1.check for device-specified errors, device not ready.
  535. // 2.Initialize the device if it is opened for the first time.
  536. // 3.Update f_op pointer.
  537. // 4.Fill data structures into private_data
  538. //CAM_RESET
  539. static int Laser_Open(struct inode * a_pstInode, struct file * a_pstFile)
  540. {
  541. LOG_INF("Start \n");
  542. if( g_s4Laser_Opened )
  543. {
  544. LOG_INF("The device is opened \n");
  545. return -EBUSY;
  546. }
  547. spin_lock(&g_Laser_SpinLock);
  548. g_s4Laser_Opened = 1;
  549. spin_unlock(&g_Laser_SpinLock);
  550. LOG_INF("End \n");
  551. return 0;
  552. }
  553. //Main jobs:
  554. // 1.Deallocate anything that "open" allocated in private_data.
  555. // 2.Shut down the device on last close.
  556. // 3.Only called once on last time.
  557. // Q1 : Try release multiple times.
  558. static int Laser_Release(struct inode * a_pstInode, struct file * a_pstFile)
  559. {
  560. LOG_INF("Start \n");
  561. if (g_s4Laser_Opened)
  562. {
  563. LOG_INF("Free \n");
  564. spin_lock(&g_Laser_SpinLock);
  565. g_s4Laser_Opened = 0;
  566. spin_unlock(&g_Laser_SpinLock);
  567. }
  568. LOG_INF("End \n");
  569. return 0;
  570. }
  571. static const struct file_operations g_stLaser_fops =
  572. {
  573. .owner = THIS_MODULE,
  574. .open = Laser_Open,
  575. .release = Laser_Release,
  576. .unlocked_ioctl = Laser_Ioctl,
  577. #ifdef CONFIG_COMPAT
  578. .compat_ioctl = Laser_Ioctl,
  579. #endif
  580. };
  581. inline static int Register_Laser_CharDrv(void)
  582. {
  583. struct device* laser_device = NULL;
  584. LOG_INF("Start\n");
  585. //Allocate char driver no.
  586. if( alloc_chrdev_region(&g_Laser_devno, 0, 1,LASER_DRVNAME) )
  587. {
  588. LOG_INF("Allocate device no failed\n");
  589. return -EAGAIN;
  590. }
  591. //Allocate driver
  592. g_pLaser_CharDrv = cdev_alloc();
  593. if(NULL == g_pLaser_CharDrv)
  594. {
  595. unregister_chrdev_region(g_Laser_devno, 1);
  596. LOG_INF("Allocate mem for kobject failed\n");
  597. return -ENOMEM;
  598. }
  599. //Attatch file operation.
  600. cdev_init(g_pLaser_CharDrv, &g_stLaser_fops);
  601. g_pLaser_CharDrv->owner = THIS_MODULE;
  602. //Add to system
  603. if(cdev_add(g_pLaser_CharDrv, g_Laser_devno, 1))
  604. {
  605. LOG_INF("Attatch file operation failed\n");
  606. unregister_chrdev_region(g_Laser_devno, 1);
  607. return -EAGAIN;
  608. }
  609. actuator_class = class_create(THIS_MODULE, LASER_DRIVER_CLASS_NAME);
  610. if (IS_ERR(actuator_class)) {
  611. int ret = PTR_ERR(actuator_class);
  612. LOG_INF("Unable to create class, err = %d\n", ret);
  613. return ret;
  614. }
  615. laser_device = device_create(actuator_class, NULL, g_Laser_devno, NULL, LASER_DRVNAME);
  616. if(NULL == laser_device)
  617. {
  618. return -EIO;
  619. }
  620. LOG_INF("End\n");
  621. return 0;
  622. }
  623. inline static void UnRegister_Laser_CharDrv(void)
  624. {
  625. LOG_INF("Start\n");
  626. //Release char driver
  627. cdev_del(g_pLaser_CharDrv);
  628. unregister_chrdev_region(g_Laser_devno, 1);
  629. device_destroy(actuator_class, g_Laser_devno);
  630. class_destroy(actuator_class);
  631. LOG_INF("End\n");
  632. }
  633. //////////////////////////////////////////////////////////////////////
  634. static int Laser_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id);
  635. static int Laser_i2c_remove(struct i2c_client *client);
  636. static const struct i2c_device_id Laser_i2c_id[] = {{LASER_DRVNAME, 0},{}};
  637. /* Compatible name must be the same with that defined in codegen.dws and cust_i2c.dtsi */
  638. /* TOOL : kernel-3.10\tools\dct */
  639. /* PATH : vendor\mediatek\proprietary\custom\#project#\kernel\dct\dct */
  640. #if I2C_CONFIG_SETTING == 2
  641. static const struct of_device_id LASER_of_match[] = {
  642. {.compatible = "mediatek,CAMERA_MAIN_AF"},
  643. {},
  644. };
  645. #endif
  646. static struct i2c_driver Laser_i2c_driver = {
  647. .probe = Laser_i2c_probe,
  648. .remove = Laser_i2c_remove,
  649. .driver.name = LASER_DRVNAME,
  650. #if I2C_CONFIG_SETTING == 2
  651. .driver.of_match_table = LASER_of_match,
  652. #endif
  653. .id_table = Laser_i2c_id,
  654. };
  655. #if 0
  656. static int Laser_i2c_detect(struct i2c_client *client, int kind, struct i2c_board_info *info) {
  657. strcpy(info->type, LASER_DRVNAME);
  658. return 0;
  659. }
  660. #endif
  661. static int Laser_i2c_remove(struct i2c_client *client) {
  662. return 0;
  663. }
  664. /* Kirby: add new-style driver {*/
  665. static int Laser_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
  666. {
  667. int i4RetValue = 0;
  668. LOG_INF("Start\n");
  669. /* Kirby: add new-style driver { */
  670. g_pstLaser_I2Cclient = client;
  671. g_pstLaser_I2Cclient->addr = I2C_SLAVE_ADDRESS;
  672. g_pstLaser_I2Cclient->addr = g_pstLaser_I2Cclient->addr >> 1;
  673. //Register char driver
  674. i4RetValue = Register_Laser_CharDrv();
  675. if(i4RetValue){
  676. LOG_INF(" register char device failed!\n");
  677. return i4RetValue;
  678. }
  679. spin_lock_init(&g_Laser_SpinLock);
  680. LOG_INF("Attached!! \n");
  681. return 0;
  682. }
  683. static int Laser_probe(struct platform_device *pdev)
  684. {
  685. return i2c_add_driver(&Laser_i2c_driver);
  686. }
  687. static int Laser_remove(struct platform_device *pdev)
  688. {
  689. i2c_del_driver(&Laser_i2c_driver);
  690. return 0;
  691. }
  692. static int Laser_suspend(struct platform_device *pdev, pm_message_t mesg)
  693. {
  694. return 0;
  695. }
  696. static int Laser_resume(struct platform_device *pdev)
  697. {
  698. return 0;
  699. }
  700. // platform structure
  701. static struct platform_driver g_stLaser_Driver = {
  702. .probe = Laser_probe,
  703. .remove = Laser_remove,
  704. .suspend = Laser_suspend,
  705. .resume = Laser_resume,
  706. .driver = {
  707. .name = PLATFORM_DRIVER_NAME,
  708. .owner = THIS_MODULE,
  709. }
  710. };
  711. static struct platform_device g_stLaser_Device = {
  712. .name = PLATFORM_DRIVER_NAME,
  713. .id = 0,
  714. .dev = {}
  715. };
  716. static int __init STMVL6180_i2c_init(void)
  717. {
  718. #if I2C_CONFIG_SETTING == 1
  719. i2c_register_board_info(LASER_I2C_BUSNUM, &kd_laser_dev, 1);
  720. #endif
  721. if(platform_device_register(&g_stLaser_Device)){
  722. LOG_INF("failed to register Laser driver\n");
  723. return -ENODEV;
  724. }
  725. if(platform_driver_register(&g_stLaser_Driver)){
  726. LOG_INF("Failed to register Laser driver\n");
  727. return -ENODEV;
  728. }
  729. return 0;
  730. }
  731. static void __exit STMVL6180_i2c_exit(void)
  732. {
  733. platform_driver_unregister(&g_stLaser_Driver);
  734. }
  735. module_init(STMVL6180_i2c_init);
  736. module_exit(STMVL6180_i2c_exit);
  737. MODULE_DESCRIPTION("ST FlightSense Time-of-Flight sensor driver");
  738. MODULE_AUTHOR("STMicroelectronics Imaging Division");
  739. MODULE_LICENSE("GPL");