wacom_i2c_func.c 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184
  1. /*
  2. * wacom_i2c_func.c - Wacom G5 Digitizer Controller (I2C bus)
  3. *
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. */
  19. #include "wacom.h"
  20. #include "wacom_i2c_func.h"
  21. #include "wacom_i2c_firm.h"
  22. #ifdef WACOM_IMPORT_FW_ALGO
  23. #include "wacom_i2c_coord_table.h"
  24. /* For firmware algorithm */
  25. #define CAL_PITCH 100
  26. #define LATTICE_SIZE_X ((WACOM_MAX_COORD_X / CAL_PITCH)+2)
  27. #define LATTICE_SIZE_Y ((WACOM_MAX_COORD_Y / CAL_PITCH)+2)
  28. #endif
  29. #if !defined(CONFIG_SAMSUNG_PRODUCT_SHIP)
  30. #define CONFIG_SAMSUNG_KERNEL_DEBUG_USER
  31. #endif
  32. #if defined(WACOM_BOOSTER_DVFS)
  33. extern int useing_in_tsp_or_epen;
  34. void wacom_change_dvfs_lock(struct work_struct *work)
  35. {
  36. struct wacom_i2c *info = container_of(work,struct wacom_i2c,work_dvfs_chg.work);
  37. int retval = 0;
  38. mutex_lock(&info->dvfs_lock);
  39. if (info->dvfs_boost_mode == DVFS_STAGE_DUAL) {
  40. if (info->stay_awake) {
  41. dev_info(&info->client->dev, "%s: do fw update, do not change cpu frequency.\n", __func__);
  42. } else {
  43. retval = set_freq_limit(DVFS_TOUCH_ID, MIN_TOUCH_LIMIT_SECOND);
  44. info->dvfs_freq = MIN_TOUCH_LIMIT_SECOND;
  45. }
  46. } else if (info->dvfs_boost_mode == DVFS_STAGE_SINGLE || info->dvfs_boost_mode == DVFS_STAGE_TRIPLE) {
  47. retval = set_freq_limit(DVFS_TOUCH_ID, -1);
  48. info->dvfs_freq = -1;
  49. }
  50. if (retval < 0)
  51. dev_err(&info->client->dev,"%s: booster change failed(%d).\n",__func__, retval);
  52. mutex_unlock(&info->dvfs_lock);
  53. }
  54. void wacom_set_dvfs_off(struct work_struct *work)
  55. {
  56. struct wacom_i2c *info = container_of(work,struct wacom_i2c,work_dvfs_off.work);
  57. int retval;
  58. if (info->stay_awake) {
  59. dev_info(&info->client->dev, "%s: do fw update, do not change cpu frequency.\n", __func__);
  60. } else {
  61. mutex_lock(&info->dvfs_lock);
  62. if((useing_in_tsp_or_epen & 0x02)== 0x02){
  63. useing_in_tsp_or_epen = 0x02;
  64. retval = 0;
  65. }else{
  66. retval = set_freq_limit(DVFS_TOUCH_ID, -1);
  67. useing_in_tsp_or_epen = 0;
  68. }
  69. info->dvfs_freq = -1;
  70. dev_info(&info->client->dev,"%s :set freq -1\n",__func__);
  71. if (retval < 0)dev_err(&info->client->dev,"%s: booster stop failed(%d).\n", __func__, retval);
  72. info->dvfs_lock_status = false;
  73. mutex_unlock(&info->dvfs_lock);
  74. }
  75. }
  76. void wacom_set_dvfs_lock(struct wacom_i2c *info, uint32_t on)
  77. {
  78. int ret = 0;
  79. if (info->dvfs_boost_mode == DVFS_STAGE_NONE) {
  80. dev_dbg(&info->client->dev,"%s: DVFS stage is none(%d)\n", __func__, info->dvfs_boost_mode);
  81. return;
  82. }
  83. mutex_lock(&info->dvfs_lock);
  84. if (on == 0) {
  85. if (info->dvfs_lock_status)
  86. schedule_delayed_work(&info->work_dvfs_off,msecs_to_jiffies(WACOM_BOOSTER_OFF_TIME));
  87. } else if (on > 0) {
  88. cancel_delayed_work(&info->work_dvfs_off);
  89. if ((!info->dvfs_lock_status) || (info->dvfs_old_stauts < on)) {
  90. useing_in_tsp_or_epen = useing_in_tsp_or_epen | 0x1;
  91. if (info->dvfs_boost_mode == DVFS_STAGE_SINGLE){
  92. ret = set_freq_limit(DVFS_TOUCH_ID, MIN_TOUCH_LIMIT_SECOND);
  93. info->dvfs_freq = MIN_TOUCH_LIMIT_SECOND;
  94. if (ret < 0)
  95. dev_err(&info->client->dev,"%s: cpu first lock failed(%d)\n", __func__, ret);
  96. }else {
  97. cancel_delayed_work(&info->work_dvfs_chg);
  98. if (info->dvfs_freq != MIN_TOUCH_LIMIT) {
  99. if (info->dvfs_boost_mode == DVFS_STAGE_TRIPLE)
  100. ret = set_freq_limit(DVFS_TOUCH_ID, MIN_TOUCH_LIMIT_SECOND);
  101. else
  102. ret = set_freq_limit(DVFS_TOUCH_ID, MIN_TOUCH_LIMIT);
  103. info->dvfs_freq = MIN_TOUCH_LIMIT;
  104. if (ret < 0)
  105. dev_err(&info->client->dev,"%s: cpu first lock failed(%d)\n", __func__, ret);
  106. }
  107. schedule_delayed_work(&info->work_dvfs_chg, msecs_to_jiffies(WACOM_BOOSTER_CHG_TIME));
  108. }
  109. info->dvfs_lock_status = true;
  110. }
  111. } else if (on < 0) {
  112. if (info->dvfs_lock_status) {
  113. cancel_delayed_work(&info->work_dvfs_off);
  114. cancel_delayed_work(&info->work_dvfs_chg);
  115. schedule_work(&info->work_dvfs_off.work);
  116. }
  117. }
  118. info->dvfs_old_stauts = on;
  119. mutex_unlock(&info->dvfs_lock);
  120. }
  121. void wacom_init_dvfs(struct wacom_i2c *info)
  122. {
  123. mutex_init(&info->dvfs_lock);
  124. info->dvfs_boost_mode = DVFS_STAGE_SINGLE; // DVFS_STAGE_DUAL;
  125. INIT_DELAYED_WORK(&info->work_dvfs_off, wacom_set_dvfs_off);
  126. INIT_DELAYED_WORK(&info->work_dvfs_chg, wacom_change_dvfs_lock);
  127. info->dvfs_lock_status = false;
  128. }
  129. #elif defined(WACOM_BOOSTER)
  130. #define set_qos(req, pm_qos_class, value) { \
  131. if (pm_qos_request_active(req)) \
  132. pm_qos_update_request(req, value); \
  133. else \
  134. pm_qos_add_request(req, pm_qos_class, value); \
  135. }
  136. #define remove_qos(req) { \
  137. if (pm_qos_request_active(req)) \
  138. pm_qos_remove_request(req); \
  139. }
  140. void wacom_change_dvfs_lock(struct work_struct *work)
  141. {
  142. struct wacom_i2c *wac_i2c =
  143. container_of(work, struct wacom_i2c, dvfs_chg_work.work);
  144. mutex_lock(&wac_i2c->dvfs_lock);
  145. if (wac_i2c->boost_level == WACOM_BOOSTER_LEVEL1 || \
  146. wac_i2c->boost_level == WACOM_BOOSTER_LEVEL3) {
  147. remove_qos(&wac_i2c->cpu_qos);
  148. remove_qos(&wac_i2c->mif_qos);
  149. remove_qos(&wac_i2c->int_qos);
  150. wac_i2c->dvfs_lock_status = false;
  151. printk(KERN_DEBUG"epen:DVFS Off, %d\n", wac_i2c->boost_level);
  152. } else {
  153. set_qos(&wac_i2c->cpu_qos, PM_QOS_KFC_FREQ_MIN, WACOM_BOOSTER_CPU_FREQ2);
  154. set_qos(&wac_i2c->mif_qos, PM_QOS_BUS_THROUGHPUT, WACOM_BOOSTER_MIF_FREQ2);
  155. set_qos(&wac_i2c->int_qos, PM_QOS_DEVICE_THROUGHPUT, WACOM_BOOSTER_INT_FREQ2);
  156. printk(KERN_DEBUG"epen:change_mif_dvfs_lock\n");
  157. }
  158. mutex_unlock(&wac_i2c->dvfs_lock);
  159. }
  160. void wacom_set_dvfs_off(struct work_struct *work)
  161. {
  162. struct wacom_i2c *wac_i2c =
  163. container_of(work,
  164. struct wacom_i2c, dvfs_off_work.work);
  165. mutex_lock(&wac_i2c->dvfs_lock);
  166. remove_qos(&wac_i2c->cpu_qos);
  167. remove_qos(&wac_i2c->mif_qos);
  168. remove_qos(&wac_i2c->int_qos);
  169. wac_i2c->dvfs_lock_status = false;
  170. mutex_unlock(&wac_i2c->dvfs_lock);
  171. printk(KERN_DEBUG"epen:DVFS Off, %d\n", wac_i2c->boost_level);
  172. }
  173. void wacom_set_dvfs_lock(struct wacom_i2c *wac_i2c,
  174. uint32_t on)
  175. {
  176. if (WACOM_BOOSTER_DISABLE == wac_i2c->boost_level)
  177. return;
  178. mutex_lock(&wac_i2c->dvfs_lock);
  179. if (on == 0) {
  180. if (wac_i2c->dvfs_lock_status) {
  181. schedule_delayed_work(&wac_i2c->dvfs_off_work,
  182. msecs_to_jiffies(WACOM_BOOSTER_OFF_TIME));
  183. }
  184. } else if (on == 1) {
  185. cancel_delayed_work(&wac_i2c->dvfs_off_work);
  186. cancel_delayed_work(&wac_i2c->dvfs_chg_work);
  187. if (wac_i2c->boost_level == WACOM_BOOSTER_LEVEL3) {
  188. set_qos(&wac_i2c->cpu_qos, PM_QOS_KFC_FREQ_MIN, WACOM_BOOSTER_CPU_FREQ3);
  189. set_qos(&wac_i2c->mif_qos, PM_QOS_BUS_THROUGHPUT, WACOM_BOOSTER_MIF_FREQ3);
  190. set_qos(&wac_i2c->int_qos, PM_QOS_DEVICE_THROUGHPUT, WACOM_BOOSTER_INT_FREQ3);
  191. } else {
  192. set_qos(&wac_i2c->cpu_qos, PM_QOS_KFC_FREQ_MIN, WACOM_BOOSTER_CPU_FREQ1);
  193. set_qos(&wac_i2c->mif_qos, PM_QOS_BUS_THROUGHPUT, WACOM_BOOSTER_MIF_FREQ1);
  194. set_qos(&wac_i2c->int_qos, PM_QOS_DEVICE_THROUGHPUT, WACOM_BOOSTER_INT_FREQ1);
  195. }
  196. schedule_delayed_work(&wac_i2c->dvfs_chg_work,
  197. msecs_to_jiffies(WACOM_BOOSTER_CHG_TIME));
  198. wac_i2c->dvfs_lock_status = true;
  199. printk(KERN_DEBUG"epen:DVFS On, %d\n", wac_i2c->boost_level);
  200. } else if (on == 2) {
  201. if (wac_i2c->dvfs_lock_status) {
  202. cancel_delayed_work(&wac_i2c->dvfs_off_work);
  203. cancel_delayed_work(&wac_i2c->dvfs_chg_work);
  204. schedule_work(&wac_i2c->dvfs_off_work.work);
  205. }
  206. }
  207. mutex_unlock(&wac_i2c->dvfs_lock);
  208. }
  209. void wacom_init_dvfs(struct wacom_i2c *wac_i2c)
  210. {
  211. mutex_init(&wac_i2c->dvfs_lock);
  212. INIT_DELAYED_WORK(&wac_i2c->dvfs_off_work, wacom_set_dvfs_off);
  213. INIT_DELAYED_WORK(&wac_i2c->dvfs_chg_work, wacom_change_dvfs_lock);
  214. wac_i2c->dvfs_lock_status = false;
  215. }
  216. #endif
  217. void forced_release(struct wacom_i2c *wac_i2c)
  218. {
  219. #if defined(CONFIG_SAMSUNG_KERNEL_DEBUG_USER)
  220. printk(KERN_DEBUG "epen:%s\n", __func__);
  221. #endif
  222. input_report_abs(wac_i2c->input_dev, ABS_X, wac_i2c->last_x);
  223. input_report_abs(wac_i2c->input_dev, ABS_Y, wac_i2c->last_y);
  224. input_report_abs(wac_i2c->input_dev, ABS_PRESSURE, 0);
  225. #ifdef WACOM_USE_GAIN
  226. input_report_abs(wac_i2c->input_dev, ABS_DISTANCE, 0);
  227. #endif
  228. input_report_key(wac_i2c->input_dev, BTN_STYLUS, 0);
  229. input_report_key(wac_i2c->input_dev, BTN_TOUCH, 0);
  230. input_report_key(wac_i2c->input_dev, BTN_TOOL_RUBBER, 0);
  231. input_report_key(wac_i2c->input_dev, BTN_TOOL_PEN, 0);
  232. #ifdef CONFIG_INPUT_BOOSTER
  233. INPUT_BOOSTER_REPORT_KEY_EVENT(wac_i2c->input_dev, KEY_BOOSTER_PEN, 0);
  234. INPUT_BOOSTER_SEND_EVENT(KEY_BOOSTER_PEN, BOOSTER_MODE_FORCE_OFF);
  235. #endif
  236. input_sync(wac_i2c->input_dev);
  237. wac_i2c->last_x = 0;
  238. wac_i2c->last_y = 0;
  239. wac_i2c->pen_prox = 0;
  240. wac_i2c->pen_pressed = 0;
  241. wac_i2c->side_pressed = 0;
  242. /*wac_i2c->pen_pdct = PDCT_NOSIGNAL;*/
  243. #if defined(WACOM_BOOSTER) || defined(WACOM_BOOSTER_DVFS)
  244. if (wac_i2c->last_x == 0 && wac_i2c->last_y == 0)
  245. wacom_set_dvfs_lock(wac_i2c, 0);
  246. #endif
  247. }
  248. #ifdef DISABLE_WACOM_PDCT_WORK_AROUND
  249. void forced_hover(struct wacom_i2c *wac_i2c)
  250. {
  251. /* To distinguish hover and pdct area, release */
  252. if (wac_i2c->last_x != 0 || wac_i2c->last_y != 0) {
  253. printk(KERN_DEBUG "epen:release hover\n");
  254. forced_release(wac_i2c);
  255. }
  256. wac_i2c->rdy_pdct = true;
  257. #if defined(CONFIG_SAMSUNG_KERNEL_DEBUG_USER)
  258. printk(KERN_DEBUG "epen:%s\n", __func__);
  259. #endif
  260. input_report_key(wac_i2c->input_dev, KEY_PEN_PDCT, 1);
  261. input_sync(wac_i2c->input_dev);
  262. }
  263. #endif
  264. int wacom_i2c_send(struct wacom_i2c *wac_i2c,
  265. const char *buf, int count, bool mode)
  266. {
  267. struct i2c_client *client = mode ?
  268. wac_i2c->client_boot : wac_i2c->client;
  269. if (wac_i2c->boot_mode && !mode) {
  270. printk(KERN_DEBUG
  271. "epen:failed to send\n");
  272. return 0;
  273. }
  274. return i2c_master_send(client, buf, count);
  275. }
  276. int wacom_i2c_recv(struct wacom_i2c *wac_i2c,
  277. char *buf, int count, bool mode)
  278. {
  279. struct i2c_client *client = mode ?
  280. wac_i2c->client_boot : wac_i2c->client;
  281. if (wac_i2c->boot_mode && !mode) {
  282. printk(KERN_DEBUG
  283. "epen:failed to send\n");
  284. return 0;
  285. }
  286. return i2c_master_recv(client, buf, count);
  287. }
  288. int wacom_i2c_test(struct wacom_i2c *wac_i2c)
  289. {
  290. int ret, i;
  291. char buf, test[10];
  292. buf = COM_QUERY;
  293. ret = wacom_i2c_send(wac_i2c, &buf, sizeof(buf), false);
  294. if (ret > 0)
  295. printk(KERN_INFO "epen:buf:%d, sent:%d\n", buf, ret);
  296. else {
  297. printk(KERN_ERR "epen:Digitizer is not active\n");
  298. return -1;
  299. }
  300. ret = wacom_i2c_recv(wac_i2c, test, sizeof(test), false);
  301. if (ret >= 0) {
  302. for (i = 0; i < 8; i++)
  303. printk(KERN_INFO "epen:%d\n", test[i]);
  304. } else {
  305. printk(KERN_ERR "epen:Digitizer does not reply\n");
  306. return -1;
  307. }
  308. return 0;
  309. }
  310. int wacom_checksum(struct wacom_i2c *wac_i2c)
  311. {
  312. int ret = 0, retry = 10;
  313. int i = 0;
  314. u8 buf[5] = {0, };
  315. buf[0] = COM_CHECKSUM;
  316. while (retry--) {
  317. ret = wacom_i2c_send(wac_i2c, &buf[0], 1, false);
  318. if (ret < 0) {
  319. printk(KERN_DEBUG
  320. "epen:i2c fail, retry, %d\n",
  321. __LINE__);
  322. continue;
  323. }
  324. msleep(200);
  325. ret = wacom_i2c_recv(wac_i2c, buf, 5, false);
  326. if (ret < 0) {
  327. printk(KERN_DEBUG
  328. "epen:i2c fail, retry, %d\n",
  329. __LINE__);
  330. continue;
  331. } else if (buf[0] == 0x1f)
  332. break;
  333. printk(KERN_DEBUG "epen:checksum retry\n");
  334. }
  335. if (ret >= 0) {
  336. printk(KERN_DEBUG
  337. "epen:received checksum %x, %x, %x, %x, %x\n",
  338. buf[0], buf[1], buf[2], buf[3], buf[4]);
  339. }
  340. for (i = 0; i < 5; ++i) {
  341. if (buf[i] != fw_chksum[i]) {
  342. printk(KERN_DEBUG
  343. "epen:checksum fail %dth %x %x\n", i,
  344. buf[i], fw_chksum[i]);
  345. break;
  346. }
  347. }
  348. wac_i2c->checksum_result = (5 == i);
  349. return ret;
  350. }
  351. int wacom_i2c_query(struct wacom_i2c *wac_i2c)
  352. {
  353. struct wacom_features *wac_feature = wac_i2c->wac_feature;
  354. int ret;
  355. u8 buf;
  356. u8 data[COM_QUERY_NUM] = {0, };
  357. int i = 0;
  358. const int query_limit = 3;
  359. buf = COM_QUERY;
  360. for (i = 0; i < query_limit; i++) {
  361. ret = wacom_i2c_send(wac_i2c, &buf, 1, false);
  362. if (ret < 0) {
  363. printk(KERN_ERR"epen:I2C send failed(%d)\n", ret);
  364. continue;
  365. }
  366. msleep(100);
  367. ret = wacom_i2c_recv(wac_i2c, data, COM_QUERY_NUM, false);
  368. if (ret < 0) {
  369. printk(KERN_ERR"epen:I2C recv failed(%d)\n", ret);
  370. continue;
  371. }
  372. printk(KERN_INFO "epen:%s: %dth ret of wacom query=%d\n",
  373. __func__, i, ret);
  374. if (COM_QUERY_NUM != ret) {
  375. printk(KERN_ERR"epen:failed to read i2c(%d)\n", ret);
  376. continue;
  377. }
  378. if (0x0f == data[0]) {
  379. wac_feature->fw_version =
  380. ((u16) data[7] << 8) + (u16) data[8];
  381. break;
  382. }
  383. printk(KERN_NOTICE
  384. "epen:%X, %X, %X, %X, %X, %X, %X, fw=0x%x\n",
  385. data[0], data[1], data[2], data[3],
  386. data[4], data[5], data[6],
  387. wac_feature->fw_version);
  388. }
  389. #if defined(WACOM_USE_PDATA)
  390. wac_feature->x_max = (u16) WACOM_MAX_COORD_X;
  391. wac_feature->y_max = (u16) WACOM_MAX_COORD_Y;
  392. #else
  393. wac_feature->x_max = ((u16) data[1] << 8) + (u16) data[2];
  394. wac_feature->y_max = ((u16) data[3] << 8) + (u16) data[4];
  395. #endif
  396. wac_feature->pressure_max = (u16) data[6] + ((u16) data[5] << 8);
  397. #if defined(COOR_WORK_AROUND)
  398. if (i == query_limit || ret < 0) {
  399. printk(KERN_NOTICE "epen:COOR_WORK_AROUND is applied\n");
  400. printk(KERN_NOTICE
  401. "epen:%X, %X, %X, %X, %X, %X, %X, %X, %X\n", data[0],
  402. data[1], data[2], data[3], data[4], data[5], data[6],
  403. data[7], data[8]);
  404. wac_feature->x_max = (u16) WACOM_MAX_COORD_X;
  405. wac_feature->y_max = (u16) WACOM_MAX_COORD_Y;
  406. wac_feature->pressure_max = (u16) WACOM_MAX_PRESSURE;
  407. wac_feature->fw_version = 0;
  408. }
  409. #endif
  410. printk(KERN_NOTICE "epen:x_max=0x%X\n", wac_feature->x_max);
  411. printk(KERN_NOTICE "epen:y_max=0x%X\n", wac_feature->y_max);
  412. printk(KERN_NOTICE "epen:pressure_max=0x%X\n",
  413. wac_feature->pressure_max);
  414. printk(KERN_NOTICE "epen:fw_version=0x%X (d7:0x%X,d8:0x%X)\n",
  415. wac_feature->fw_version, data[7], data[8]);
  416. printk(KERN_NOTICE "epen:%X, %X, %X, %X, %X, %X, %X, %X, %X\n",
  417. data[0], data[1], data[2], data[3], data[4], data[5], data[6],
  418. data[7], data[8]);
  419. if ((i == query_limit) && (ret < 0)) {
  420. printk(KERN_DEBUG"epen:%s, failed\n", __func__);
  421. wac_i2c->query_status = false;
  422. return ret;
  423. }
  424. wac_i2c->query_status = true;
  425. return 0;
  426. }
  427. #ifdef WACOM_IMPORT_FW_ALGO
  428. #ifdef WACOM_USE_OFFSET_TABLE
  429. void wacom_i2c_coord_offset(u16 *coordX, u16 *coordY)
  430. {
  431. u16 ix, iy;
  432. u16 dXx_0, dXy_0, dXx_1, dXy_1;
  433. int D0, D1, D2, D3, D;
  434. ix = (u16) (((*coordX)) / CAL_PITCH);
  435. iy = (u16) (((*coordY)) / CAL_PITCH);
  436. dXx_0 = *coordX - (ix * CAL_PITCH);
  437. dXx_1 = CAL_PITCH - dXx_0;
  438. dXy_0 = *coordY - (iy * CAL_PITCH);
  439. dXy_1 = CAL_PITCH - dXy_0;
  440. if (*coordX <= WACOM_MAX_COORD_X) {
  441. D0 = tableX[user_hand][screen_rotate][ix +
  442. (iy * LATTICE_SIZE_X)] *
  443. (dXx_1 + dXy_1);
  444. D1 = tableX[user_hand][screen_rotate][ix + 1 +
  445. iy * LATTICE_SIZE_X] *
  446. (dXx_0 + dXy_1);
  447. D2 = tableX[user_hand][screen_rotate][ix +
  448. (iy +
  449. 1) * LATTICE_SIZE_X] *
  450. (dXx_1 + dXy_0);
  451. D3 = tableX[user_hand][screen_rotate][ix + 1 +
  452. (iy +
  453. 1) * LATTICE_SIZE_X] *
  454. (dXx_0 + dXy_0);
  455. D = (D0 + D1 + D2 + D3) / (4 * CAL_PITCH);
  456. if (((int)*coordX + D) > 0)
  457. *coordX += D;
  458. else
  459. *coordX = 0;
  460. }
  461. if (*coordY <= WACOM_MAX_COORD_Y) {
  462. D0 = tableY[user_hand][screen_rotate][ix +
  463. (iy * LATTICE_SIZE_X)] *
  464. (dXy_1 + dXx_1);
  465. D1 = tableY[user_hand][screen_rotate][ix + 1 +
  466. iy * LATTICE_SIZE_X] *
  467. (dXy_1 + dXx_0);
  468. D2 = tableY[user_hand][screen_rotate][ix +
  469. (iy +
  470. 1) * LATTICE_SIZE_X] *
  471. (dXy_0 + dXx_1);
  472. D3 = tableY[user_hand][screen_rotate][ix + 1 +
  473. (iy +
  474. 1) * LATTICE_SIZE_X] *
  475. (dXy_0 + dXx_0);
  476. D = (D0 + D1 + D2 + D3) / (4 * CAL_PITCH);
  477. if (((int)*coordY + D) > 0)
  478. *coordY += D;
  479. else
  480. *coordY = 0;
  481. }
  482. }
  483. #endif
  484. #ifdef WACOM_USE_AVERAGING
  485. #define STEP 32
  486. void wacom_i2c_coord_average(short *CoordX, short *CoordY,
  487. int bFirstLscan, int aveStrength)
  488. {
  489. unsigned char i;
  490. unsigned int work;
  491. unsigned char ave_step = 4, ave_shift = 2;
  492. static int Sum_X, Sum_Y;
  493. static int AveBuffX[STEP], AveBuffY[STEP];
  494. static unsigned char AvePtr;
  495. static unsigned char bResetted;
  496. #ifdef WACOM_USE_AVE_TRANSITION
  497. static int tmpBuffX[STEP], tmpBuffY[STEP];
  498. static unsigned char last_step, last_shift;
  499. static bool transition;
  500. static int tras_counter;
  501. #endif
  502. if (bFirstLscan == 0) {
  503. bResetted = 0;
  504. #ifdef WACOM_USE_AVE_TRANSITION
  505. transition = false;
  506. tras_counter = 0;
  507. last_step = 4;
  508. last_shift = 2;
  509. #endif
  510. return ;
  511. }
  512. #ifdef WACOM_USE_AVE_TRANSITION
  513. if (bResetted) {
  514. if (transition) {
  515. ave_step = last_step;
  516. ave_shift = last_shift;
  517. } else {
  518. ave_step = 2 << (aveStrength-1);
  519. ave_shift = aveStrength;
  520. }
  521. if (!transition && ave_step != 0 && last_step != 0) {
  522. if (ave_step > last_step) {
  523. transition = true;
  524. tras_counter = ave_step;
  525. /*printk(KERN_DEBUG
  526. "epen:Trans %d to %d\n",
  527. last_step, ave_step);*/
  528. memcpy(tmpBuffX, AveBuffX,
  529. sizeof(unsigned int) * last_step);
  530. memcpy(tmpBuffY, AveBuffY,
  531. sizeof(unsigned int) * last_step);
  532. for (i = 0 ; i < last_step; ++i) {
  533. AveBuffX[i] = tmpBuffX[AvePtr];
  534. AveBuffY[i] = tmpBuffY[AvePtr];
  535. if (++AvePtr >= last_step)
  536. AvePtr = 0;
  537. }
  538. for ( ; i < ave_step; ++i) {
  539. AveBuffX[i] = *CoordX;
  540. AveBuffY[i] = *CoordY;
  541. Sum_X += *CoordX;
  542. Sum_Y += *CoordY;
  543. }
  544. AvePtr = 0;
  545. *CoordX = Sum_X >> ave_shift;
  546. *CoordY = Sum_Y >> ave_shift;
  547. bResetted = 1;
  548. last_step = ave_step;
  549. last_shift = ave_shift;
  550. return ;
  551. } else if (ave_step < last_step) {
  552. transition = true;
  553. tras_counter = ave_step;
  554. /*printk(KERN_DEBUG
  555. "epen:Trans %d to %d\n",
  556. last_step, ave_step);*/
  557. memcpy(tmpBuffX, AveBuffX,
  558. sizeof(unsigned int) * last_step);
  559. memcpy(tmpBuffY, AveBuffY,
  560. sizeof(unsigned int) * last_step);
  561. Sum_X = 0;
  562. Sum_Y = 0;
  563. for (i = 1 ; i <= ave_step; ++i) {
  564. if (AvePtr == 0)
  565. AvePtr = last_step - 1;
  566. else
  567. --AvePtr;
  568. AveBuffX[ave_step-i] = tmpBuffX[AvePtr];
  569. Sum_X = Sum_X + tmpBuffX[AvePtr];
  570. AveBuffY[ave_step-i] = tmpBuffY[AvePtr];
  571. Sum_Y = Sum_Y + tmpBuffY[AvePtr];
  572. }
  573. AvePtr = 0;
  574. bResetted = 1;
  575. *CoordX = Sum_X >> ave_shift;
  576. *CoordY = Sum_Y >> ave_shift;
  577. bResetted = 1;
  578. last_step = ave_step;
  579. last_shift = ave_shift;
  580. return ;
  581. }
  582. }
  583. if (!transition && (last_step != ave_step)) {
  584. last_step = ave_step;
  585. last_shift = ave_shift;
  586. }
  587. }
  588. #endif
  589. if (bFirstLscan && (bResetted == 0)) {
  590. AvePtr = 0;
  591. ave_step = 4;
  592. ave_shift = 2;
  593. #if defined(WACOM_USE_AVE_TRANSITION)
  594. tras_counter = ave_step;
  595. #endif
  596. for (i = 0; i < ave_step; i++) {
  597. AveBuffX[i] = *CoordX;
  598. AveBuffY[i] = *CoordY;
  599. }
  600. Sum_X = (unsigned int)*CoordX << ave_shift;
  601. Sum_Y = (unsigned int)*CoordY << ave_shift;
  602. bResetted = 1;
  603. } else if (bFirstLscan) {
  604. Sum_X = Sum_X - AveBuffX[AvePtr] + (*CoordX);
  605. AveBuffX[AvePtr] = *CoordX;
  606. work = Sum_X >> ave_shift;
  607. *CoordX = (unsigned int)work;
  608. Sum_Y = Sum_Y - AveBuffY[AvePtr] + (*CoordY);
  609. AveBuffY[AvePtr] = (*CoordY);
  610. work = Sum_Y >> ave_shift;
  611. *CoordY = (unsigned int)work;
  612. if (++AvePtr >= ave_step)
  613. AvePtr = 0;
  614. }
  615. #ifdef WACOM_USE_AVE_TRANSITION
  616. if (transition) {
  617. --tras_counter;
  618. if (tras_counter < 0)
  619. transition = false;
  620. }
  621. #endif
  622. }
  623. #endif
  624. #if defined(WACOM_USE_GAIN)
  625. u8 wacom_i2c_coord_level(u16 gain)
  626. {
  627. if (gain >= 0 && gain <= 14)
  628. return 0;
  629. else if (gain > 14 && gain <= 24)
  630. return 1;
  631. else
  632. return 2;
  633. }
  634. #endif
  635. #ifdef WACOM_USE_BOX_FILTER
  636. void boxfilt(short *CoordX, short *CoordY,
  637. int height, int bFirstLscan)
  638. {
  639. bool isMoved = false;
  640. static bool bFirst = true;
  641. static short lastX_loc, lastY_loc;
  642. static unsigned char bResetted;
  643. int threshold = 0;
  644. int distance = 0;
  645. static short bounce;
  646. /*Reset filter*/
  647. if (bFirstLscan == 0) {
  648. bResetted = 0;
  649. return ;
  650. }
  651. if (bFirstLscan && (bResetted == 0)) {
  652. lastX_loc = *CoordX;
  653. lastY_loc = *CoordY;
  654. bResetted = 1;
  655. }
  656. if (bFirst) {
  657. lastX_loc = *CoordX;
  658. lastY_loc = *CoordY;
  659. bFirst = false;
  660. }
  661. /*Start Filtering*/
  662. threshold = 30;
  663. /*X*/
  664. distance = abs(*CoordX - lastX_loc);
  665. if (distance >= threshold)
  666. isMoved = true;
  667. if (isMoved == false) {
  668. distance = abs(*CoordY - lastY_loc);
  669. if (distance >= threshold)
  670. isMoved = true;
  671. }
  672. /*Update position*/
  673. if (isMoved) {
  674. lastX_loc = *CoordX;
  675. lastY_loc = *CoordY;
  676. } else {
  677. *CoordX = lastX_loc + bounce;
  678. *CoordY = lastY_loc;
  679. if (bounce)
  680. bounce = 0;
  681. else
  682. bounce += 5;
  683. }
  684. }
  685. #endif
  686. #if defined(WACOM_USE_AVE_TRANSITION)
  687. int g_aveLevel_C[] = {2, 2, 4, };
  688. int g_aveLevel_X[] = {3, 3, 4, };
  689. int g_aveLevel_Y[] = {3, 3, 4, };
  690. int g_aveLevel_Trs[] = {3, 4, 4, };
  691. int g_aveLevel_Cor[] = {4, 4, 4, };
  692. void ave_level(short CoordX, short CoordY,
  693. int height, int *aveStrength)
  694. {
  695. bool transition = false;
  696. bool edgeY = false, edgeX = false;
  697. bool cY = false, cX = false;
  698. if (CoordY > (WACOM_MAX_COORD_Y - 800))
  699. cY = true;
  700. else if (CoordY < 800)
  701. cY = true;
  702. if (CoordX > (WACOM_MAX_COORD_X - 800))
  703. cX = true;
  704. else if (CoordX < 800)
  705. cX = true;
  706. if (cX && cY) {
  707. *aveStrength = g_aveLevel_Cor[height];
  708. return ;
  709. }
  710. /*Start Filtering*/
  711. if (CoordX > X_INC_E1)
  712. edgeX = true;
  713. else if (CoordX < X_INC_S1)
  714. edgeX = true;
  715. /*Right*/
  716. if (CoordY > Y_INC_E1) {
  717. /*Transition*/
  718. if (CoordY < Y_INC_E3)
  719. transition = true;
  720. else
  721. edgeY = true;
  722. }
  723. /*Left*/
  724. else if (CoordY < Y_INC_S1) {
  725. /*Transition*/
  726. if (CoordY > Y_INC_S3)
  727. transition = true;
  728. else
  729. edgeY = true;
  730. }
  731. if (transition)
  732. *aveStrength = g_aveLevel_Trs[height];
  733. else if (edgeX)
  734. *aveStrength = g_aveLevel_X[height];
  735. else if (edgeY)
  736. *aveStrength = g_aveLevel_Y[height];
  737. else
  738. *aveStrength = g_aveLevel_C[height];
  739. }
  740. #endif
  741. #endif /*WACOM_IMPORT_FW_ALGO*/
  742. static bool wacom_i2c_coord_range(s16 *x, s16 *y)
  743. {
  744. #if defined(CONFIG_MACH_T0)
  745. if ((*x >= 0) && (*y >= 0) &&
  746. (*x <= WACOM_POSX_MAX) && (*y <= WACOM_POSY_MAX - 50))
  747. #elif defined(CONFIG_MACH_V1)
  748. if ((*x <= WACOM_MAX_COORD_X) && (*y <= WACOM_MAX_COORD_Y))
  749. #else
  750. if ((*x >= 0) && (*y >= 0) &&
  751. (*x <= WACOM_POSX_MAX) && (*y <= WACOM_POSY_MAX))
  752. #endif
  753. return true;
  754. return false;
  755. }
  756. #ifdef WACOM_USE_SOFTKEY
  757. static int keycode[] = {
  758. KEY_MENU, KEY_BACK,
  759. };
  760. void wacom_i2c_softkey(struct wacom_i2c *wac_i2c, s16 key, s16 pressed)
  761. {
  762. #if defined(WACOM_BOOSTER) || defined(WACOM_BOOSTER_DVFS)
  763. wacom_set_dvfs_lock(wac_i2c, pressed);
  764. #endif
  765. input_report_key(wac_i2c->input_dev,
  766. keycode[key], pressed);
  767. input_sync(wac_i2c->input_dev);
  768. #if !defined(CONFIG_SAMSUNG_PRODUCT_SHIP)
  769. printk(KERN_DEBUG "epen:keycode:%d pressed:%d\n",
  770. keycode[key], pressed);
  771. #else
  772. printk(KERN_DEBUG "epen:pressed:%d\n",
  773. pressed);
  774. #endif
  775. }
  776. #endif
  777. int wacom_i2c_coord(struct wacom_i2c *wac_i2c)
  778. {
  779. bool prox = false;
  780. int ret = 0;
  781. u8 *data;
  782. int rubber, stylus;
  783. static s16 x, y, pressure;
  784. static s16 tmp;
  785. int rdy = 0;
  786. #if defined(WACOM_USE_GAIN)
  787. u8 gain = 0;
  788. #endif
  789. #ifdef WACOM_USE_AVERAGING
  790. int aveStrength = 2;
  791. #endif
  792. #ifdef WACOM_USE_SOFTKEY
  793. static s16 softkey, pressed, keycode;
  794. #endif
  795. #ifdef LCD_FREQ_SYNC
  796. int lcd_freq = 0;
  797. #endif
  798. data = wac_i2c->wac_feature->data;
  799. ret = wacom_i2c_recv(wac_i2c, data, COM_COORD_NUM, false);
  800. if (ret < 0) {
  801. printk(KERN_ERR "epen:%s failed to read i2c.L%d\n", __func__,
  802. __LINE__);
  803. return -1;
  804. }
  805. #if defined(CONFIG_SAMSUNG_KERNEL_DEBUG_USER)
  806. #if defined(CONFIG_MACH_T0)
  807. /*printk(KERN_DEBUG"epen:%x, %x, %x, %x, %x, %x, %x %x\n",
  808. data[0], data[1], data[2], data[3],
  809. data[4], data[5], data[6], data[7]);*/
  810. #else
  811. /*printk(KERN_DEBUG"epen:%x, %x, %x, %x, %x, %x, %x %x %x %x %x %x\n",
  812. data[0], data[1], data[2], data[3], data[4], data[5], data[6],
  813. data[7], data[8], data[9], data[10], data[11]);*/
  814. #endif
  815. #endif
  816. #ifdef LCD_FREQ_SYNC
  817. if (likely(wac_i2c->use_lcd_freq_sync)) {
  818. if (unlikely(!wac_i2c->pen_prox)) {
  819. if (wac_i2c->lcd_freq_wait == false) {
  820. lcd_freq = ((u16) data[10] << 8) + (u16) data[11];
  821. ++lcd_freq;
  822. wac_i2c->lcd_freq = 2000000000 / lcd_freq;
  823. if (wac_i2c->lcd_freq < LCD_FREQ_BOTTOM || wac_i2c->lcd_freq > LCD_FREQ_TOP) {
  824. wac_i2c->lcd_freq_wait = true;
  825. schedule_work(&wac_i2c->lcd_freq_work);
  826. }
  827. }
  828. }
  829. }
  830. #endif
  831. if (data[0] & 0x80) {
  832. #ifdef WACOM_USE_SOFTKEY
  833. softkey = !!(data[5] & 0x80);
  834. if (softkey) {
  835. if (unlikely(wac_i2c->pen_prox))
  836. forced_release(wac_i2c);
  837. pressed = !!(data[5] & 0x40);
  838. keycode = (data[5] & 0x30) >> 4;
  839. #ifdef WACOM_USE_SOFTKEY_BLOCK
  840. if (wac_i2c->block_softkey && pressed) {
  841. cancel_delayed_work_sync(&wac_i2c->softkey_block_work);
  842. printk(KERN_DEBUG"epen:block p\n");
  843. return 0;
  844. } else if (wac_i2c->block_softkey && !pressed) {
  845. printk(KERN_DEBUG"epen:block r\n");
  846. wac_i2c->block_softkey = false;
  847. return 0;
  848. }
  849. #endif
  850. wacom_i2c_softkey(wac_i2c, keycode, pressed);
  851. return 0;
  852. }
  853. #endif
  854. /* enable emr device */
  855. if (!wac_i2c->pen_prox) {
  856. #if defined(WACOM_PDCT_WORK_AROUND)
  857. if (unlikely(wac_i2c->pen_pdct == PDCT_NOSIGNAL)) {
  858. printk(KERN_DEBUG"epen:pdct is not active\n");
  859. return 0;
  860. }
  861. #endif
  862. #if defined(WACOM_BOOSTER) || defined(WACOM_BOOSTER_DVFS)
  863. wacom_set_dvfs_lock(wac_i2c, 1);
  864. #endif
  865. #ifdef CONFIG_INPUT_BOOSTER
  866. INPUT_BOOSTER_REPORT_KEY_EVENT(wac_i2c->input_dev, KEY_BOOSTER_PEN, 1);
  867. INPUT_BOOSTER_SEND_EVENT(KEY_BOOSTER_PEN, BOOSTER_MODE_ON);
  868. #endif
  869. wac_i2c->pen_prox = 1;
  870. if (data[0] & 0x40)
  871. wac_i2c->tool = BTN_TOOL_RUBBER;
  872. else
  873. wac_i2c->tool = BTN_TOOL_PEN;
  874. #if defined(CONFIG_SAMSUNG_KERNEL_DEBUG_USER)
  875. printk(KERN_DEBUG"epen:is in(%d)\n", wac_i2c->tool);
  876. #endif
  877. }
  878. prox = !!(data[0] & 0x10);
  879. stylus = !!(data[0] & 0x20);
  880. rubber = !!(data[0] & 0x40);
  881. rdy = !!(data[0] & 0x80);
  882. x = ((u16) data[1] << 8) + (u16) data[2];
  883. y = ((u16) data[3] << 8) + (u16) data[4];
  884. pressure = ((u16) data[5] << 8) + (u16) data[6];
  885. #if defined(WACOM_USE_GAIN)
  886. gain = data[7];
  887. #endif
  888. #ifdef WACOM_IMPORT_FW_ALGO
  889. x = x - origin_offset[0];
  890. y = y - origin_offset[1];
  891. #ifdef WACOM_USE_OFFSET_TABLE
  892. if (wac_i2c->use_offset_table) {
  893. if (x >= 0 && y >= 0)
  894. wacom_i2c_coord_offset(&x, &y);
  895. }
  896. #endif
  897. #ifdef CONFIG_MACH_T0
  898. if (wac_i2c->use_aveTransition && pressure == 0) {
  899. #if defined(WACOM_USE_GAIN)
  900. height = wacom_i2c_coord_level(gain);
  901. #endif
  902. #if defined(WACOM_USE_AVE_TRANSITION)
  903. ave_level(x, y, height, &aveStrength);
  904. #endif
  905. }
  906. #endif
  907. #ifdef WACOM_USE_AVERAGING
  908. wacom_i2c_coord_average(&x, &y, rdy, aveStrength);
  909. #endif
  910. #ifdef WACOM_USE_BOX_FILTER
  911. if (pressure == 0)
  912. boxfilt(&x, &y, height, rdy);
  913. #endif
  914. #endif /*WACOM_IMPORT_FW_ALGO*/
  915. if (wac_i2c->wac_pdata->x_invert)
  916. x = wac_i2c->wac_feature->x_max - x;
  917. if (wac_i2c->wac_pdata->y_invert)
  918. y = wac_i2c->wac_feature->y_max - y;
  919. if (wac_i2c->wac_pdata->xy_switch) {
  920. tmp = x;
  921. x = y;
  922. y = tmp;
  923. }
  924. #ifdef WACOM_USE_TILT_OFFSET
  925. /* Add offset */
  926. x = x + tilt_offsetX[user_hand][screen_rotate];
  927. y = y + tilt_offsetY[user_hand][screen_rotate];
  928. #endif
  929. if (false == wacom_i2c_coord_range(&x, &y)) {
  930. #if defined(CONFIG_SAMSUNG_KERNEL_DEBUG_USER)
  931. printk(KERN_DEBUG "epen:raw data x=%d, y=%d\n",
  932. x, y);
  933. #endif
  934. return 0;
  935. }
  936. input_report_abs(wac_i2c->input_dev, ABS_X, x);
  937. input_report_abs(wac_i2c->input_dev, ABS_Y, y);
  938. input_report_abs(wac_i2c->input_dev,
  939. ABS_PRESSURE, pressure);
  940. #ifdef WACOM_USE_GAIN
  941. input_report_abs(wac_i2c->input_dev,
  942. ABS_DISTANCE, gain);
  943. #endif
  944. input_report_key(wac_i2c->input_dev,
  945. BTN_STYLUS, stylus);
  946. input_report_key(wac_i2c->input_dev, BTN_TOUCH, prox);
  947. input_report_key(wac_i2c->input_dev, wac_i2c->tool, 1);
  948. #ifdef DISABLE_WACOM_PDCT_WORK_AROUND
  949. if (wac_i2c->rdy_pdct) {
  950. wac_i2c->rdy_pdct = false;
  951. input_report_key(wac_i2c->input_dev,
  952. KEY_PEN_PDCT, 0);
  953. }
  954. #endif
  955. input_sync(wac_i2c->input_dev);
  956. wac_i2c->last_x = x;
  957. wac_i2c->last_y = y;
  958. if (prox && !wac_i2c->pen_pressed) {
  959. #if defined(CONFIG_SAMSUNG_KERNEL_DEBUG_USER)
  960. printk(KERN_DEBUG
  961. "epen:is pressed(%d,%d,%d)(%d)\n",
  962. x, y, pressure, wac_i2c->tool);
  963. #else
  964. printk(KERN_DEBUG "epen:pressed\n");
  965. #endif
  966. } else if (!prox && wac_i2c->pen_pressed) {
  967. #if defined(CONFIG_SAMSUNG_KERNEL_DEBUG_USER)
  968. printk(KERN_DEBUG
  969. "epen:is released(%d,%d,%d)(%d)\n",
  970. x, y, pressure, wac_i2c->tool);
  971. #else
  972. printk(KERN_DEBUG "epen:released\n");
  973. #endif
  974. }
  975. wac_i2c->pen_pressed = prox;
  976. if (stylus && !wac_i2c->side_pressed)
  977. printk(KERN_DEBUG "epen:side on\n");
  978. else if (!stylus && wac_i2c->side_pressed)
  979. printk(KERN_DEBUG "epen:side off\n");
  980. wac_i2c->side_pressed = stylus;
  981. } else {
  982. #ifdef WACOM_USE_AVERAGING
  983. /* enable emr device */
  984. wacom_i2c_coord_average(0, 0, 0, 0);
  985. #endif
  986. #ifdef WACOM_USE_BOX_FILTER
  987. boxfilt(0, 0, 0, 0);
  988. #endif
  989. #ifdef DISABLE_WACOM_PDCT_WORK_AROUND
  990. if (wac_i2c->pen_pdct == PDCT_DETECT_PEN)
  991. forced_hover(wac_i2c);
  992. else
  993. #endif
  994. if (wac_i2c->pen_prox) {
  995. /* input_report_abs(wac->input_dev,
  996. ABS_X, x); */
  997. /* input_report_abs(wac->input_dev,
  998. ABS_Y, y); */
  999. input_report_abs(wac_i2c->input_dev, ABS_PRESSURE, 0);
  1000. #ifdef WACOM_USE_GAIN
  1001. input_report_abs(wac_i2c->input_dev,
  1002. ABS_DISTANCE, 0);
  1003. #endif
  1004. input_report_key(wac_i2c->input_dev, BTN_STYLUS, 0);
  1005. input_report_key(wac_i2c->input_dev, BTN_TOUCH, 0);
  1006. input_report_key(wac_i2c->input_dev,
  1007. BTN_TOOL_RUBBER, 0);
  1008. input_report_key(wac_i2c->input_dev, BTN_TOOL_PEN, 0);
  1009. #ifdef CONFIG_INPUT_BOOSTER
  1010. INPUT_BOOSTER_REPORT_KEY_EVENT(wac_i2c->input_dev, KEY_BOOSTER_PEN, 0);
  1011. INPUT_BOOSTER_SEND_EVENT(KEY_BOOSTER_PEN, BOOSTER_MODE_OFF);
  1012. #endif
  1013. input_sync(wac_i2c->input_dev);
  1014. #ifdef WACOM_USE_SOFTKEY_BLOCK
  1015. if (wac_i2c->pen_pressed) {
  1016. cancel_delayed_work_sync(&wac_i2c->softkey_block_work);
  1017. wac_i2c->block_softkey = true;
  1018. schedule_delayed_work(&wac_i2c->softkey_block_work,
  1019. SOFTKEY_BLOCK_DURATION);
  1020. }
  1021. #endif
  1022. printk(KERN_DEBUG "epen:is out");
  1023. }
  1024. wac_i2c->pen_prox = 0;
  1025. wac_i2c->pen_pressed = 0;
  1026. wac_i2c->side_pressed = 0;
  1027. wac_i2c->last_x = 0;
  1028. wac_i2c->last_y = 0;
  1029. #if defined(WACOM_BOOSTER) || defined(WACOM_BOOSTER_DVFS)
  1030. wacom_set_dvfs_lock(wac_i2c, 0);
  1031. #endif
  1032. }
  1033. return 0;
  1034. }