input_booster.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. /*
  2. * input_booster.c - touch booster driver
  3. *
  4. * Copyright (C) 2014 Samsung Electronics
  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 version 2 as
  8. * published by the Free Software Foundation.
  9. *
  10. */
  11. #include <linux/module.h>
  12. #include <linux/input/input_booster.h>
  13. static void input_booster_change_dvfs_tsp_work(struct work_struct *work)
  14. {
  15. int retval = 0;
  16. struct input_booster *booster =
  17. container_of(work,
  18. struct input_booster, work_dvfs_chg.work);
  19. mutex_lock(&booster->dvfs_lock);
  20. switch (booster->dvfs_boost_mode) {
  21. case DVFS_STAGE_SINGLE:
  22. case DVFS_STAGE_TRIPLE:
  23. case DVFS_STAGE_PENTA:
  24. retval = set_freq_limit(DVFS_TOUCH_ID, -1);
  25. booster->dvfs_freq = -1;
  26. break;
  27. case DVFS_STAGE_DUAL:
  28. retval = set_freq_limit(DVFS_TOUCH_ID,
  29. MIN_TOUCH_LIMIT_SECOND);
  30. booster->dvfs_freq = MIN_TOUCH_LIMIT_SECOND;
  31. break;
  32. case DVFS_STAGE_NINTH:
  33. retval = set_freq_limit(DVFS_TOUCH_ID,
  34. MIN_TOUCH_LIMIT);
  35. booster->dvfs_freq = MIN_TOUCH_LIMIT;
  36. break;
  37. }
  38. if (retval < 0)
  39. pr_err("%s: booster change failed(%d).\n",
  40. __func__, retval);
  41. mutex_unlock(&booster->dvfs_lock);
  42. }
  43. static void input_booster_set_dvfs_tsp_lock(struct input_booster *booster, int on)
  44. {
  45. int retval = 0;
  46. if (booster->dvfs_boost_mode == DVFS_STAGE_NONE) {
  47. pr_debug("%s: DVFS stage is none(%d)\n",
  48. __func__, booster->dvfs_boost_mode);
  49. return;
  50. }
  51. mutex_lock(&booster->dvfs_lock);
  52. if (on == 0) {
  53. if (booster->dvfs_lock_status) {
  54. switch (booster->dvfs_boost_mode) {
  55. case DVFS_STAGE_SINGLE:
  56. case DVFS_STAGE_DUAL:
  57. case DVFS_STAGE_TRIPLE:
  58. case DVFS_STAGE_PENTA:
  59. schedule_delayed_work(&booster->work_dvfs_off,
  60. msecs_to_jiffies(INPUT_BOOSTER_OFF_TIME_TSP));
  61. break;
  62. case DVFS_STAGE_NINTH:
  63. schedule_delayed_work(&booster->work_dvfs_off,
  64. msecs_to_jiffies(INPUT_BOOSTER_HIGH_OFF_TIME_TSP));
  65. break;
  66. }
  67. }
  68. } else if (on > 0) {
  69. cancel_delayed_work(&booster->work_dvfs_off);
  70. if ((!booster->dvfs_lock_status) || (booster->dvfs_old_stauts < on)) {
  71. cancel_delayed_work(&booster->work_dvfs_chg);
  72. switch (booster->dvfs_boost_mode) {
  73. case DVFS_STAGE_SINGLE:
  74. case DVFS_STAGE_DUAL:
  75. if (booster->dvfs_freq != MIN_TOUCH_LIMIT) {
  76. retval = set_freq_limit(DVFS_TOUCH_ID,
  77. MIN_TOUCH_LIMIT);
  78. booster->dvfs_freq = MIN_TOUCH_LIMIT;
  79. }
  80. schedule_delayed_work(&booster->work_dvfs_chg,
  81. msecs_to_jiffies(INPUT_BOOSTER_CHG_TIME_TSP));
  82. break;
  83. case DVFS_STAGE_TRIPLE:
  84. if (booster->dvfs_freq != MIN_TOUCH_LIMIT_SECOND) {
  85. retval = set_freq_limit(DVFS_TOUCH_ID,
  86. MIN_TOUCH_LIMIT_SECOND);
  87. booster->dvfs_freq = MIN_TOUCH_LIMIT_SECOND;
  88. }
  89. schedule_delayed_work(&booster->work_dvfs_chg,
  90. msecs_to_jiffies(INPUT_BOOSTER_CHG_TIME_TSP));
  91. break;
  92. case DVFS_STAGE_PENTA:
  93. if (booster->dvfs_freq != MIN_TOUCH_LOW_LIMIT) {
  94. retval = set_freq_limit(DVFS_TOUCH_ID,
  95. MIN_TOUCH_LOW_LIMIT);
  96. booster->dvfs_freq = MIN_TOUCH_LOW_LIMIT;
  97. }
  98. schedule_delayed_work(&booster->work_dvfs_chg,
  99. msecs_to_jiffies(INPUT_BOOSTER_CHG_TIME_TSP));
  100. break;
  101. case DVFS_STAGE_NINTH:
  102. if (booster->dvfs_freq != MIN_TOUCH_HIGH_LIMIT) {
  103. retval = set_freq_limit(DVFS_TOUCH_ID,
  104. MIN_TOUCH_HIGH_LIMIT);
  105. booster->dvfs_freq = MIN_TOUCH_HIGH_LIMIT;
  106. }
  107. schedule_delayed_work(&booster->work_dvfs_chg,
  108. msecs_to_jiffies(INPUT_BOOSTER_HIGH_CHG_TIME_TSP));
  109. break;
  110. }
  111. if (retval < 0)
  112. pr_err("%s: cpu first lock failed(%d)\n",
  113. __func__, retval);
  114. booster->dvfs_lock_status = true;
  115. }
  116. } else if (on < 0) {
  117. if (booster->dvfs_lock_status) {
  118. cancel_delayed_work(&booster->work_dvfs_off);
  119. cancel_delayed_work(&booster->work_dvfs_chg);
  120. schedule_work(&booster->work_dvfs_off.work);
  121. }
  122. }
  123. booster->dvfs_old_stauts = on;
  124. mutex_unlock(&booster->dvfs_lock);
  125. }
  126. static void input_booster_change_dvfs_tkey_work(struct work_struct *work)
  127. {
  128. int retval = 0;
  129. struct input_booster *booster =
  130. container_of(work,
  131. struct input_booster, work_dvfs_chg.work);
  132. mutex_lock(&booster->dvfs_lock);
  133. retval = set_freq_limit(DVFS_TOUCH_ID, booster->dvfs_freq);
  134. if (retval < 0)
  135. pr_info("%s: booster change failed(%d).\n",
  136. __func__, retval);
  137. booster->dvfs_lock_status = false;
  138. mutex_unlock(&booster->dvfs_lock);
  139. }
  140. static void input_booster_set_dvfs_tkey_lock(struct input_booster *booster, int on)
  141. {
  142. int retval = 0;
  143. if (booster->dvfs_boost_mode == DVFS_STAGE_NONE) {
  144. pr_debug("%s: DVFS stage is none(%d)\n",
  145. __func__, booster->dvfs_boost_mode);
  146. return;
  147. }
  148. mutex_lock(&booster->dvfs_lock);
  149. if (on == 0) {
  150. cancel_delayed_work(&booster->work_dvfs_chg);
  151. if (booster->dvfs_lock_status) {
  152. retval = set_freq_limit(DVFS_TOUCH_ID, booster->dvfs_freq);
  153. if (retval < 0)
  154. pr_info("%s: cpu first lock failed(%d)\n", __func__, retval);
  155. booster->dvfs_lock_status = false;
  156. }
  157. schedule_delayed_work(&booster->work_dvfs_off,
  158. msecs_to_jiffies(INPUT_BOOSTER_CHG_TIME_TKEY));
  159. } else if (on == 1) {
  160. cancel_delayed_work(&booster->work_dvfs_off);
  161. schedule_delayed_work(&booster->work_dvfs_chg,
  162. msecs_to_jiffies(INPUT_BOOSTER_OFF_TIME_TKEY));
  163. } else if (on == 2) {
  164. if (booster->dvfs_lock_status) {
  165. cancel_delayed_work(&booster->work_dvfs_off);
  166. cancel_delayed_work(&booster->work_dvfs_chg);
  167. schedule_work(&booster->work_dvfs_off.work);
  168. }
  169. }
  170. mutex_unlock(&booster->dvfs_lock);
  171. }
  172. static void input_booster_change_dvfs_wacom_work(struct work_struct *work)
  173. {
  174. int retval = 0;
  175. struct input_booster *booster =
  176. container_of(work,
  177. struct input_booster, work_dvfs_chg.work);
  178. mutex_lock(&booster->dvfs_lock);
  179. switch (booster->dvfs_boost_mode) {
  180. case DVFS_STAGE_SINGLE:
  181. case DVFS_STAGE_TRIPLE:
  182. retval = set_freq_limit(DVFS_TOUCH_ID, -1);
  183. booster->dvfs_freq = -1;
  184. break;
  185. case DVFS_STAGE_DUAL:
  186. retval = set_freq_limit(DVFS_TOUCH_ID,
  187. MIN_TOUCH_LIMIT_SECOND);
  188. booster->dvfs_freq = MIN_TOUCH_LIMIT_SECOND;
  189. break;
  190. }
  191. if (retval < 0)
  192. pr_info("%s: booster change failed(%d).\n",
  193. __func__, retval);
  194. mutex_unlock(&booster->dvfs_lock);
  195. }
  196. static void input_booster_set_dvfs_wacom_lock(struct input_booster *booster, int on)
  197. {
  198. int retval = 0;
  199. if (booster->dvfs_boost_mode == DVFS_STAGE_NONE) {
  200. pr_debug("%s: DVFS stage is none(%d)\n",
  201. __func__, booster->dvfs_boost_mode);
  202. return;
  203. }
  204. mutex_lock(&booster->dvfs_lock);
  205. if (on == 0) {
  206. if (booster->dvfs_lock_status) {
  207. schedule_delayed_work(&booster->work_dvfs_off,
  208. msecs_to_jiffies(INPUT_BOOSTER_OFF_TIME_WACOM));
  209. }
  210. } else if (on > 0) {
  211. cancel_delayed_work(&booster->work_dvfs_off);
  212. if (!booster->dvfs_lock_status || booster->dvfs_old_stauts < on) {
  213. cancel_delayed_work(&booster->work_dvfs_chg);
  214. switch (booster->dvfs_boost_mode) {
  215. case DVFS_STAGE_SINGLE:
  216. case DVFS_STAGE_DUAL:
  217. if (booster->dvfs_freq != MIN_TOUCH_LIMIT) {
  218. retval = set_freq_limit(DVFS_TOUCH_ID,
  219. MIN_TOUCH_LIMIT);
  220. booster->dvfs_freq = MIN_TOUCH_LIMIT;
  221. }
  222. schedule_delayed_work(&booster->work_dvfs_chg,
  223. msecs_to_jiffies(INPUT_BOOSTER_CHG_TIME_WACOM));
  224. break;
  225. case DVFS_STAGE_TRIPLE:
  226. if (booster->dvfs_freq != MIN_TOUCH_LIMIT_SECOND) {
  227. retval = set_freq_limit(DVFS_TOUCH_ID,
  228. MIN_TOUCH_LIMIT_SECOND);
  229. booster->dvfs_freq = MIN_TOUCH_LIMIT_SECOND;
  230. }
  231. schedule_delayed_work(&booster->work_dvfs_chg,
  232. msecs_to_jiffies(INPUT_BOOSTER_CHG_TIME_WACOM));
  233. break;
  234. }
  235. if (retval < 0)
  236. pr_info("%s: cpu first lock failed(%d)\n",
  237. __func__, retval);
  238. schedule_delayed_work(&booster->work_dvfs_chg,
  239. msecs_to_jiffies(INPUT_BOOSTER_CHG_TIME_WACOM));
  240. booster->dvfs_lock_status = true;
  241. }
  242. } else if (on < 0) {
  243. if (booster->dvfs_lock_status) {
  244. cancel_delayed_work(&booster->work_dvfs_off);
  245. cancel_delayed_work(&booster->work_dvfs_chg);
  246. schedule_work(&booster->work_dvfs_off.work);
  247. }
  248. }
  249. booster->dvfs_old_stauts = on;
  250. mutex_unlock(&booster->dvfs_lock);
  251. }
  252. static int input_booster_set_dvfs_off(struct input_booster *booster)
  253. {
  254. int retval;
  255. mutex_lock(&booster->dvfs_lock);
  256. retval = set_freq_limit(DVFS_TOUCH_ID, -1);
  257. if (retval < 0)
  258. pr_err("%s: booster stop failed(%d).\n",
  259. __func__, retval);
  260. if (booster->dvfs_id == INPUT_BOOSTER_ID_TKEY) {
  261. if (retval < 0)
  262. booster->dvfs_lock_status = false;
  263. else
  264. booster->dvfs_lock_status = true;
  265. } else {
  266. booster->dvfs_freq = -1;
  267. booster->dvfs_lock_status = false;
  268. }
  269. mutex_unlock(&booster->dvfs_lock);
  270. return retval;
  271. }
  272. static void input_booster_off_dvfs_work(struct work_struct *work)
  273. {
  274. struct input_booster *booster =
  275. container_of(work,
  276. struct input_booster, work_dvfs_off.work);
  277. input_booster_set_dvfs_off(booster);
  278. }
  279. void input_booster_init_dvfs(struct input_booster *booster, int id)
  280. {
  281. booster->dvfs_id = id;
  282. mutex_init(&booster->dvfs_lock);
  283. switch (booster->dvfs_id) {
  284. case INPUT_BOOSTER_ID_TSP:
  285. booster->dvfs_set = input_booster_set_dvfs_tsp_lock;
  286. INIT_DELAYED_WORK(&booster->work_dvfs_chg,
  287. input_booster_change_dvfs_tsp_work);
  288. booster->dvfs_stage = DVFS_TSP_STAGE;
  289. break;
  290. case INPUT_BOOSTER_ID_TKEY:
  291. booster->dvfs_set = input_booster_set_dvfs_tkey_lock;
  292. INIT_DELAYED_WORK(&booster->work_dvfs_chg,
  293. input_booster_change_dvfs_tkey_work);
  294. booster->dvfs_stage = DVFS_TKEY_STAGE;
  295. break;
  296. case INPUT_BOOSTER_ID_WACOM:
  297. booster->dvfs_set = input_booster_set_dvfs_wacom_lock;
  298. INIT_DELAYED_WORK(&booster->work_dvfs_chg,
  299. input_booster_change_dvfs_wacom_work);
  300. booster->dvfs_stage = DVFS_WACOM_STAGE;
  301. break;
  302. default:
  303. booster->dvfs_off = NULL;
  304. booster->dvfs_set = NULL;
  305. pr_err("%s: Booster ID is not defined\n", __func__);
  306. return;
  307. }
  308. booster->dvfs_off = input_booster_set_dvfs_off;
  309. INIT_DELAYED_WORK(&booster->work_dvfs_off, input_booster_off_dvfs_work);
  310. if(booster->dvfs_stage & DVFS_STAGE_DUAL)
  311. booster->dvfs_boost_mode = DVFS_STAGE_DUAL;
  312. else
  313. booster->dvfs_boost_mode = DVFS_STAGE_NONE;
  314. if (booster->dvfs_id == INPUT_BOOSTER_ID_TKEY) {
  315. booster->dvfs_freq = MIN_TOUCH_LIMIT_SECOND;
  316. booster->dvfs_lock_status = true;
  317. } else {
  318. booster->dvfs_lock_status = false;
  319. }
  320. pr_err("%s: booster stage: 0x%04x\n", __func__, booster->dvfs_stage);
  321. }
  322. MODULE_DESCRIPTION("Input device[Touch, Touchkey, Hardkey] booster");
  323. MODULE_LICENSE("GPL");