ha2605.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. /*
  2. * linux/drivers/input/ha2605.c
  3. *
  4. * ha2605 Keypad Driver
  5. *
  6. * Copyright (C) 2011 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. * author :
  22. */
  23. #include <linux/delay.h>
  24. #include <linux/i2c.h>
  25. #include <linux/input.h>
  26. #include <linux/interrupt.h>
  27. #include <linux/irq.h>
  28. #include <linux/slab.h>
  29. #include <linux/device.h>
  30. #include <linux/platform_device.h>
  31. #include <linux/workqueue.h>
  32. #include <linux/gpio.h>
  33. #include <linux/i2c/ha2605.h>
  34. #define DRIVER_NAME "ha2605"
  35. #define __HA2605_DEBUG__ 0
  36. /* periodic polling delay and period */
  37. #define KP_POLL_DELAY (40 * 1000000)
  38. #define KP_POLL_PERIOD (30 * 1000000)
  39. struct ha2605 {
  40. spinlock_t lock;
  41. struct i2c_client *client;
  42. struct input_dev *input;
  43. struct hrtimer timer;
  44. int config_major;
  45. char config_name[20];
  46. struct class *config_class;
  47. struct device *config_dev;
  48. struct work_struct work;
  49. struct workqueue_struct *workqueue;
  50. int (*get_irq_level)(void);
  51. struct cap_key *key;
  52. int key_num;
  53. int pending_keys;
  54. int pending_key_code;
  55. int last_read;
  56. };
  57. static struct ha2605 *gp_kp=NULL;
  58. static u8 ha2605_init_param_table[] = {
  59. 0x88,0x05,0x8e,0x8e,0x9d,0x9d,0x9d,0xc0,0x00,0x05,0x00,0xbd,
  60. };
  61. static int ha2605_read_data(struct i2c_client *client)
  62. {
  63. int ret;
  64. u8 buf[2];
  65. struct i2c_msg msg[1] = {
  66. [0] = {
  67. .addr = client->addr,
  68. .flags = I2C_M_RD,
  69. .len = 1,
  70. .buf = buf,
  71. },
  72. };
  73. ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
  74. if (ret >= 0) {
  75. ret = buf[0];
  76. }
  77. return ret;
  78. }
  79. static int ha2605_write_param(struct i2c_client *client)
  80. {
  81. struct i2c_msg msg = {
  82. .addr = client->addr,
  83. .flags = !I2C_M_RD,
  84. .len = sizeof(ha2605_init_param_table),
  85. .buf = ha2605_init_param_table,
  86. };
  87. printk("ha2605 param table len = %d\n", sizeof(ha2605_init_param_table));
  88. return i2c_transfer(client->adapter, &msg, 1);
  89. }
  90. static int ha2605_reset(struct i2c_client *client)
  91. {
  92. int ret;
  93. printk("ha2605 client = %x\n", (u32)client);
  94. ret = ha2605_write_param(client);
  95. if (ret < 0) {
  96. printk("write ha2605 param table fail\n");
  97. return -EINVAL;
  98. }
  99. return 0;
  100. }
  101. #if 0
  102. static int ha2605_sleep(struct i2c_client *client, bool sleep)
  103. {
  104. return 0;
  105. }
  106. #endif
  107. static void ha2605_work(struct work_struct *work)
  108. {
  109. int i;
  110. int button_val = 0;
  111. struct ha2605 *kp;
  112. struct cap_key *key;
  113. kp = (struct ha2605 *)container_of(work, struct ha2605, work);
  114. if (!kp->get_irq_level())
  115. {
  116. button_val = ha2605_read_data(kp->client);
  117. }
  118. else
  119. {
  120. button_val = 255;
  121. }
  122. if ((button_val < 255) && (button_val > 5)){
  123. ha2605_reset(kp->client);
  124. return;
  125. }
  126. #if __HA2605_DEBUG__
  127. printk(KERN_INFO "button_val = 0x%04x\r\n", button_val);
  128. #endif
  129. key = kp->key;
  130. if ((button_val <= 5) && (button_val > 0))
  131. {
  132. if(kp->pending_keys)
  133. {
  134. if(kp->pending_keys != button_val)
  135. {
  136. input_report_key(kp->input, kp->pending_key_code, 0);
  137. kp->pending_keys = 0;
  138. printk(KERN_INFO" key(%d) released\n", kp->pending_key_code);
  139. }
  140. }
  141. if(kp->pending_keys != button_val)
  142. {
  143. kp->pending_keys = button_val;
  144. for (i = 0; i < kp->key_num; i++)
  145. {
  146. if (button_val == key->mask)
  147. {
  148. input_report_key(kp->input, key->code, 1);
  149. printk(KERN_INFO"%s key(%d) pressed\n", key->name, key->code);
  150. kp->pending_key_code = key->code;
  151. break;
  152. }
  153. key++;
  154. }
  155. }
  156. //restart:
  157. hrtimer_start(&kp->timer, ktime_set(0, KP_POLL_PERIOD), HRTIMER_MODE_REL);
  158. }
  159. else
  160. {
  161. if(button_val == 255)
  162. {
  163. if(kp->pending_keys)
  164. {
  165. input_report_key(kp->input, kp->pending_key_code, 0);
  166. kp->pending_keys = 0;
  167. printk(KERN_INFO" key(%d) released\n", kp->pending_key_code);
  168. }
  169. }
  170. enable_irq(kp->client->irq);
  171. }
  172. }
  173. static struct input_dev* ha2605_register_input(struct cap_key *key, int key_num)
  174. {
  175. struct input_dev *input;
  176. int i;
  177. input = input_allocate_device();
  178. if (input) {
  179. /* setup input device */
  180. set_bit(EV_KEY, input->evbit);
  181. set_bit(EV_REP, input->evbit);
  182. for (i=0; i<key_num; i++) {
  183. set_bit(key->code, input->keybit);
  184. printk(KERN_INFO "%s key(%d) registed.\n", key->name, key->code);
  185. key++;
  186. }
  187. input->name = DRIVER_NAME;
  188. input->phys = "ha2605/input0";
  189. // input->dev.parent = &pdev->dev;
  190. input->id.bustype = BUS_ISA;
  191. input->id.vendor = 0x0015;
  192. input->id.product = 0x0001;
  193. input->id.version = 0x0100;
  194. input->rep[REP_DELAY]=0xffffffff;
  195. input->rep[REP_PERIOD]=0xffffffff;
  196. input->keycodesize = sizeof(unsigned short);
  197. input->keycodemax = 0x1ff;
  198. if (input_register_device(input) < 0) {
  199. printk(KERN_ERR "ha2605 register input device failed\n");
  200. input_free_device(input);
  201. input = 0;
  202. }
  203. else {
  204. printk("ha2605 register input device completed\n");
  205. }
  206. }
  207. return input;
  208. }
  209. /**
  210. * ha2605_timer() - timer callback function
  211. * @timer: timer that caused this function call
  212. */
  213. static enum hrtimer_restart ha2605_timer(struct hrtimer *timer)
  214. {
  215. struct ha2605 *kp = (struct ha2605*)container_of(timer, struct ha2605, timer);
  216. unsigned long flags = 0;
  217. spin_lock_irqsave(&kp->lock, flags);
  218. queue_work(kp->workqueue, &kp->work);
  219. spin_unlock_irqrestore(&kp->lock, flags);
  220. return HRTIMER_NORESTART;
  221. }
  222. static irqreturn_t ha2605_interrupt(int irq, void *context)
  223. {
  224. struct ha2605 *kp = (struct ha2605 *)context;
  225. unsigned long flags;
  226. spin_lock_irqsave(&kp->lock, flags);
  227. printk(KERN_INFO "ha2605 enter irq\n");
  228. /* if the attn low or data not clear, disable IRQ and start timer chain */
  229. if ((!kp->get_irq_level()) || (kp->pending_keys)) {
  230. disable_irq_nosync(kp->client->irq);
  231. hrtimer_start(&kp->timer, ktime_set(0, KP_POLL_DELAY), HRTIMER_MODE_REL);
  232. }
  233. spin_unlock_irqrestore(&kp->lock, flags);
  234. return IRQ_HANDLED;
  235. }
  236. static int ha2605_config_open(struct inode *inode, struct file *file)
  237. {
  238. file->private_data = gp_kp;
  239. return 0;
  240. }
  241. static int ha2605_config_release(struct inode *inode, struct file *file)
  242. {
  243. file->private_data=NULL;
  244. return 0;
  245. }
  246. static const struct file_operations ha2605_fops = {
  247. .owner = THIS_MODULE,
  248. .open = ha2605_config_open,
  249. .ioctl = NULL,
  250. .release = ha2605_config_release,
  251. };
  252. static int ha2605_register_device(struct ha2605 *kp)
  253. {
  254. int ret=0;
  255. strcpy(kp->config_name,DRIVER_NAME);
  256. ret=register_chrdev(0, kp->config_name, &ha2605_fops);
  257. if(ret<=0) {
  258. printk("register char device error\r\n");
  259. return ret ;
  260. }
  261. kp->config_major=ret;
  262. printk("ha2605 major:%d\r\n",ret);
  263. kp->config_class=class_create(THIS_MODULE,kp->config_name);
  264. kp->config_dev=device_create(kp->config_class, NULL,
  265. MKDEV(kp->config_major,0),NULL,kp->config_name);
  266. return ret;
  267. }
  268. static int ha2605_probe(struct i2c_client *client, const struct i2c_device_id *id)
  269. {
  270. int err;
  271. struct ha2605 *kp;
  272. struct ha2605_platform_data *pdata;
  273. pdata = client->dev.platform_data;
  274. if (!pdata) {
  275. dev_err(&client->dev, "ha2605 require platform data!\n");
  276. return -EINVAL;
  277. }
  278. kp = kzalloc(sizeof(struct ha2605), GFP_KERNEL);
  279. if (!kp) {
  280. dev_err(&client->dev, "ha2605 alloc data failed!\n");
  281. return -ENOMEM;
  282. }
  283. kp->last_read = 0;
  284. kp->client = client;
  285. kp->key = pdata->key;
  286. kp->key_num = pdata->key_num;
  287. kp->pending_keys = 0;
  288. kp->pending_key_code = 0;
  289. kp->input = ha2605_register_input(kp->key, kp->key_num);
  290. if (!kp->input) {
  291. err = -EINVAL;
  292. goto fail_irq;
  293. }
  294. ha2605_reset(client);
  295. hrtimer_init(&kp->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
  296. kp->timer.function = ha2605_timer;
  297. INIT_WORK(&kp->work, ha2605_work);
  298. kp->workqueue = create_singlethread_workqueue(DRIVER_NAME);
  299. if (kp->workqueue == NULL) {
  300. dev_err(&client->dev, "ha2605 can't create work queue\n");
  301. err = -ENOMEM;
  302. goto fail;
  303. }
  304. if (!pdata->init_irq || !pdata->get_irq_level) {
  305. err = -ENOMEM;
  306. goto fail;
  307. }
  308. kp->get_irq_level = pdata->get_irq_level;
  309. pdata->init_irq();
  310. err = request_irq(client->irq, ha2605_interrupt, IRQF_TRIGGER_RISING,
  311. client->dev.driver->name, kp);
  312. if (err) {
  313. dev_err(&client->dev, "failed to request IRQ#%d: %d\n", client->irq, err);
  314. goto fail_irq;
  315. }
  316. gp_kp=kp;
  317. i2c_set_clientdata(client, kp);
  318. ha2605_register_device(gp_kp);
  319. return 0;
  320. fail_irq:
  321. free_irq(client->irq, client);
  322. fail:
  323. kfree(kp);
  324. return err;
  325. }
  326. static int ha2605_remove(struct i2c_client *client)
  327. {
  328. struct ha2605 *kp = i2c_get_clientdata(client);
  329. free_irq(client->irq, client);
  330. i2c_set_clientdata(client, NULL);
  331. input_unregister_device(kp->input);
  332. input_free_device(kp->input);
  333. unregister_chrdev(kp->config_major,kp->config_name);
  334. if(kp->config_class)
  335. {
  336. if(kp->config_dev)
  337. device_destroy(kp->config_class,MKDEV(kp->config_major,0));
  338. class_destroy(kp->config_class);
  339. }
  340. kfree(kp);
  341. gp_kp=NULL ;
  342. return 0;
  343. }
  344. static const struct i2c_device_id ha2605_ids[] = {
  345. { DRIVER_NAME, 0 },
  346. { }
  347. };
  348. static struct i2c_driver ha2605_driver = {
  349. .driver = {
  350. .name = DRIVER_NAME,
  351. .owner = THIS_MODULE,
  352. },
  353. .probe = ha2605_probe,
  354. .remove = ha2605_remove,
  355. // .suspend = ha2605_suspend,
  356. // .resume = ha2605_resume,
  357. .id_table = ha2605_ids,
  358. };
  359. static int __init ha2605_init(void)
  360. {
  361. printk(KERN_INFO "ha2605 init\n");
  362. return i2c_add_driver(&ha2605_driver);
  363. }
  364. static void __exit ha2605_exit(void)
  365. {
  366. printk(KERN_INFO "ha2605 exit\n");
  367. i2c_del_driver(&ha2605_driver);
  368. }
  369. module_init(ha2605_init);
  370. module_exit(ha2605_exit);
  371. MODULE_AUTHOR("");
  372. MODULE_DESCRIPTION("ha2605 driver");
  373. MODULE_LICENSE("GPL");