prox_max88005.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  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 "MAX88005"
  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. /*************************************************************************/
  26. /* factory Sysfs */
  27. /*************************************************************************/
  28. static ssize_t prox_vendor_show(struct device *dev,
  29. struct device_attribute *attr, char *buf)
  30. {
  31. return sprintf(buf, "%s\n", VENDOR);
  32. }
  33. static ssize_t prox_name_show(struct device *dev,
  34. struct device_attribute *attr, char *buf)
  35. {
  36. return sprintf(buf, "%s\n", CHIP_ID);
  37. }
  38. static ssize_t proximity_avg_show(struct device *dev,
  39. struct device_attribute *attr, char *buf)
  40. {
  41. struct ssp_data *data = dev_get_drvdata(dev);
  42. return snprintf(buf, PAGE_SIZE, "%d,%d,%d\n",
  43. data->buf[PROXIMITY_RAW].prox[1],
  44. data->buf[PROXIMITY_RAW].prox[2],
  45. data->buf[PROXIMITY_RAW].prox[3]);
  46. }
  47. static ssize_t proximity_avg_store(struct device *dev,
  48. struct device_attribute *attr, const char *buf, size_t size)
  49. {
  50. char chTempbuf[2] = { 1, 20};
  51. int iRet;
  52. int64_t dEnable;
  53. struct ssp_data *data = dev_get_drvdata(dev);
  54. iRet = kstrtoll(buf, 10, &dEnable);
  55. if (iRet < 0)
  56. return iRet;
  57. if (dEnable) {
  58. send_instruction(data, ADD_SENSOR, PROXIMITY_RAW, chTempbuf, 2);
  59. data->bProximityRawEnabled = true;
  60. } else {
  61. send_instruction(data, REMOVE_SENSOR, PROXIMITY_RAW,
  62. chTempbuf, 2);
  63. data->bProximityRawEnabled = false;
  64. }
  65. return size;
  66. }
  67. static unsigned char get_proximity_rawdata(struct ssp_data *data)
  68. {
  69. unsigned char uRowdata = 0;
  70. char chTempbuf[2] = { 1, 20};
  71. if (data->bProximityRawEnabled == false) {
  72. send_instruction(data, ADD_SENSOR, PROXIMITY_RAW, chTempbuf, 2);
  73. msleep(200);
  74. uRowdata = data->buf[PROXIMITY_RAW].prox[0];
  75. send_instruction(data, REMOVE_SENSOR, PROXIMITY_RAW,
  76. chTempbuf, 2);
  77. } else {
  78. uRowdata = data->buf[PROXIMITY_RAW].prox[0];
  79. }
  80. return uRowdata;
  81. }
  82. static ssize_t proximity_state_show(struct device *dev,
  83. struct device_attribute *attr, char *buf)
  84. {
  85. struct ssp_data *data = dev_get_drvdata(dev);
  86. return sprintf(buf, "%u\n", get_proximity_rawdata(data));
  87. }
  88. static int get_proximity_threshold(struct ssp_data *data)
  89. {
  90. if (data->uProxCanc <= (DEFAULT_THRESHOLD_LOW >> 1))
  91. return FAIL;
  92. data->uProxThreshHi = DEFAULT_THRESHOLD_HI
  93. + (data->uProxCanc - (DEFAULT_THRESHOLD_LOW >> 1));
  94. data->uProxThreshLow = DEFAULT_THRESHOLD_LOW
  95. + (data->uProxCanc - (DEFAULT_THRESHOLD_LOW >> 1));
  96. return SUCCESS;
  97. }
  98. static void change_proximity_default_threshold(struct ssp_data *data)
  99. {
  100. switch (data->chLcdLdi[1]) {
  101. case LDI_GRAY:
  102. data->uProxThreshHi = GRAY_OCTA_DEFAULT_THRESHOLD;
  103. data->uProxThreshLow = DEFAULT_THRESHOLD_LOW;
  104. break;
  105. case LDI_WHITE:
  106. data->uProxThreshHi = WHITE_OCTA_DEFAULT_THRESHOLD;
  107. data->uProxThreshLow = DEFAULT_THRESHOLD_LOW;
  108. break;
  109. case LDI_OTHERS:
  110. data->uProxThreshHi = OTHERS_OCTA_DEFAULT_THRESHOLD;
  111. data->uProxThreshLow = DEFAULT_THRESHOLD_LOW;
  112. break;
  113. default:
  114. data->uProxThreshHi = DEFAULT_THRESHOLD_HI;
  115. data->uProxThreshLow = DEFAULT_THRESHOLD_LOW;
  116. break;
  117. }
  118. }
  119. int proximity_open_lcd_ldi(struct ssp_data *data)
  120. {
  121. int iRet = 0;
  122. mm_segment_t old_fs;
  123. struct file *cancel_filp = NULL;
  124. old_fs = get_fs();
  125. set_fs(KERNEL_DS);
  126. cancel_filp = filp_open(LCD_LDI_FILE_PATH, O_RDONLY, 0666);
  127. if (IS_ERR(cancel_filp)) {
  128. iRet = PTR_ERR(cancel_filp);
  129. if (iRet != -ENOENT)
  130. pr_err("[SSP]: %s - Can't open lcd ldi file\n",
  131. __func__);
  132. set_fs(old_fs);
  133. data->chLcdLdi[0] = 0;
  134. data->chLcdLdi[1] = 0;
  135. goto exit;
  136. }
  137. iRet = cancel_filp->f_op->read(cancel_filp,
  138. (u8 *)data->chLcdLdi, sizeof(u8) * 2, &cancel_filp->f_pos);
  139. if (iRet != (sizeof(u8) * 2)) {
  140. pr_err("[SSP]: %s - Can't read the lcd ldi data\n", __func__);
  141. iRet = -EIO;
  142. }
  143. ssp_dbg("[SSP]: %s - %c%c\n", __func__,
  144. data->chLcdLdi[0], data->chLcdLdi[1]);
  145. filp_close(cancel_filp, current->files);
  146. set_fs(old_fs);
  147. exit:
  148. change_proximity_default_threshold(data);
  149. return iRet;
  150. }
  151. int proximity_open_calibration(struct ssp_data *data)
  152. {
  153. int iRet = 0;
  154. mm_segment_t old_fs;
  155. struct file *cancel_filp = NULL;
  156. old_fs = get_fs();
  157. set_fs(KERNEL_DS);
  158. cancel_filp = filp_open(CANCELATION_FILE_PATH, O_RDONLY, 0666);
  159. if (IS_ERR(cancel_filp)) {
  160. iRet = PTR_ERR(cancel_filp);
  161. if (iRet != -ENOENT)
  162. pr_err("[SSP]: %s - Can't open cancelation file\n",
  163. __func__);
  164. set_fs(old_fs);
  165. goto exit;
  166. }
  167. iRet = cancel_filp->f_op->read(cancel_filp,
  168. (u8 *)&data->uProxCanc, sizeof(u8), &cancel_filp->f_pos);
  169. if (iRet != sizeof(u8)) {
  170. pr_err("[SSP]: %s - Can't read the cancel data\n", __func__);
  171. iRet = -EIO;
  172. }
  173. if (data->uProxCanc != 0) /*If there is an offset cal data. */
  174. get_proximity_threshold(data);
  175. pr_info("%s: proximity ps_canc = %d, ps_thresh hi - %d lo - %d\n",
  176. __func__, data->uProxCanc, data->uProxThreshHi,
  177. data->uProxThreshLow);
  178. filp_close(cancel_filp, current->files);
  179. set_fs(old_fs);
  180. exit:
  181. set_proximity_threshold(data);
  182. return iRet;
  183. }
  184. static int proximity_store_cancelation(struct ssp_data *data, int iCalCMD)
  185. {
  186. int iRet = 0;
  187. mm_segment_t old_fs;
  188. struct file *cancel_filp = NULL;
  189. if (iCalCMD) {
  190. data->uProxCanc = get_proximity_rawdata(data);
  191. get_proximity_threshold(data);
  192. } else {
  193. data->uProxThreshHi = DEFAULT_THRESHOLD_HI;
  194. data->uProxThreshLow = DEFAULT_THRESHOLD_LOW;
  195. data->uProxCanc = 0;
  196. }
  197. set_proximity_threshold(data);
  198. old_fs = get_fs();
  199. set_fs(KERNEL_DS);
  200. cancel_filp = filp_open(CANCELATION_FILE_PATH,
  201. O_CREAT | O_TRUNC | O_WRONLY, 0666);
  202. if (IS_ERR(cancel_filp)) {
  203. pr_err("%s: Can't open cancelation file\n", __func__);
  204. set_fs(old_fs);
  205. iRet = PTR_ERR(cancel_filp);
  206. return iRet;
  207. }
  208. iRet = cancel_filp->f_op->write(cancel_filp, (u8 *)&data->uProxCanc,
  209. sizeof(u8), &cancel_filp->f_pos);
  210. if (iRet != sizeof(u8)) {
  211. pr_err("%s: Can't write the cancel data to file\n", __func__);
  212. iRet = -EIO;
  213. }
  214. filp_close(cancel_filp, current->files);
  215. set_fs(old_fs);
  216. return iRet;
  217. }
  218. static ssize_t proximity_cancel_show(struct device *dev,
  219. struct device_attribute *attr, char *buf)
  220. {
  221. struct ssp_data *data = dev_get_drvdata(dev);
  222. ssp_dbg("[SSP]: uProxThresh : hi : %u lo : %u, uProxCanc = %u\n",
  223. data->uProxThreshHi, data->uProxThreshLow, data->uProxCanc);
  224. return sprintf(buf, "%u,%u\n", data->uProxCanc, data->uProxThreshHi);
  225. }
  226. static ssize_t proximity_cancel_store(struct device *dev,
  227. struct device_attribute *attr, const char *buf, size_t size)
  228. {
  229. int iCalCMD = 0, iRet = 0;
  230. struct ssp_data *data = dev_get_drvdata(dev);
  231. if (sysfs_streq(buf, "1")) /* calibrate cancelation value */
  232. iCalCMD = 1;
  233. else if (sysfs_streq(buf, "0")) /* reset cancelation value */
  234. iCalCMD = 0;
  235. else {
  236. pr_debug("%s: invalid value %d\n", __func__, *buf);
  237. return -EINVAL;
  238. }
  239. iRet = proximity_store_cancelation(data, iCalCMD);
  240. if (iRet < 0) {
  241. pr_err("[SSP]: - %s proximity_store_cancelation() failed\n",
  242. __func__);
  243. return iRet;
  244. }
  245. ssp_dbg("[SSP]: %s - %u\n", __func__, iCalCMD);
  246. return size;
  247. }
  248. static ssize_t proximity_thresh_show(struct device *dev,
  249. struct device_attribute *attr, char *buf)
  250. {
  251. struct ssp_data *data = dev_get_drvdata(dev);
  252. ssp_dbg("[SSP]: uProxThresh = hi - %u, lo - %u\n",
  253. data->uProxThreshHi, data->uProxThreshLow);
  254. return sprintf(buf, "%u\n", data->uProxThreshHi);
  255. }
  256. static ssize_t proximity_thresh_store(struct device *dev,
  257. struct device_attribute *attr, const char *buf, size_t size)
  258. {
  259. char chTemp;
  260. u8 uNewThresh = DEFAULT_THRESHOLD_HI;
  261. int iRet = 0;
  262. struct ssp_data *data = dev_get_drvdata(dev);
  263. iRet = kstrtou8(buf, 10, &uNewThresh);
  264. if (iRet < 0)
  265. pr_err("[SSP]: %s - kstrtoint failed.", __func__);
  266. chTemp = uNewThresh - DEFAULT_THRESHOLD_HI;
  267. if (chTemp < 0)
  268. chTemp = 0;
  269. data->uProxThreshHi = uNewThresh;
  270. data->uProxThreshLow = (unsigned char)(DEFAULT_THRESHOLD_LOW + chTemp);
  271. set_proximity_threshold(data);
  272. ssp_dbg("[SSP]: %s - new prox threshold : hi - %u, lo - %u\n",
  273. __func__, data->uProxThreshHi, data->uProxThreshLow);
  274. return size;
  275. }
  276. static ssize_t barcode_emul_enable_show(struct device *dev,
  277. struct device_attribute *attr, char *buf)
  278. {
  279. struct ssp_data *data = dev_get_drvdata(dev);
  280. return snprintf(buf, PAGE_SIZE, "%u\n", data->bBarcodeEnabled);
  281. }
  282. static ssize_t barcode_emul_enable_store(struct device *dev,
  283. struct device_attribute *attr, const char *buf, size_t size)
  284. {
  285. int iRet;
  286. int64_t dEnable;
  287. struct ssp_data *data = dev_get_drvdata(dev);
  288. iRet = kstrtoll(buf, 10, &dEnable);
  289. if (iRet < 0)
  290. return iRet;
  291. if (dEnable)
  292. set_proximity_barcode_enable(data, true);
  293. else
  294. set_proximity_barcode_enable(data, false);
  295. return size;
  296. }
  297. static DEVICE_ATTR(vendor, S_IRUGO, prox_vendor_show, NULL);
  298. static DEVICE_ATTR(name, S_IRUGO, prox_name_show, NULL);
  299. static DEVICE_ATTR(state, S_IRUGO, proximity_state_show, NULL);
  300. static DEVICE_ATTR(barcode_emul_en, S_IRUGO | S_IWUSR | S_IWGRP,
  301. barcode_emul_enable_show, barcode_emul_enable_store);
  302. static DEVICE_ATTR(prox_avg, S_IRUGO | S_IWUSR | S_IWGRP,
  303. proximity_avg_show, proximity_avg_store);
  304. static DEVICE_ATTR(prox_cal, S_IRUGO | S_IWUSR | S_IWGRP,
  305. proximity_cancel_show, proximity_cancel_store);
  306. static DEVICE_ATTR(prox_thresh, S_IRUGO | S_IWUSR | S_IWGRP,
  307. proximity_thresh_show, proximity_thresh_store);
  308. static struct device_attribute *prox_attrs[] = {
  309. &dev_attr_vendor,
  310. &dev_attr_name,
  311. &dev_attr_state,
  312. &dev_attr_prox_avg,
  313. &dev_attr_prox_cal,
  314. &dev_attr_prox_thresh,
  315. &dev_attr_barcode_emul_en,
  316. NULL,
  317. };
  318. void initialize_prox_factorytest(struct ssp_data *data)
  319. {
  320. sensors_register(data->prox_device, data,
  321. prox_attrs, "proximity_sensor");
  322. }
  323. void remove_prox_factorytest(struct ssp_data *data)
  324. {
  325. sensors_unregister(data->prox_device, prox_attrs);
  326. }