input:ir:add remotectl support
[firefly-linux-kernel-4.4.55.git] / drivers / input / remotectl / rockchip_pwm_remotectl.c
1 #include <linux/clk.h>
2 #include <linux/io.h>
3 #include <linux/module.h>
4 #include <linux/of.h>
5 #include <linux/platform_device.h>
6 #include <linux/module.h>
7 #include <linux/init.h>
8 #include <linux/interrupt.h>
9 #include <linux/platform_device.h>
10 #include <linux/input.h>
11 #include <linux/workqueue.h>
12 #include <linux/wakelock.h>
13 #include "rockchip_pwm_remotectl.h"
14
15
16
17 /*sys/module/rk_pwm_remotectl/parameters,
18 modify code_print to change the value*/
19
20 static int rk_remote_print_code;
21 module_param_named(code_print, rk_remote_print_code, int, 0644);
22 #define DBG_CODE(args...) \
23         do { \
24                 if (rk_remote_print_code) { \
25                         pr_info(args); \
26                 } \
27         } while (0)
28
29 static int rk_remote_pwm_dbg_level;
30 module_param_named(dbg_level, rk_remote_pwm_dbg_level, int, 0644);
31 #define DBG(args...) \
32         do { \
33                 if (rk_remote_pwm_dbg_level) { \
34                         pr_info(args); \
35                 } \
36         } while (0)
37
38
39 struct rkxx_remote_key_table {
40         int scancode;
41         int keycode;
42 };
43
44 struct rkxx_remotectl_button {
45         int usercode;
46         int nbuttons;
47         struct rkxx_remote_key_table *key_table;
48 };
49
50 struct rkxx_remotectl_drvdata {
51         void __iomem *base;
52         int state;
53         int nbuttons;
54         int result;
55         int scandata;
56         int count;
57         int keynum;
58         int keycode;
59         int press;
60         int pre_press;
61         int period;
62         int irq;
63         int wakeup;
64         struct input_dev *input;
65         struct timer_list timer;
66         struct tasklet_struct remote_tasklet;
67         struct wake_lock remotectl_wake_lock;
68 };
69
70
71 static struct rkxx_remote_key_table remote_key_table_meiyu_4040[] = {
72         {0xf2, KEY_REPLY},
73         {0xba, KEY_BACK},
74         {0xf4, KEY_UP},
75         {0xf1, KEY_DOWN},
76         {0xef, KEY_LEFT},
77         {0xee, KEY_RIGHT},
78         {0xbd, KEY_HOME},
79         {0xea, KEY_VOLUMEUP},
80         {0xe3, KEY_VOLUMEDOWN},
81         {0xe2, KEY_SEARCH},
82         {0xb2, KEY_POWER},
83         {0xbc, KEY_MUTE},
84         {0xec, KEY_MENU},
85 /*lay pause*/
86         {0xbf, 0x190},
87 /*pre*/
88         {0xe0, 0x191},
89 /*next*/
90         {0xe1, 0x192},
91 /*pic,rorate left*/
92         {0xe9, 183},
93 /*rorate right*/
94         {0xe6, 248},
95 /*zoom out*/
96         {0xe8, 185},
97 /*zoom in*/
98         {0xe7, 186},
99 /*mouse switch*/
100         {0xb8, 388},
101 /*zoom outdisplay switch*/
102         {0xbe, 0x175},
103 };
104
105
106 static struct rkxx_remote_key_table remote_key_table_sunchip_ff00[] = {
107         {0xf9, KEY_HOME},
108         {0xbf, KEY_BACK},
109         {0xfb, KEY_MENU},
110         {0xaa, KEY_REPLY},
111         {0xb9, KEY_UP},
112         {0xe9, KEY_DOWN},
113         {0xb8, KEY_LEFT},
114         {0xea, KEY_RIGHT},
115         {0xeb, KEY_VOLUMEDOWN},
116         {0xef, KEY_VOLUMEUP},
117         {0xf7, KEY_MUTE},
118         {0xe7, KEY_POWER},
119         {0xfc, KEY_POWER},
120         {0xa9, KEY_VOLUMEDOWN},
121         {0xa8, KEY_VOLUMEDOWN},
122         {0xe0, KEY_VOLUMEDOWN},
123         {0xa5, KEY_VOLUMEDOWN},
124         {0xab, 183},
125         {0xb7, 388},
126         {0xf8, 184},
127         {0xaf, 185},
128         {0xed, KEY_VOLUMEDOWN},
129         {0xee, 186},
130         {0xb3, KEY_VOLUMEDOWN},
131         {0xf1, KEY_VOLUMEDOWN},
132         {0xf2, KEY_VOLUMEDOWN},
133         {0xf3, KEY_SEARCH},
134         {0xb4, KEY_VOLUMEDOWN},
135         {0xbe, KEY_SEARCH},
136 };
137
138
139 static struct rkxx_remotectl_button remotectl_button[] = {
140         {
141                 .usercode = 0xff00,
142                 .nbuttons =  29,
143                 .key_table = &remote_key_table_sunchip_ff00[0],
144         },
145         {
146                 .usercode = 0x4040,
147                 .nbuttons =  22,
148                 .key_table = &remote_key_table_meiyu_4040[0],
149         },
150 };
151
152
153 static int remotectl_keybd_num_lookup(struct rkxx_remotectl_drvdata *ddata)
154 {
155         int i;
156         int num;
157
158         num =  sizeof(remotectl_button)/sizeof(struct rkxx_remotectl_button);
159         for (i = 0; i < num; i++) {
160                 if (remotectl_button[i].usercode == (ddata->scandata&0xFFFF)) {
161                         ddata->keynum = i;
162                         return 1;
163                 }
164         }
165         return 0;
166 }
167
168
169 static int remotectl_keycode_lookup(struct rkxx_remotectl_drvdata *ddata)
170 {
171         int i;
172         unsigned char keydata = (unsigned char)((ddata->scandata >> 8) & 0xff);
173
174         for (i = 0; i < remotectl_button[ddata->keynum].nbuttons; i++) {
175                 if (remotectl_button[ddata->keynum].key_table[i].scancode ==
176                     keydata) {
177                         ddata->keycode =
178                         remotectl_button[ddata->keynum].key_table[i].keycode;
179                         return 1;
180                 }
181         }
182         return 0;
183 }
184
185
186 static void rk_pwm_remotectl_do_something(unsigned long  data)
187 {
188         struct rkxx_remotectl_drvdata *ddata;
189
190         ddata = (struct rkxx_remotectl_drvdata *)data;
191         switch (ddata->state) {
192         case RMC_IDLE: {
193                 ;
194                 break;
195         }
196         case RMC_PRELOAD: {
197                 mod_timer(&ddata->timer, jiffies + msecs_to_jiffies(130));
198                 if ((RK_PWM_TIME_PRE_MIN < ddata->period) &&
199                     (ddata->period < RK_PWM_TIME_PRE_MAX)) {
200                         ddata->scandata = 0;
201                         ddata->count = 0;
202                         ddata->state = RMC_USERCODE;
203                 } else {
204                         ddata->state = RMC_PRELOAD;
205                 }
206                 break;
207         }
208         case RMC_USERCODE: {
209                 if ((RK_PWM_TIME_BIT1_MIN < ddata->period) &&
210                     (ddata->period < RK_PWM_TIME_BIT1_MAX))
211                         ddata->scandata |= (0x01 << ddata->count);
212                 ddata->count++;
213                 if (ddata->count == 0x10) {
214                         DBG_CODE("USERCODE=0x%x\n", ddata->scandata);
215                         if (remotectl_keybd_num_lookup(ddata)) {
216                                 ddata->state = RMC_GETDATA;
217                                 ddata->scandata = 0;
218                                 ddata->count = 0;
219                         } else {
220                                 ddata->state = RMC_PRELOAD;
221                         }
222                 }
223         }
224         break;
225         case RMC_GETDATA: {
226                 if ((RK_PWM_TIME_BIT1_MIN < ddata->period) &&
227                     (ddata->period < RK_PWM_TIME_BIT1_MAX))
228                         ddata->scandata |= (0x01<<ddata->count);
229                 ddata->count++;
230                 if (ddata->count < 0x10)
231                         return;
232                 DBG_CODE("RMC_GETDATA=%x\n", (ddata->scandata>>8));
233                 if ((ddata->scandata&0x0ff) ==
234                     ((~ddata->scandata >> 8) & 0x0ff)) {
235                         if (remotectl_keycode_lookup(ddata)) {
236                                 ddata->press = 1;
237                                 input_event(ddata->input, EV_KEY,
238                                             ddata->keycode, 1);
239                                 input_sync(ddata->input);
240                                 ddata->state = RMC_SEQUENCE;
241                         } else {
242                                 ddata->state = RMC_PRELOAD;
243                         }
244                 } else {
245                         ddata->state = RMC_PRELOAD;
246                 }
247         }
248         break;
249         case RMC_SEQUENCE:{
250                 DBG("S=%d\n", ddata->period);
251                 if ((RK_PWM_TIME_RPT_MIN < ddata->period) &&
252                     (ddata->period < RK_PWM_TIME_RPT_MAX)) {
253                         DBG("S1\n");
254                         mod_timer(&ddata->timer, jiffies
255                                   + msecs_to_jiffies(110));
256                 } else if ((RK_PWM_TIME_SEQ1_MIN < ddata->period) &&
257                            (ddata->period < RK_PWM_TIME_SEQ1_MAX)) {
258                         DBG("S2\n");
259                         mod_timer(&ddata->timer, jiffies
260                                   + msecs_to_jiffies(110));
261                 } else if ((RK_PWM_TIME_SEQ2_MIN < ddata->period) &&
262                           (ddata->period < RK_PWM_TIME_SEQ2_MAX)) {
263                         DBG("S3\n");
264                         mod_timer(&ddata->timer, jiffies
265                                   + msecs_to_jiffies(110));
266                 } else {
267                         DBG("S4\n");
268                         input_event(ddata->input, EV_KEY,
269                                     ddata->keycode, 0);
270                         input_sync(ddata->input);
271                         ddata->state = RMC_PRELOAD;
272                         ddata->press = 0;
273                 }
274         }
275         break;
276         default:
277         break;
278         }
279 }
280
281 static void rk_pwm_remotectl_timer(unsigned long _data)
282 {
283         struct rkxx_remotectl_drvdata *ddata;
284
285         ddata =  (struct rkxx_remotectl_drvdata *)_data;
286         if (ddata->press != ddata->pre_press) {
287                 ddata->pre_press = 0;
288                 ddata->press = 0;
289                 input_event(ddata->input, EV_KEY, ddata->keycode, 0);
290                 input_sync(ddata->input);
291         }
292         ddata->state = RMC_PRELOAD;
293 }
294
295
296 static irqreturn_t rockchip_pwm_irq(int irq, void *dev_id)
297 {
298         struct rkxx_remotectl_drvdata *ddata;
299         int val;
300
301         ddata = (struct rkxx_remotectl_drvdata *)dev_id;
302         val = readl_relaxed(ddata->base + PWM_REG_INTSTS);
303         if (val&PWM_CH3_INT) {
304                 if (val & PWM_CH3_POL) {
305                         val = readl_relaxed(ddata->base + PWM_REG_HPR);
306                         ddata->period = val;
307                         tasklet_hi_schedule(&ddata->remote_tasklet);
308                         DBG("hpr=0x%x\n", val);
309                 } else {
310                         val = readl_relaxed(ddata->base + PWM_REG_LPR);
311                         DBG("lpr=0x%x\n", val);
312                 }
313                 writel_relaxed(PWM_CH3_INT, ddata->base + PWM_REG_INTSTS);
314                 if (ddata->state == RMC_PRELOAD)
315                         wake_lock_timeout(&ddata->remotectl_wake_lock, HZ);
316                 return IRQ_HANDLED;
317         }
318         return IRQ_NONE;
319 }
320
321 static int rk_pwm_remotectl_hw_init(struct rkxx_remotectl_drvdata *ddata)
322 {
323         int val;
324
325         val = readl_relaxed(ddata->base + PWM_REG_CTRL);
326         val = (val & 0xFFFFFFFE) | PWM_DISABLE;
327         writel_relaxed(val, ddata->base + PWM_REG_CTRL);
328         val = readl_relaxed(ddata->base + PWM_REG_CTRL);
329         val = (val & 0xFFFFFFF9) | PWM_MODE_CAPTURE;
330         writel_relaxed(val, ddata->base + PWM_REG_CTRL);
331         val = readl_relaxed(ddata->base + PWM_REG_CTRL);
332         val = (val & 0xFF008DFF) | 0x00646200;
333         writel_relaxed(val, ddata->base + PWM_REG_CTRL);
334         val = readl_relaxed(ddata->base + PWM_REG_INT_EN);
335         val = (val & 0xFFFFFFF7) | PWM_CH3_INT_ENABLE;
336         writel_relaxed(val, ddata->base + PWM_REG_INT_EN);
337         val = readl_relaxed(ddata->base + PWM_REG_CTRL);
338         val = (val & 0xFFFFFFFE) | PWM_ENABLE;
339         writel_relaxed(val, ddata->base + PWM_REG_CTRL);
340         return 0;
341 }
342
343
344
345 static int rk_pwm_probe(struct platform_device *pdev)
346 {
347         struct rkxx_remotectl_drvdata *ddata;
348         struct resource *r;
349         struct input_dev *input;
350         struct clk *clk;
351         int num;
352         int irq;
353         int ret;
354         int i, j;
355
356         DBG(".. rk pwm remotectl v1.1 init\n");
357         r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
358         if (!r) {
359                 dev_err(&pdev->dev, "no memory resources defined\n");
360                 return -ENODEV;
361         }
362         ddata = devm_kzalloc(&pdev->dev, sizeof(struct rkxx_remotectl_drvdata),
363                              GFP_KERNEL);
364         if (!ddata) {
365                 dev_err(&pdev->dev, "failed to allocate memory\n");
366                 return -ENOMEM;
367         }
368         ddata->state = RMC_PRELOAD;
369         ddata->base = devm_ioremap_resource(&pdev->dev, r);
370         if (IS_ERR(ddata->base))
371                 return PTR_ERR(ddata->base);
372         clk = devm_clk_get(&pdev->dev, "pclk_pwm");
373         if (IS_ERR(clk))
374                 return PTR_ERR(clk);
375         platform_set_drvdata(pdev, ddata);
376         input = input_allocate_device();
377         input->name = pdev->name;
378         input->phys = "gpio-keys/remotectl";
379         input->dev.parent = &pdev->dev;
380         input->id.bustype = BUS_HOST;
381         input->id.vendor = 0x0001;
382         input->id.product = 0x0001;
383         input->id.version = 0x0100;
384         ddata->input = input;
385         ddata->input = input;
386         wake_lock_init(&ddata->remotectl_wake_lock,
387                        WAKE_LOCK_SUSPEND, "rk29_pwm_remote");
388         ret = clk_prepare_enable(clk);
389         if (ret)
390                 return ret;
391         irq = platform_get_irq(pdev, 0);
392         if (ret < 0) {
393                 dev_err(&pdev->dev, "cannot find IRQ\n");
394                 return ret;
395         }
396         ddata->irq = irq;
397         ddata->wakeup = 1;
398         tasklet_init(&ddata->remote_tasklet, rk_pwm_remotectl_do_something,
399                      (unsigned long)ddata);
400         num =  sizeof(remotectl_button)/sizeof(struct rkxx_remotectl_button);
401         for (j = 0; j < num; j++) {
402                 DBG("remotectl probe j = 0x%x\n", j);
403                 for (i = 0; i < remotectl_button[j].nbuttons; i++) {
404                         unsigned int type = EV_KEY;
405
406                         input_set_capability(input, type, remotectl_button[j].
407                                              key_table[i].keycode);
408                 }
409         }
410         ret = input_register_device(input);
411         if (ret)
412                 pr_err("remotectl: register input device err, ret: %d\n", ret);
413         input_set_capability(input, EV_KEY, KEY_WAKEUP);
414         device_init_wakeup(&pdev->dev, 1);
415         ret = devm_request_irq(&pdev->dev, irq, rockchip_pwm_irq,
416                                0, "rk_pwm_irq", ddata);
417         if (ret) {
418                 dev_err(&pdev->dev, "cannot claim IRQ %d\n", irq);
419                 return ret;
420         }
421         enable_irq_wake(irq);
422         setup_timer(&ddata->timer, rk_pwm_remotectl_timer,
423                     (unsigned long)ddata);
424         mod_timer(&ddata->timer, jiffies + msecs_to_jiffies(1000));
425         rk_pwm_remotectl_hw_init(ddata);
426         return ret;
427 }
428
429 static int rk_pwm_remove(struct platform_device *pdev)
430 {
431         return 0;
432 }
433
434
435 static const struct of_device_id rk_pwm_of_match[] = {
436         { .compatible =  "rockchip,remotectl-pwm"},
437         { }
438 };
439
440 MODULE_DEVICE_TABLE(of, rk_pwm_of_match);
441
442 static struct platform_driver rk_pwm_driver = {
443         .driver = {
444                 .name = "remotectl-pwm",
445                 .of_match_table = rk_pwm_of_match,
446         },
447         .probe = rk_pwm_probe,
448         .remove = rk_pwm_remove,
449 };
450
451 module_platform_driver(rk_pwm_driver);
452
453 MODULE_LICENSE("GPL");