flicker_test.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. /*
  2. * Copyright (C) 2021 Samsung Electronics Co., Ltd. All rights reserved.
  3. *
  4. * This software is licensed under the terms of the GNU General Public
  5. * License, as published by the Free Software Foundation, and
  6. * may be copied, distributed, and modified under those terms.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include "flicker_test.h"
  17. static struct test_data *data = NULL;
  18. static struct result_data *test_result = NULL;
  19. static void (*err_handler)(void);
  20. void als_eol_set_err_handler(void (*handler)(void)){
  21. err_handler = handler;
  22. }
  23. EXPORT_SYMBOL_GPL(als_eol_set_err_handler);
  24. /**
  25. * als_eol_update_als - Record every test value
  26. *
  27. * @awb : current 'awb' value
  28. * (You can use any value as you need. Maybe Infrared value will be used in most cases)
  29. * @clear : current clear value detected by sensor. It means visible light in light spectrum
  30. * @wideband : current Wideband value detected by sensor.
  31. * wideband light include visible light and infrared.
  32. *
  33. */
  34. void als_eol_update_als(int awb, int clear, int wideband, int uv)
  35. {
  36. if (data->eol_enable && data->eol_count >= EOL_SKIP_COUNT) {
  37. data->eol_awb += awb;
  38. data->eol_clear += clear;
  39. data->eol_wideband += wideband;
  40. data->eol_uv += uv;
  41. data->eol_sum_count++;
  42. }
  43. if (data->eol_enable && data->eol_state < EOL_STATE_DONE) {
  44. switch (data->eol_state) {
  45. case EOL_STATE_INIT:
  46. memset(test_result, 0, sizeof(struct result_data));
  47. data->eol_count = 0;
  48. data->eol_sum_count = 0;
  49. data->eol_awb = 0;
  50. data->eol_clear = 0;
  51. data->eol_wideband = 0;
  52. data->eol_flicker = 0;
  53. data->eol_flicker_sum = 0;
  54. data->eol_flicker_sum_count = 0;
  55. data->eol_flicker_count = 0;
  56. data->eol_flicker_skip_count = EOL_FLICKER_SKIP_COUNT;
  57. data->eol_state = EOL_STATE_100;
  58. data->eol_pulse_count = 0;
  59. data->eol_uv = 0;
  60. break;
  61. default:
  62. data->eol_count++;
  63. printk(KERN_INFO"%s - eol_state:%d, eol_cnt:%d (sum_cnt:%d), flk:%d (flk_cnt:%d, sum_cnt:%d), ir:%d, clear:%d, wide:%d, uv:%d\n", __func__,
  64. data->eol_state, data->eol_count, data->eol_sum_count, data->eol_flicker, data->eol_flicker_count, data->eol_flicker_sum_count, awb, clear, wideband, uv);
  65. if ((data->eol_count >= (EOL_COUNT + EOL_SKIP_COUNT)) && (data->eol_flicker_count >= (EOL_COUNT + data->eol_flicker_skip_count))) {
  66. if (data->eol_flicker_sum_count) {
  67. test_result->flicker[data->eol_state] = data->eol_flicker_sum / data->eol_flicker_sum_count;
  68. } else {
  69. test_result->flicker[data->eol_state] = data->eol_flicker;
  70. }
  71. if (data->eol_sum_count) {
  72. test_result->awb[data->eol_state] = data->eol_awb / data->eol_sum_count;
  73. test_result->clear[data->eol_state] = data->eol_clear / data->eol_sum_count;
  74. test_result->wideband[data->eol_state] = data->eol_wideband / data->eol_sum_count;
  75. test_result->uv[data->eol_state] = data->eol_uv / data->eol_sum_count;
  76. } else {
  77. test_result->awb[data->eol_state] = awb;
  78. test_result->clear[data->eol_state] = clear;
  79. test_result->wideband[data->eol_state] = wideband;
  80. test_result->uv[data->eol_state] = uv;
  81. }
  82. printk(KERN_INFO"%s - eol_state = %d, pulse_count = %d, flicker_result = %d Hz (%d/%d)\n",
  83. __func__, data->eol_state, data->eol_pulse_count, test_result->flicker[data->eol_state], data->eol_flicker_sum, data->eol_flicker_sum_count);
  84. data->eol_count = 0;
  85. data->eol_sum_count = 0;
  86. data->eol_awb = 0;
  87. data->eol_clear = 0;
  88. data->eol_wideband = 0;
  89. data->eol_flicker = 0;
  90. data->eol_flicker_sum = 0;
  91. data->eol_flicker_sum_count = 0;
  92. data->eol_flicker_count = 0;
  93. data->eol_pulse_count = 0;
  94. data->eol_uv = 0;
  95. data->eol_state++;
  96. }
  97. break;
  98. }
  99. }
  100. }
  101. EXPORT_SYMBOL_GPL(als_eol_update_als);
  102. /**
  103. * als_eol_update_flicker - Record every test value
  104. *
  105. * @flicker: current Flicker value detected by sensor.
  106. */
  107. void als_eol_update_flicker(int Hz)
  108. {
  109. data->eol_flicker_count++;
  110. data->eol_flicker = Hz;
  111. if ((data->eol_flicker_skip_count < EOL_SKIP_COUNT) && (data->eol_flicker_count >= data->eol_count)) {
  112. data->eol_flicker_skip_count = EOL_SKIP_COUNT;
  113. }
  114. if ((data->eol_enable && Hz != 0) && (data->eol_flicker_count > data->eol_flicker_skip_count)) {
  115. data->eol_flicker_sum += Hz;
  116. data->eol_flicker_sum_count++;
  117. }
  118. }
  119. EXPORT_SYMBOL_GPL(als_eol_update_flicker);
  120. void set_led_mode(int led_curr)
  121. {
  122. #if IS_ENABLED (CONFIG_LEDS_S2MPB02)
  123. s2mpb02_led_en(led_mode, led_curr, S2MPB02_LED_TURN_WAY_GPIO);
  124. #elif IS_ENABLED(CONFIG_LEDS_KTD2692)
  125. ktd2692_led_mode_ctrl(led_mode, led_curr);
  126. #elif IS_ENABLED(CONFIG_LEDS_AW36518_FLASH)
  127. if (led_curr)
  128. aw36518_enable_flicker(led_curr, true);
  129. else
  130. aw36518_enable_flicker(0, false);
  131. #elif IS_ENABLED(CONFIG_LEDS_QTI_FLASH) && (IS_ENABLED(CONFIG_SENSORS_STK6D2X) || IS_ENABLED(CONFIG_SENSORS_TSL2511))
  132. if(led_curr) {
  133. qti_flash_led_set_strobe_sel(switch3_trigger, 1);
  134. led_trigger_event(torch2_trigger, led_curr/2);
  135. led_trigger_event(torch3_trigger, led_curr/2);
  136. led_trigger_event(switch3_trigger, 1);
  137. } else {
  138. qti_flash_led_set_strobe_sel(switch3_trigger, 0);
  139. led_trigger_event(switch3_trigger, 0);
  140. }
  141. #endif
  142. }
  143. void als_eol_set_env(bool torch, int intensity)
  144. {
  145. #if IS_ENABLED(CONFIG_LEDS_S2MPB02)
  146. led_curr = (intensity/20);
  147. led_mode = S2MPB02_TORCH_LED_1;
  148. #elif IS_ENABLED(CONFIG_LEDS_KTD2692)
  149. led_curr = 1400;
  150. led_mode = KTD2692_FLICKER_FLASH_MODE;
  151. #elif IS_ENABLED(CONFIG_LEDS_AW36518_FLASH)
  152. led_curr = intensity;
  153. #elif IS_ENABLED(CONFIG_LEDS_QTI_FLASH)
  154. led_curr = intensity;
  155. #endif
  156. printk(KERN_INFO "%s - gpio:%d intensity:%d(%d) led_mode:%d",
  157. __func__, gpio_torch, intensity, led_curr, led_mode);
  158. }
  159. EXPORT_SYMBOL_GPL(als_eol_set_env);
  160. /**
  161. * als_eol_mode - start LED flicker loop
  162. *
  163. * Return result_data
  164. * MUST call als_eol_update* functions to notify the sensor output!!
  165. */
  166. struct result_data* als_eol_mode(void)
  167. {
  168. int pulse_duty = 0;
  169. int curr_state = EOL_STATE_INIT;
  170. int ret = 0;
  171. u32 prev_eol_count = 0, loop_count = 0;
  172. set_led_mode(0);
  173. ret = gpio_request(gpio_torch, NULL);
  174. if (ret < 0)
  175. return NULL;
  176. data->eol_state = EOL_STATE_INIT;
  177. data->eol_enable = 1;
  178. printk(KERN_INFO"%s - eol_loop start", __func__);
  179. while (data->eol_state < EOL_STATE_DONE) {
  180. if (prev_eol_count == data->eol_count)
  181. loop_count++;
  182. else
  183. loop_count = 0;
  184. prev_eol_count = data->eol_count;
  185. switch (data->eol_state) {
  186. case EOL_STATE_INIT:
  187. pulse_duty = 1000;
  188. break;
  189. case EOL_STATE_100:
  190. pulse_duty = DEFAULT_DUTY_50HZ;
  191. break;
  192. case EOL_STATE_120:
  193. pulse_duty = DEFAULT_DUTY_60HZ;
  194. break;
  195. default:
  196. break;
  197. }
  198. if (data->eol_state >= EOL_STATE_100) {
  199. if (curr_state != data->eol_state) {
  200. #if IS_ENABLED(CONFIG_LEDS_KTD2692) || IS_ENABLED(CONFIG_LEDS_AW36518_FLASH)
  201. if(ret >= 0) {
  202. gpio_free(gpio_torch);
  203. }
  204. #endif
  205. set_led_mode(led_curr);
  206. curr_state = data->eol_state;
  207. #if IS_ENABLED(CONFIG_LEDS_KTD2692) || IS_ENABLED(CONFIG_LEDS_AW36518_FLASH)
  208. ret = gpio_request(gpio_torch, NULL);
  209. if (ret < 0)
  210. break;
  211. #endif
  212. } else {
  213. gpio_direction_output(gpio_torch, 1);
  214. udelay(pulse_duty);
  215. gpio_direction_output(gpio_torch, 0);
  216. data->eol_pulse_count++;
  217. }
  218. }
  219. if (loop_count > 1000) {
  220. printk(KERN_ERR "%s - ERR NO Interrupt", __func__);
  221. // Add Debug Code
  222. if (err_handler)
  223. err_handler();
  224. break;
  225. }
  226. udelay(pulse_duty);
  227. }
  228. printk(KERN_INFO"%s - eol_loop end",__func__);
  229. if(ret >= 0) {
  230. gpio_free(gpio_torch);
  231. }
  232. set_led_mode(0);
  233. if (data->eol_state >= EOL_STATE_DONE) {
  234. if(test_result->clear[EOL_STATE_100] != 0) {
  235. test_result->ratio[EOL_STATE_100] = test_result->awb[EOL_STATE_100] * 100 / test_result->clear[EOL_STATE_100];
  236. }
  237. if(test_result->clear[EOL_STATE_120] != 0) {
  238. test_result->ratio[EOL_STATE_120] = test_result->awb[EOL_STATE_120] * 100 / test_result->clear[EOL_STATE_120];
  239. }
  240. } else {
  241. printk(KERN_ERR "%s - abnormal termination\n", __func__);
  242. }
  243. printk(KERN_INFO "%s - RESULT: flicker:%d|%d awb:%d|%d clear:%d|%d wide:%d|%d ratio:%d|%d uv:%d|%d", __func__,
  244. test_result->flicker[EOL_STATE_100], test_result->flicker[EOL_STATE_120],
  245. test_result->awb[EOL_STATE_100], test_result->awb[EOL_STATE_120],
  246. test_result->clear[EOL_STATE_100], test_result->clear[EOL_STATE_120],
  247. test_result->wideband[EOL_STATE_100], test_result->wideband[EOL_STATE_120],
  248. test_result->ratio[EOL_STATE_100], test_result->ratio[EOL_STATE_120],
  249. test_result->uv[EOL_STATE_100], test_result->uv[EOL_STATE_120]);
  250. data->eol_enable = 0;
  251. return test_result;
  252. }
  253. EXPORT_SYMBOL_GPL(als_eol_mode);
  254. int als_eol_parse_dt(void)
  255. {
  256. struct device_node *np;
  257. #if KERNEL_VERSION(6, 2, 0) > LINUX_VERSION_CODE
  258. enum of_gpio_flags flags;
  259. #endif
  260. np = of_find_node_by_name(NULL, LED_DT_NODE_NAME);
  261. if (np == NULL) {
  262. printk(KERN_ERR "%s - Can't find node", __func__);
  263. return -1;
  264. }
  265. #if KERNEL_VERSION(6, 2, 0) <= LINUX_VERSION_CODE
  266. gpio_torch = of_get_named_gpio(np, "flicker_test,torch-gpio", 0);
  267. #else
  268. gpio_torch = of_get_named_gpio_flags(np, "flicker_test,torch-gpio", 0, &flags);
  269. #endif
  270. printk(KERN_INFO "%s - torch : %d", __func__, gpio_torch);
  271. return 0;
  272. }
  273. static int __init als_eol_init(void)
  274. {
  275. int ret = 0;
  276. printk(KERN_INFO "%s - EOL_TEST Module init", __func__);
  277. data = (struct test_data*)kzalloc(sizeof(struct test_data), GFP_KERNEL);
  278. if (data == NULL) {
  279. printk(KERN_INFO "%s - data alloc err", __func__);
  280. return -1;
  281. }
  282. test_result = (struct result_data*)kzalloc(sizeof(struct result_data), GFP_KERNEL);
  283. if (test_result == NULL) {
  284. printk(KERN_INFO "%s - test_result alloc err", __func__);
  285. return -1;
  286. }
  287. ret = als_eol_parse_dt();
  288. if (ret < 0) {
  289. printk(KERN_ERR "%s - dt parse fail!", __func__);
  290. return ret;
  291. }
  292. #if !IS_ENABLED(CONFIG_LEDS_S2MPB02) && !IS_ENABLED(CONFIG_LEDS_KTD2692) && IS_ENABLED(CONFIG_LEDS_QTI_FLASH) \
  293. && (IS_ENABLED(CONFIG_SENSORS_STK6D2X) || IS_ENABLED(CONFIG_SENSORS_TSL2511)) && !IS_ENABLED(CONFIG_LEDS_AW36518_FLASH)
  294. led_trigger_register_simple("torch2_trigger", &torch2_trigger);
  295. led_trigger_register_simple("torch3_trigger", &torch3_trigger);
  296. led_trigger_register_simple("switch3_trigger", &switch3_trigger);
  297. #endif
  298. return ret;
  299. }
  300. static void __exit als_eol_exit(void)
  301. {
  302. printk(KERN_INFO "%s - EOL_TEST Module exit\n", __func__);
  303. #if !IS_ENABLED(CONFIG_LEDS_S2MPB02) && !IS_ENABLED(CONFIG_LEDS_KTD2692) && IS_ENABLED(CONFIG_LEDS_QTI_FLASH) \
  304. && (IS_ENABLED(CONFIG_SENSORS_STK6D2X) || IS_ENABLED(CONFIG_SENSORS_TSL2511)) && !IS_ENABLED(CONFIG_LEDS_AW36518_FLASH)
  305. led_trigger_unregister_simple(torch2_trigger);
  306. led_trigger_unregister_simple(torch3_trigger);
  307. led_trigger_unregister_simple(switch3_trigger);
  308. #endif
  309. if(data) {
  310. kfree(data);
  311. }
  312. if(test_result) {
  313. kfree(test_result);
  314. }
  315. }
  316. module_init(als_eol_init);
  317. module_exit(als_eol_exit);
  318. MODULE_AUTHOR("Samsung Electronics");
  319. MODULE_DESCRIPTION("Flicker Sensor Test Driver");
  320. MODULE_LICENSE("GPL");