stmvl6180.c 20 KB

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