sw_remote_kbd.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. /*
  2. * linux/drivers/input/irremote/sw_remote_kbd.c
  3. *
  4. * Keypad Driver
  5. *
  6. * Copyright (C) 2009 Amlogic Corporation
  7. *
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  22. * author : jianfeng_wang
  23. */
  24. /*
  25. * !!caution: if you use remote ,you should disable card1 used for ata_enable pin.
  26. */
  27. #include <linux/module.h>
  28. #include <linux/init.h>
  29. #include <linux/interrupt.h>
  30. #include <linux/types.h>
  31. #include <linux/input.h>
  32. #include <linux/kernel.h>
  33. #include <linux/delay.h>
  34. #include <linux/platform_device.h>
  35. #include <linux/mutex.h>
  36. #include <linux/errno.h>
  37. #include <asm/irq.h>
  38. #include <asm/io.h>
  39. #include <mach/am_regs.h>
  40. #include "am_remote.h"
  41. extern char *remote_log_buf;
  42. static int dbg_printk(const char *fmt, ...)
  43. {
  44. char buf[100];
  45. va_list args;
  46. va_start(args, fmt);
  47. vscnprintf(buf, 100, fmt, args);
  48. if (strlen(remote_log_buf) + (strlen(buf) + 64) > REMOTE_LOG_BUF_LEN) {
  49. remote_log_buf[0] = '\0';
  50. }
  51. strcat(remote_log_buf, buf);
  52. va_end(args);
  53. return 0;
  54. }
  55. static int get_pulse_width(unsigned long data)
  56. {
  57. struct remote *remote_data = (struct remote *)data;
  58. int pulse_width;
  59. const char *state;
  60. pulse_width = (am_remote_read_reg(AM_IR_DEC_REG1) & 0x1FFF0000) >> 16;
  61. state = remote_data->step == REMOTE_STATUS_WAIT ? "wait" :
  62. remote_data->step == REMOTE_STATUS_LEADER ? "leader" :
  63. remote_data->step == REMOTE_STATUS_DATA ? "data" :
  64. remote_data->step == REMOTE_STATUS_SYNC ? "sync" : NULL;
  65. dbg_printk("%02d:pulse_wdith:%d==>%s\r\n",
  66. remote_data->bit_count - remote_data->bit_num, pulse_width, state);
  67. //sometimes we found remote pulse width==0. in order to sync machine state we modify it .
  68. if (pulse_width == 0) {
  69. switch (remote_data->step) {
  70. case REMOTE_STATUS_LEADER:
  71. pulse_width = remote_data->time_window[0] + 1;
  72. break;
  73. case REMOTE_STATUS_DATA:
  74. pulse_width = remote_data->time_window[2] + 1;
  75. break;
  76. }
  77. }
  78. return pulse_width;
  79. }
  80. static inline void kbd_software_mode_remote_wait(unsigned long data)
  81. {
  82. unsigned short pulse_width;
  83. struct remote *remote_data = (struct remote *)data;
  84. pulse_width = get_pulse_width(data);
  85. remote_data->step = REMOTE_STATUS_LEADER;
  86. remote_data->cur_keycode = 0;
  87. remote_data->bit_num = remote_data->bit_count;
  88. }
  89. static inline void kbd_software_mode_remote_leader(unsigned long data)
  90. {
  91. unsigned short pulse_width;
  92. struct remote *remote_data = (struct remote *)data;
  93. pulse_width = get_pulse_width(data);
  94. if ((pulse_width > remote_data->time_window[0])
  95. && (pulse_width < remote_data->time_window[1])) {
  96. remote_data->step = REMOTE_STATUS_DATA;
  97. } else {
  98. remote_data->step = REMOTE_STATUS_WAIT;
  99. }
  100. remote_data->cur_keycode = 0;
  101. remote_data->bit_num = remote_data->bit_count;
  102. }
  103. static inline void kbd_software_mode_remote_send_key(unsigned long data)
  104. {
  105. struct remote *remote_data = (struct remote *)data;
  106. unsigned int reort_key_code = remote_data->cur_keycode >> 16 & 0xffff;
  107. remote_data->step = REMOTE_STATUS_SYNC;
  108. if (remote_data->repeate_flag) {
  109. if (remote_data->custom_code != (remote_data->cur_keycode & 0xffff)) {
  110. return;
  111. }
  112. if (((reort_key_code & 0xff) ^ (reort_key_code >> 8 & 0xff)) !=
  113. 0xff) {
  114. return;
  115. }
  116. if (remote_data->repeat_tick < jiffies) {
  117. remote_send_key(remote_data->input,
  118. (remote_data->cur_keycode >> 16) & 0xff, 2);
  119. remote_data->repeat_tick +=
  120. msecs_to_jiffies(remote_data->input->rep[REP_PERIOD]);
  121. }
  122. } else {
  123. switch (remote_data->work_mode) {
  124. case REMOTE_WORK_MODE_FIQ_RCMM:
  125. if (remote_data->custom_code !=
  126. (remote_data->cur_keycode & 0xfff)) {
  127. input_dbg("Wrong custom code is 0x%08x\n",
  128. remote_data->cur_keycode);
  129. return;
  130. }
  131. if (remote_data->bit_count == 32)
  132. remote_send_key(remote_data->input,
  133. 0x100 | (remote_data->cur_keycode >>
  134. (remote_data->bit_count - 8)),
  135. 1);
  136. else
  137. remote_send_key(remote_data->input,
  138. remote_data->
  139. cur_keycode >> (remote_data->bit_count -
  140. 8), 1);
  141. break;
  142. default:
  143. if (remote_data->custom_code !=
  144. (remote_data->cur_keycode & 0xffff)) {
  145. input_dbg("Wrong custom code is 0x%08x\n",
  146. remote_data->cur_keycode);
  147. return;
  148. }
  149. if (((reort_key_code & 0xff) ^
  150. (reort_key_code >> 8 & 0xff)) == 0xff)
  151. remote_send_key(remote_data->input,
  152. (remote_data->cur_keycode >> 16) & 0xff,
  153. 1);
  154. }
  155. if (remote_data->repeat_enable)
  156. remote_data->repeat_tick =
  157. jiffies +
  158. msecs_to_jiffies(remote_data->input->rep[REP_DELAY]);
  159. }
  160. }
  161. static inline void kbd_software_mode_remote_data(unsigned long data)
  162. {
  163. unsigned short pulse_width;
  164. struct remote *remote_data = (struct remote *)data;
  165. pulse_width = get_pulse_width(data);
  166. remote_data->step = REMOTE_STATUS_DATA;
  167. switch (remote_data->work_mode) {
  168. case REMOTE_WORK_MODE_SW:
  169. case REMOTE_WORK_MODE_FIQ:
  170. if ((pulse_width > remote_data->time_window[2])
  171. && (pulse_width < remote_data->time_window[3])) {
  172. remote_data->bit_num--;
  173. } else if ((pulse_width > remote_data->time_window[4])
  174. && (pulse_width < remote_data->time_window[5])) {
  175. remote_data->cur_keycode |=
  176. 1 << (remote_data->bit_count - remote_data->bit_num);
  177. remote_data->bit_num--;
  178. } else {
  179. remote_data->step = REMOTE_STATUS_WAIT;
  180. }
  181. if (remote_data->bit_num == 0) {
  182. remote_data->repeate_flag = 0;
  183. remote_data->send_data = 1;
  184. if (remote_data->work_mode == REMOTE_WORK_MODE_FIQ)
  185. fiq_bridge_pulse_trigger
  186. (&remote_data->fiq_handle_item);
  187. else {
  188. remote_bridge_isr(0, remote_data);
  189. }
  190. }
  191. break;
  192. case REMOTE_WORK_MODE_FIQ_RCMM:
  193. if ((pulse_width > remote_data->time_window[2])
  194. && (pulse_width < remote_data->time_window[3])) {
  195. if ((remote_data->bit_num == 12) && (remote_data->bit_count == 24)) { /*sub mode is remote control */
  196. remote_data->bit_count += 8;
  197. remote_data->bit_num += 8;
  198. }
  199. remote_data->bit_num -= 2;
  200. } else if ((pulse_width > remote_data->time_window[4])
  201. && (pulse_width < remote_data->time_window[5])) {
  202. remote_data->cur_keycode |=
  203. 1 << (remote_data->bit_count - remote_data->bit_num);
  204. remote_data->bit_num -= 2;
  205. } else if ((pulse_width > remote_data->time_window[8])
  206. && (pulse_width < remote_data->time_window[9])) {
  207. remote_data->cur_keycode |=
  208. 2 << (remote_data->bit_count - remote_data->bit_num);
  209. if ((remote_data->bit_num == 20) && (remote_data->bit_count == 32)) { /*sub mode is keyboard */
  210. remote_data->bit_count -= 8;
  211. remote_data->bit_num -= 8;
  212. }
  213. remote_data->bit_num -= 2;
  214. } else if ((pulse_width > remote_data->time_window[10])
  215. && (pulse_width < remote_data->time_window[11])) {
  216. remote_data->cur_keycode |=
  217. 3 << (remote_data->bit_count - remote_data->bit_num);
  218. remote_data->bit_num -= 2;
  219. } else {
  220. remote_data->step = REMOTE_STATUS_WAIT;
  221. }
  222. if (remote_data->bit_num == 0) {
  223. remote_data->repeate_flag = 0;
  224. remote_data->send_data = 1;
  225. fiq_bridge_pulse_trigger(&remote_data->fiq_handle_item);
  226. }
  227. break;
  228. }
  229. }
  230. static inline void kbd_software_mode_remote_sync(unsigned long data)
  231. {
  232. unsigned short pulse_width;
  233. struct remote *remote_data = (struct remote *)data;
  234. pulse_width = get_pulse_width(data);
  235. if ((pulse_width > remote_data->time_window[6])
  236. && (pulse_width < remote_data->time_window[7])) {
  237. remote_data->repeate_flag = 1;
  238. if (remote_data->repeat_enable) {
  239. remote_data->send_data = 1;
  240. } else {
  241. remote_data->step = REMOTE_STATUS_SYNC;
  242. return;
  243. }
  244. }
  245. remote_data->step = REMOTE_STATUS_SYNC;
  246. if ((remote_data->work_mode == REMOTE_WORK_MODE_FIQ)
  247. || (remote_data->work_mode == REMOTE_WORK_MODE_FIQ_RCMM)) {
  248. fiq_bridge_pulse_trigger(&remote_data->fiq_handle_item);
  249. } else {
  250. remote_bridge_isr(0, remote_data);
  251. }
  252. }
  253. void remote_sw_reprot_key(unsigned long data)
  254. {
  255. struct remote *remote_data = (struct remote *)data;
  256. int current_jiffies = jiffies;
  257. if (((current_jiffies - remote_data->last_jiffies) > 20)
  258. && (remote_data->step <= REMOTE_STATUS_SYNC)) {
  259. remote_data->step = REMOTE_STATUS_WAIT;
  260. }
  261. remote_data->last_jiffies = current_jiffies; //ignore a little msecs
  262. switch (remote_data->step) {
  263. case REMOTE_STATUS_WAIT:
  264. kbd_software_mode_remote_wait(data);
  265. break;
  266. case REMOTE_STATUS_LEADER:
  267. kbd_software_mode_remote_leader(data);
  268. break;
  269. case REMOTE_STATUS_DATA:
  270. kbd_software_mode_remote_data(data);
  271. break;
  272. case REMOTE_STATUS_SYNC:
  273. kbd_software_mode_remote_sync(data);
  274. break;
  275. default:
  276. break;
  277. }
  278. }
  279. irqreturn_t remote_bridge_isr(int irq, void *dev_id)
  280. {
  281. struct remote *remote_data = (struct remote *)dev_id;
  282. if (remote_data->send_data) { //report key
  283. kbd_software_mode_remote_send_key((unsigned long)remote_data);
  284. remote_data->send_data = 0;
  285. }
  286. remote_data->timer.data = (unsigned long)remote_data;
  287. mod_timer(&remote_data->timer,
  288. jiffies + msecs_to_jiffies(remote_data->release_delay));
  289. return IRQ_HANDLED;
  290. }