prox_max88920.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  1. /*
  2. * Copyright (C) 2012, Samsung Electronics Co. Ltd. All Rights Reserved.
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. */
  15. #include "../ssp.h"
  16. #define VENDOR "MAXIM"
  17. #define CHIP_ID "MAX88920"
  18. #define CANCELATION_FILE_PATH "/efs/prox_cal"
  19. #define LCD_LDI_FILE_PATH "/sys/class/lcd/panel/window_type"
  20. #define LINE_1 '4'
  21. #define LINE_2 '2'
  22. #define LDI_OTHERS '0'
  23. #define LDI_GRAY '1'
  24. #define LDI_WHITE '2'
  25. #if defined(CONFIG_MACH_JACTIVESKT)
  26. #define DEFUALT_HIGH_THRESHOLD 45
  27. #define DEFUALT_LOW_THRESHOLD 30
  28. #define TBD_HIGH_THRESHOLD 45
  29. #define TBD_LOW_THRESHOLD 30
  30. #define WHITE_HIGH_THRESHOLD 45
  31. #define WHITE_LOW_THRESHOLD 30
  32. #else
  33. #define DEFUALT_HIGH_THRESHOLD 60
  34. #define DEFUALT_LOW_THRESHOLD 45
  35. #define TBD_HIGH_THRESHOLD 60
  36. #define TBD_LOW_THRESHOLD 45
  37. #define WHITE_HIGH_THRESHOLD 60
  38. #define WHITE_LOW_THRESHOLD 45
  39. #endif
  40. /*************************************************************************/
  41. /* factory Sysfs */
  42. /*************************************************************************/
  43. static ssize_t prox_vendor_show(struct device *dev,
  44. struct device_attribute *attr, char *buf)
  45. {
  46. return sprintf(buf, "%s\n", VENDOR);
  47. }
  48. static ssize_t prox_name_show(struct device *dev,
  49. struct device_attribute *attr, char *buf)
  50. {
  51. return sprintf(buf, "%s\n", CHIP_ID);
  52. }
  53. static ssize_t proximity_avg_show(struct device *dev,
  54. struct device_attribute *attr, char *buf)
  55. {
  56. struct ssp_data *data = dev_get_drvdata(dev);
  57. return snprintf(buf, PAGE_SIZE, "%d,%d,%d\n",
  58. data->buf[PROXIMITY_RAW].prox[1],
  59. data->buf[PROXIMITY_RAW].prox[2],
  60. data->buf[PROXIMITY_RAW].prox[3]);
  61. }
  62. static ssize_t proximity_avg_store(struct device *dev,
  63. struct device_attribute *attr, const char *buf, size_t size)
  64. {
  65. char chTempbuf[2] = { 1, 20};
  66. int iRet;
  67. int64_t dEnable;
  68. struct ssp_data *data = dev_get_drvdata(dev);
  69. iRet = kstrtoll(buf, 10, &dEnable);
  70. if (iRet < 0)
  71. return iRet;
  72. if (dEnable) {
  73. send_instruction(data, ADD_SENSOR, PROXIMITY_RAW, chTempbuf, 2);
  74. data->bProximityRawEnabled = true;
  75. } else {
  76. send_instruction(data, REMOVE_SENSOR, PROXIMITY_RAW,
  77. chTempbuf, 2);
  78. data->bProximityRawEnabled = false;
  79. }
  80. return size;
  81. }
  82. static unsigned char get_proximity_rawdata(struct ssp_data *data)
  83. {
  84. unsigned char uRowdata = 0;
  85. char chTempbuf[2] = { 1, 20};
  86. if (data->bProximityRawEnabled == false) {
  87. send_instruction(data, ADD_SENSOR, PROXIMITY_RAW, chTempbuf, 2);
  88. msleep(200);
  89. uRowdata = data->buf[PROXIMITY_RAW].prox[0];
  90. send_instruction(data, REMOVE_SENSOR, PROXIMITY_RAW,
  91. chTempbuf, 2);
  92. } else {
  93. uRowdata = data->buf[PROXIMITY_RAW].prox[0];
  94. }
  95. return uRowdata;
  96. }
  97. static ssize_t proximity_state_show(struct device *dev,
  98. struct device_attribute *attr, char *buf)
  99. {
  100. struct ssp_data *data = dev_get_drvdata(dev);
  101. return sprintf(buf, "%u\n", get_proximity_rawdata(data));
  102. }
  103. static ssize_t proximity_raw_data_show(struct device *dev,
  104. struct device_attribute *attr, char *buf)
  105. {
  106. struct ssp_data *data = dev_get_drvdata(dev);
  107. return sprintf(buf, "%u\n", get_proximity_rawdata(data));
  108. }
  109. static int get_proximity_threshold(struct ssp_data *data)
  110. {
  111. if (data->uProxCanc <= (data->uProxLoThresh_default >> 1))
  112. return FAIL;
  113. data->uProxHiThresh = data->uProxHiThresh_default
  114. + (data->uProxCanc - (data->uProxLoThresh_default >> 1));
  115. data->uProxLoThresh = data->uProxLoThresh_default
  116. + (data->uProxCanc - (data->uProxLoThresh_default >> 1));
  117. return SUCCESS;
  118. }
  119. static void change_proximity_default_threshold(struct ssp_data *data)
  120. {
  121. switch (data->chLcdLdi[1]) {
  122. case LDI_GRAY:
  123. data->uProxHiThresh_default = TBD_HIGH_THRESHOLD;
  124. data->uProxLoThresh_default = TBD_LOW_THRESHOLD;
  125. break;
  126. case LDI_WHITE:
  127. data->uProxHiThresh_default = WHITE_HIGH_THRESHOLD;
  128. data->uProxLoThresh_default = WHITE_LOW_THRESHOLD;
  129. break;
  130. case LDI_OTHERS:
  131. data->uProxHiThresh_default = DEFUALT_HIGH_THRESHOLD;
  132. data->uProxLoThresh_default = DEFUALT_LOW_THRESHOLD;
  133. break;
  134. default:
  135. data->uProxHiThresh_default = DEFUALT_HIGH_THRESHOLD;
  136. data->uProxLoThresh_default = DEFUALT_LOW_THRESHOLD;
  137. break;
  138. }
  139. data->uProxHiThresh = data->uProxHiThresh_default;
  140. data->uProxLoThresh = data->uProxLoThresh_default;
  141. }
  142. int proximity_open_lcd_ldi(struct ssp_data *data)
  143. {
  144. int iRet = 0;
  145. mm_segment_t old_fs;
  146. struct file *cancel_filp = NULL;
  147. old_fs = get_fs();
  148. set_fs(KERNEL_DS);
  149. cancel_filp = filp_open(LCD_LDI_FILE_PATH, O_RDONLY, 0666);
  150. if (IS_ERR(cancel_filp)) {
  151. iRet = PTR_ERR(cancel_filp);
  152. if (iRet != -ENOENT)
  153. pr_err("[SSP]: %s - Can't open lcd ldi file\n",
  154. __func__);
  155. set_fs(old_fs);
  156. data->chLcdLdi[0] = 0;
  157. data->chLcdLdi[1] = 0;
  158. goto exit;
  159. }
  160. iRet = cancel_filp->f_op->read(cancel_filp,
  161. (u8 *)data->chLcdLdi, sizeof(u8) * 2, &cancel_filp->f_pos);
  162. if (iRet != (sizeof(u8) * 2)) {
  163. pr_err("[SSP]: %s - Can't read the lcd ldi data\n", __func__);
  164. iRet = -EIO;
  165. }
  166. ssp_dbg("[SSP]: %s - %c%c\n", __func__,
  167. data->chLcdLdi[0], data->chLcdLdi[1]);
  168. filp_close(cancel_filp, current->files);
  169. set_fs(old_fs);
  170. exit:
  171. change_proximity_default_threshold(data);
  172. return iRet;
  173. }
  174. int proximity_open_calibration(struct ssp_data *data)
  175. {
  176. int iRet = 0;
  177. mm_segment_t old_fs;
  178. struct file *cancel_filp = NULL;
  179. if(data->prox_state == OFFSET_CAL_DATA) {
  180. data->uProxHiThresh = data->proximity_highThreshold;
  181. data->uProxLoThresh = data->proximity_lowThreshold;
  182. goto exit;
  183. }
  184. else if (data->prox_state == FILE_OPEN_FAIL) {
  185. goto exit;
  186. }
  187. old_fs = get_fs();
  188. set_fs(KERNEL_DS);
  189. cancel_filp = filp_open(CANCELATION_FILE_PATH, O_RDONLY, 0666);
  190. if (IS_ERR(cancel_filp)) {
  191. iRet = PTR_ERR(cancel_filp);
  192. if (iRet != -ENOENT)
  193. pr_err("[SSP]: %s - Can't open cancelation file\n",
  194. __func__);
  195. set_fs(old_fs);
  196. data->prox_state = FILE_OPEN_FAIL;
  197. goto exit;
  198. }
  199. iRet = cancel_filp->f_op->read(cancel_filp,
  200. (u8 *)&data->uProxCanc, sizeof(u8), &cancel_filp->f_pos);
  201. if (iRet != sizeof(u8)) {
  202. pr_err("[SSP]: %s - Can't read the cancel data\n", __func__);
  203. iRet = -EIO;
  204. }
  205. if (data->uProxCanc != 0) /*If there is an offset cal data. */ {
  206. get_proximity_threshold(data);
  207. data->prox_state = OFFSET_CAL_DATA;
  208. data->proximity_highThreshold = data->uProxHiThresh;
  209. data->proximity_lowThreshold = data->uProxLoThresh;
  210. }
  211. pr_info("%s: proximity ps_canc = %d, ps_thresh hi - %d lo - %d\n",
  212. __func__, data->uProxCanc, data->uProxHiThresh,
  213. data->uProxLoThresh);
  214. filp_close(cancel_filp, current->files);
  215. set_fs(old_fs);
  216. exit:
  217. set_proximity_threshold(data, data->uProxHiThresh, data->uProxLoThresh);
  218. return iRet;
  219. }
  220. static int proximity_store_cancelation(struct ssp_data *data, int iCalCMD)
  221. {
  222. int iRet = 0;
  223. mm_segment_t old_fs;
  224. struct file *cancel_filp = NULL;
  225. data->prox_state = STORE_SUCCESS;
  226. if (iCalCMD) {
  227. data->uProxCanc = get_proximity_rawdata(data);
  228. get_proximity_threshold(data);
  229. } else {
  230. data->uProxHiThresh = data->uProxHiThresh_default;
  231. data->uProxLoThresh = data->uProxLoThresh_default;
  232. data->uProxCanc = 0;
  233. }
  234. set_proximity_threshold(data, data->uProxHiThresh, data->uProxLoThresh);
  235. old_fs = get_fs();
  236. set_fs(KERNEL_DS);
  237. cancel_filp = filp_open(CANCELATION_FILE_PATH,
  238. O_CREAT | O_TRUNC | O_WRONLY | O_SYNC, 0666);
  239. if (IS_ERR(cancel_filp)) {
  240. pr_err("%s: Can't open cancelation file\n", __func__);
  241. set_fs(old_fs);
  242. iRet = PTR_ERR(cancel_filp);
  243. return iRet;
  244. }
  245. iRet = cancel_filp->f_op->write(cancel_filp, (u8 *)&data->uProxCanc,
  246. sizeof(u8), &cancel_filp->f_pos);
  247. if (iRet != sizeof(u8)) {
  248. pr_err("%s: Can't write the cancel data to file\n", __func__);
  249. iRet = -EIO;
  250. }
  251. filp_close(cancel_filp, current->files);
  252. set_fs(old_fs);
  253. return iRet;
  254. }
  255. static ssize_t proximity_cancel_show(struct device *dev,
  256. struct device_attribute *attr, char *buf)
  257. {
  258. struct ssp_data *data = dev_get_drvdata(dev);
  259. unsigned char uProxCanc = data->uProxCanc;
  260. if (uProxCanc > (data->uProxLoThresh_default >> 1))
  261. uProxCanc = uProxCanc - (data->uProxLoThresh_default >> 1);
  262. else
  263. uProxCanc = 0;
  264. ssp_dbg("[SSP]: uProxThresh : hi : %u lo : %u, uProxCanc = %u\n",
  265. data->uProxHiThresh, data->uProxLoThresh, uProxCanc);
  266. return sprintf(buf, "%u,%u,%u\n", uProxCanc, data->uProxHiThresh,
  267. data->uProxLoThresh);
  268. }
  269. static ssize_t proximity_cancel_store(struct device *dev,
  270. struct device_attribute *attr, const char *buf, size_t size)
  271. {
  272. int iCalCMD = 0, iRet = 0;
  273. struct ssp_data *data = dev_get_drvdata(dev);
  274. if (sysfs_streq(buf, "1")) /* calibrate cancelation value */
  275. iCalCMD = 1;
  276. else if (sysfs_streq(buf, "0")) /* reset cancelation value */
  277. iCalCMD = 0;
  278. else {
  279. pr_debug("%s: invalid value %d\n", __func__, *buf);
  280. return -EINVAL;
  281. }
  282. iRet = proximity_store_cancelation(data, iCalCMD);
  283. if (iRet < 0) {
  284. pr_err("[SSP]: - %s proximity_store_cancelation() failed\n",
  285. __func__);
  286. return iRet;
  287. }
  288. ssp_dbg("[SSP]: %s - %u\n", __func__, iCalCMD);
  289. return size;
  290. }
  291. static ssize_t proximity_thresh_high_show(struct device *dev,
  292. struct device_attribute *attr, char *buf)
  293. {
  294. struct ssp_data *data = dev_get_drvdata(dev);
  295. ssp_dbg("[SSP]: uProxThresh = hi - %u, lo - %u\n",
  296. data->uProxHiThresh, data->uProxLoThresh);
  297. return sprintf(buf, "%u,%u\n", data->uProxHiThresh,
  298. data->uProxLoThresh);
  299. }
  300. static ssize_t proximity_thresh_high_store(struct device *dev,
  301. struct device_attribute *attr, const char *buf, size_t size)
  302. {
  303. u8 uNewThresh;
  304. int iRet = 0;
  305. struct ssp_data *data = dev_get_drvdata(dev);
  306. iRet = kstrtou8(buf, 10, &uNewThresh);
  307. if (iRet < 0)
  308. pr_err("[SSP]: %s - kstrtoint failed.(%d)\n", __func__, iRet);
  309. else {
  310. data->uProxHiThresh = uNewThresh;
  311. set_proximity_threshold(data, data->uProxHiThresh,
  312. data->uProxLoThresh);
  313. }
  314. ssp_dbg("[SSP]: %s - new prox threshold : hi - %u, lo - %u\n",
  315. __func__, data->uProxHiThresh, data->uProxLoThresh);
  316. return size;
  317. }
  318. static ssize_t proximity_thresh_low_show(struct device *dev,
  319. struct device_attribute *attr, char *buf)
  320. {
  321. struct ssp_data *data = dev_get_drvdata(dev);
  322. ssp_dbg("[SSP]: uProxThresh = hi - %u, lo - %u\n",
  323. data->uProxHiThresh, data->uProxLoThresh);
  324. return sprintf(buf, "%u,%u\n", data->uProxHiThresh,
  325. data->uProxLoThresh);
  326. }
  327. static ssize_t proximity_thresh_low_store(struct device *dev,
  328. struct device_attribute *attr, const char *buf, size_t size)
  329. {
  330. u8 uNewThresh;
  331. int iRet = 0;
  332. struct ssp_data *data = dev_get_drvdata(dev);
  333. iRet = kstrtou8(buf, 10, &uNewThresh);
  334. if (iRet < 0)
  335. pr_err("[SSP]: %s - kstrtoint failed.(%d)\n", __func__, iRet);
  336. else {
  337. data->uProxLoThresh = uNewThresh;
  338. set_proximity_threshold(data, data->uProxHiThresh,
  339. data->uProxLoThresh);
  340. }
  341. ssp_dbg("[SSP]: %s - new prox threshold : hi - %u, lo - %u\n",
  342. __func__, data->uProxHiThresh, data->uProxLoThresh);
  343. return size;
  344. }
  345. static ssize_t barcode_emul_enable_show(struct device *dev,
  346. struct device_attribute *attr, char *buf)
  347. {
  348. struct ssp_data *data = dev_get_drvdata(dev);
  349. return snprintf(buf, PAGE_SIZE, "%u\n", data->bBarcodeEnabled);
  350. }
  351. static ssize_t barcode_emul_enable_store(struct device *dev,
  352. struct device_attribute *attr, const char *buf, size_t size)
  353. {
  354. int iRet;
  355. int64_t dEnable;
  356. struct ssp_data *data = dev_get_drvdata(dev);
  357. iRet = kstrtoll(buf, 10, &dEnable);
  358. if (iRet < 0)
  359. return iRet;
  360. if (dEnable)
  361. set_proximity_barcode_enable(data, true);
  362. else
  363. set_proximity_barcode_enable(data, false);
  364. return size;
  365. }
  366. static DEVICE_ATTR(vendor, S_IRUGO, prox_vendor_show, NULL);
  367. static DEVICE_ATTR(name, S_IRUGO, prox_name_show, NULL);
  368. static DEVICE_ATTR(state, S_IRUGO, proximity_state_show, NULL);
  369. static DEVICE_ATTR(raw_data, S_IRUGO, proximity_raw_data_show, NULL);
  370. static DEVICE_ATTR(barcode_emul_en, S_IRUGO | S_IWUSR | S_IWGRP,
  371. barcode_emul_enable_show, barcode_emul_enable_store);
  372. static DEVICE_ATTR(prox_avg, S_IRUGO | S_IWUSR | S_IWGRP,
  373. proximity_avg_show, proximity_avg_store);
  374. static DEVICE_ATTR(prox_cal, S_IRUGO | S_IWUSR | S_IWGRP,
  375. proximity_cancel_show, proximity_cancel_store);
  376. static DEVICE_ATTR(thresh_high, S_IRUGO | S_IWUSR | S_IWGRP,
  377. proximity_thresh_high_show, proximity_thresh_high_store);
  378. static DEVICE_ATTR(thresh_low, S_IRUGO | S_IWUSR | S_IWGRP,
  379. proximity_thresh_low_show, proximity_thresh_low_store);
  380. static struct device_attribute *prox_attrs[] = {
  381. &dev_attr_vendor,
  382. &dev_attr_name,
  383. &dev_attr_state,
  384. &dev_attr_raw_data,
  385. &dev_attr_prox_avg,
  386. &dev_attr_prox_cal,
  387. &dev_attr_thresh_high,
  388. &dev_attr_thresh_low,
  389. &dev_attr_barcode_emul_en,
  390. NULL,
  391. };
  392. void initialize_prox_factorytest(struct ssp_data *data)
  393. {
  394. sensors_register(data->prox_device, data,
  395. prox_attrs, "proximity_sensor");
  396. }
  397. void remove_prox_factorytest(struct ssp_data *data)
  398. {
  399. sensors_unregister(data->prox_device, prox_attrs);
  400. }