3 #include <linux/module.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"
17 /*sys/module/rk_pwm_remotectl/parameters,
18 modify code_print to change the value*/
20 static int rk_remote_print_code;
21 module_param_named(code_print, rk_remote_print_code, int, 0644);
22 #define DBG_CODE(args...) \
24 if (rk_remote_print_code) { \
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...) \
33 if (rk_remote_pwm_dbg_level) { \
39 struct rkxx_remote_key_table {
44 struct rkxx_remotectl_button {
47 struct rkxx_remote_key_table *key_table;
50 struct rkxx_remotectl_drvdata {
64 struct input_dev *input;
65 struct timer_list timer;
66 struct tasklet_struct remote_tasklet;
67 struct wake_lock remotectl_wake_lock;
71 static struct rkxx_remote_key_table remote_key_table_meiyu_4040[] = {
80 {0xe3, KEY_VOLUMEDOWN},
101 /*zoom outdisplay switch*/
106 static struct rkxx_remote_key_table remote_key_table_sunchip_ff00[] = {
115 {0xeb, KEY_VOLUMEDOWN},
116 {0xef, KEY_VOLUMEUP},
120 {0xa9, KEY_VOLUMEDOWN},
121 {0xa8, KEY_VOLUMEDOWN},
122 {0xe0, KEY_VOLUMEDOWN},
123 {0xa5, KEY_VOLUMEDOWN},
128 {0xed, KEY_VOLUMEDOWN},
130 {0xb3, KEY_VOLUMEDOWN},
131 {0xf1, KEY_VOLUMEDOWN},
132 {0xf2, KEY_VOLUMEDOWN},
134 {0xb4, KEY_VOLUMEDOWN},
139 static struct rkxx_remotectl_button remotectl_button[] = {
143 .key_table = &remote_key_table_sunchip_ff00[0],
148 .key_table = &remote_key_table_meiyu_4040[0],
153 static int remotectl_keybd_num_lookup(struct rkxx_remotectl_drvdata *ddata)
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)) {
169 static int remotectl_keycode_lookup(struct rkxx_remotectl_drvdata *ddata)
172 unsigned char keydata = (unsigned char)((ddata->scandata >> 8) & 0xff);
174 for (i = 0; i < remotectl_button[ddata->keynum].nbuttons; i++) {
175 if (remotectl_button[ddata->keynum].key_table[i].scancode ==
178 remotectl_button[ddata->keynum].key_table[i].keycode;
186 static void rk_pwm_remotectl_do_something(unsigned long data)
188 struct rkxx_remotectl_drvdata *ddata;
190 ddata = (struct rkxx_remotectl_drvdata *)data;
191 switch (ddata->state) {
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)) {
202 ddata->state = RMC_USERCODE;
204 ddata->state = RMC_PRELOAD;
209 if ((RK_PWM_TIME_BIT1_MIN < ddata->period) &&
210 (ddata->period < RK_PWM_TIME_BIT1_MAX))
211 ddata->scandata |= (0x01 << 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;
220 ddata->state = RMC_PRELOAD;
226 if ((RK_PWM_TIME_BIT1_MIN < ddata->period) &&
227 (ddata->period < RK_PWM_TIME_BIT1_MAX))
228 ddata->scandata |= (0x01<<ddata->count);
230 if (ddata->count < 0x10)
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)) {
237 input_event(ddata->input, EV_KEY,
239 input_sync(ddata->input);
240 ddata->state = RMC_SEQUENCE;
242 ddata->state = RMC_PRELOAD;
245 ddata->state = RMC_PRELOAD;
250 DBG("S=%d\n", ddata->period);
251 if ((RK_PWM_TIME_RPT_MIN < ddata->period) &&
252 (ddata->period < RK_PWM_TIME_RPT_MAX)) {
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)) {
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)) {
264 mod_timer(&ddata->timer, jiffies
265 + msecs_to_jiffies(110));
268 input_event(ddata->input, EV_KEY,
270 input_sync(ddata->input);
271 ddata->state = RMC_PRELOAD;
281 static void rk_pwm_remotectl_timer(unsigned long _data)
283 struct rkxx_remotectl_drvdata *ddata;
285 ddata = (struct rkxx_remotectl_drvdata *)_data;
286 if (ddata->press != ddata->pre_press) {
287 ddata->pre_press = 0;
289 input_event(ddata->input, EV_KEY, ddata->keycode, 0);
290 input_sync(ddata->input);
292 ddata->state = RMC_PRELOAD;
296 static irqreturn_t rockchip_pwm_irq(int irq, void *dev_id)
298 struct rkxx_remotectl_drvdata *ddata;
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);
307 tasklet_hi_schedule(&ddata->remote_tasklet);
308 DBG("hpr=0x%x\n", val);
310 val = readl_relaxed(ddata->base + PWM_REG_LPR);
311 DBG("lpr=0x%x\n", val);
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);
321 static int rk_pwm_remotectl_hw_init(struct rkxx_remotectl_drvdata *ddata)
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);
345 static int rk_pwm_probe(struct platform_device *pdev)
347 struct rkxx_remotectl_drvdata *ddata;
349 struct input_dev *input;
356 DBG(".. rk pwm remotectl v1.1 init\n");
357 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
359 dev_err(&pdev->dev, "no memory resources defined\n");
362 ddata = devm_kzalloc(&pdev->dev, sizeof(struct rkxx_remotectl_drvdata),
365 dev_err(&pdev->dev, "failed to allocate memory\n");
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");
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);
391 irq = platform_get_irq(pdev, 0);
393 dev_err(&pdev->dev, "cannot find IRQ\n");
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;
406 input_set_capability(input, type, remotectl_button[j].
407 key_table[i].keycode);
410 ret = input_register_device(input);
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);
418 dev_err(&pdev->dev, "cannot claim IRQ %d\n", irq);
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);
429 static int rk_pwm_remove(struct platform_device *pdev)
435 static const struct of_device_id rk_pwm_of_match[] = {
436 { .compatible = "rockchip,remotectl-pwm"},
440 MODULE_DEVICE_TABLE(of, rk_pwm_of_match);
442 static struct platform_driver rk_pwm_driver = {
444 .name = "remotectl-pwm",
445 .of_match_table = rk_pwm_of_match,
447 .probe = rk_pwm_probe,
448 .remove = rk_pwm_remove,
451 module_platform_driver(rk_pwm_driver);
453 MODULE_LICENSE("GPL");