diff options
author | Daniel Hillenbrand <daniel.hillenbrand@codeworkx.de> | 2012-06-16 16:46:27 +0200 |
---|---|---|
committer | Daniel Hillenbrand <daniel.hillenbrand@codeworkx.de> | 2012-06-16 16:46:27 +0200 |
commit | 6e3fda02445d8deb384921edeb67582d4af1494d (patch) | |
tree | 4cff2501535fb94ec6e31ef2798484ab3016590f /drivers/input/keyboard/cypress/cypress-touchkey.c | |
parent | ce7b762837d2ca191580489dd655f8745cc32547 (diff) | |
download | kernel_samsung_smdk4412-6e3fda02445d8deb384921edeb67582d4af1494d.zip kernel_samsung_smdk4412-6e3fda02445d8deb384921edeb67582d4af1494d.tar.gz kernel_samsung_smdk4412-6e3fda02445d8deb384921edeb67582d4af1494d.tar.bz2 |
cypress: user configurable touchled timeout, allow to force disable leds
Diffstat (limited to 'drivers/input/keyboard/cypress/cypress-touchkey.c')
-rw-r--r-- | drivers/input/keyboard/cypress/cypress-touchkey.c | 186 |
1 files changed, 175 insertions, 11 deletions
diff --git a/drivers/input/keyboard/cypress/cypress-touchkey.c b/drivers/input/keyboard/cypress/cypress-touchkey.c index 12d16dd..b36f941 100644 --- a/drivers/input/keyboard/cypress/cypress-touchkey.c +++ b/drivers/input/keyboard/cypress/cypress-touchkey.c @@ -37,6 +37,8 @@ #include <linux/regulator/machine.h> #include "issp_extern.h" +#include "cypress-touchkey.h" + #ifdef CONFIG_TOUCHSCREEN_ATMEL_MXT540E #include <linux/i2c/mxt540e.h> #else @@ -74,6 +76,11 @@ static int touchkey_keycode[3] = { 0, KEY_MENU, KEY_BACK }; #endif static const int touchkey_count = sizeof(touchkey_keycode) / sizeof(int); +struct touchkey_i2c *tkey_i2c_local; +struct timer_list touch_led_timer; +int touch_led_timeout = 3; // timeout for the touchkey backlight in secs +int touch_led_disabled = 0; // 1= force disable the touchkey backlight + #if defined(TK_HAS_AUTOCAL) static u8 home_sensitivity; static u8 search_sensitivity; @@ -651,6 +658,7 @@ static int touchkey_firmware_update(struct touchkey_i2c *tkey_i2c) static irqreturn_t touchkey_interrupt(int irq, void *dev_id) { struct touchkey_i2c *tkey_i2c = dev_id; + static const int ledCmd[] = {TK_CMD_LED_ON, TK_CMD_LED_OFF}; u8 data[3]; int ret; int retry = 10; @@ -684,9 +692,34 @@ static irqreturn_t touchkey_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } - if (pressed) + if (pressed) { set_touchkey_debug('P'); + // enable lights on keydown + if (touch_led_disabled == 0) { + if (touchkey_led_status == TK_CMD_LED_OFF) { + pr_info("[Touchkey] %s: keydown - LED ON\n", __func__); + i2c_touchkey_write(tkey_i2c->client, (u8 *) &ledCmd[0], 1); + touchkey_led_status = TK_CMD_LED_ON; + } + if (timer_pending(&touch_led_timer) == 1) { + mod_timer(&touch_led_timer, jiffies + (HZ * touch_led_timeout)); + } + } + + } else { + // touch led timeout on keyup + if (touch_led_disabled == 0) { + if (timer_pending(&touch_led_timer) == 0) { + pr_info("[Touchkey] %s: keyup - add_timer\n", __func__); + touch_led_timer.expires = jiffies + (HZ * touch_led_timeout); + add_timer(&touch_led_timer); + } else { + mod_timer(&touch_led_timer, jiffies + (HZ * touch_led_timeout)); + } + } + } + if (get_tsp_status() && pressed) printk(KERN_DEBUG "[TouchKey] touchkey pressed but don't send event because touch is pressed.\n"); else { @@ -790,8 +823,9 @@ static irqreturn_t touchkey_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } - if (pressed) + if (pressed) { set_touchkey_debug('P'); + } if (get_tsp_status() && pressed) printk(KERN_DEBUG "[TouchKey] touchkey pressed" @@ -1072,18 +1106,132 @@ static ssize_t touchkey_led_control(struct device *dev, data = ledCmd[data-1]; #endif - ret = i2c_touchkey_write(tkey_i2c->client, (u8 *) &data, 1); + if (touch_led_disabled == 0) { + ret = i2c_touchkey_write(tkey_i2c->client, (u8 *) &data, 1); + } + + if(data == ledCmd[0]) { + if (touch_led_disabled == 0) { + if (timer_pending(&touch_led_timer) == 0) { + pr_info("[Touchkey] %s: add_timer\n", __func__); + touch_led_timer.expires = jiffies + (HZ * touch_led_timeout); + add_timer(&touch_led_timer); + } else { + mod_timer(&touch_led_timer, jiffies + (HZ * touch_led_timeout)); + } + } + } else { + if (timer_pending(&touch_led_timer) == 1) { + pr_info("[Touchkey] %s: del_timer\n", __func__); + del_timer(&touch_led_timer); + } + } if (ret == -ENODEV) { printk(KERN_DEBUG"[Touchkey] error to write i2c\n"); touchled_cmd_reversed = 1; } + pr_info("[TouchKey] %s touchkey_led_status=%d\n", __func__, data); touchkey_led_status = data; return size; } +static ssize_t touch_led_force_disable(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t size) +{ + struct touchkey_i2c *tkey_i2c = dev_get_drvdata(dev); + static const int ledCmd[] = {TK_CMD_LED_ON, TK_CMD_LED_OFF}; + int data, ret; + + ret = sscanf(buf, "%d\n", &data); + if (unlikely(ret != 1)) { + pr_err("[Touchkey] %s err\n", __func__); + return -EINVAL; + } + pr_info("[Touchkey] %s value=%d\n", __func__, data); + + if (data == 1) { + i2c_touchkey_write(tkey_i2c->client, (u8 *) &ledCmd[1], 1); + touchkey_led_status = TK_CMD_LED_OFF; + } + touch_led_disabled = data; + + return size; +} +static DEVICE_ATTR(force_disable, S_IRUGO | S_IWUSR | S_IWGRP, + NULL, touch_led_force_disable); + +static ssize_t touch_led_set_timeout(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t size) +{ + int data; + int ret; + + ret = sscanf(buf, "%d\n", &data); + if (unlikely(ret != 1)) { + pr_err("[TouchKey] %s err\n", __func__); + return -EINVAL; + } + pr_info("[TouchKey] %s new timeout=%d\n", __func__, data); + touch_led_timeout = data; + + return size; +} +static DEVICE_ATTR(timeout, S_IRUGO | S_IWUSR | S_IWGRP, + NULL, touch_led_set_timeout); + +void touch_led_timedout(unsigned long ptr) +{ + pr_info("[TouchKey] %s\n", __func__); + queue_work(tkey_i2c_local->wq, &tkey_i2c_local->work); +} + +void touch_led_timedout_work(struct work_struct *work) +{ + struct touchkey_i2c *tkey_i2c = container_of(work, struct touchkey_i2c, work); + static const int ledCmd[] = {TK_CMD_LED_ON, TK_CMD_LED_OFF}; + + if (touch_led_timeout != 0) + { + pr_info("[TouchKey] %s disabling touchled\n", __func__); + i2c_touchkey_write(tkey_i2c->client, (u8 *) &ledCmd[1], 1); + touchkey_led_status = TK_CMD_LED_OFF; + } +} + +void touchscreen_state_report(int state) +{ + static const int ledCmd[] = {TK_CMD_LED_ON, TK_CMD_LED_OFF}; + + if (touch_led_disabled == 0) { + if (state == 1) { + if(touchkey_led_status == TK_CMD_LED_OFF) { + pr_info("[TouchKey] %s enable touchleds\n", __func__); + i2c_touchkey_write(tkey_i2c_local->client, (u8 *) &ledCmd[0], 1); + touchkey_led_status = TK_CMD_LED_ON; + } else { + if (timer_pending(&touch_led_timer) == 1) { + pr_info("[TouchKey] %s mod_timer\n", __func__); + mod_timer(&touch_led_timer, jiffies + (HZ * touch_led_timeout)); + } + } + } else if (state == 0) { + if (timer_pending(&touch_led_timer) == 1) { + pr_info("[TouchKey] %s mod_timer\n", __func__); + mod_timer(&touch_led_timer, jiffies + (HZ * touch_led_timeout)); + } else if (touchkey_led_status == TK_CMD_LED_ON){ + pr_info("[TouchKey] %s add_timer\n", __func__); + touch_led_timer.expires = jiffies + (HZ * touch_led_timeout); + add_timer(&touch_led_timer); + } + } + } +} + #if defined(CONFIG_TARGET_LOCALE_NAATT) || defined(CONFIG_TARGET_LOCALE_NA) static ssize_t touchkey_menu_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -1463,6 +1611,8 @@ static struct attribute *touchkey_attributes[] = { &dev_attr_autocal_enable.attr, &dev_attr_autocal_stat.attr, #endif + &dev_attr_timeout.attr, + &dev_attr_force_disable.attr, NULL, }; @@ -1503,11 +1653,12 @@ static int i2c_touchkey_probe(struct i2c_client *client, printk(KERN_ERR "[Touchkey] failed to allocate tkey_i2c.\n"); return -ENOMEM; } + tkey_i2c_local = tkey_i2c; input_dev = input_allocate_device(); if (!input_dev) { - printk(KERN_ERR"[Touchkey] failed to allocate input device\n"); + printk(KERN_ERR "[Touchkey] failed to allocate input device\n"); kfree(tkey_i2c); return -ENOMEM; } @@ -1536,7 +1687,7 @@ static int i2c_touchkey_probe(struct i2c_client *client, ret = input_register_device(input_dev); if (ret) { - printk(KERN_ERR"[Touchkey] failed to register input device\n"); + printk(KERN_ERR "[Touchkey] failed to register input device\n"); input_free_device(input_dev); kfree(tkey_i2c); return err; @@ -1571,8 +1722,7 @@ static int i2c_touchkey_probe(struct i2c_client *client, IRQF_DISABLED | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, tkey_i2c->name, tkey_i2c); if (ret < 0) { - printk(KERN_ERR - "[Touchkey]: failed to request irq(%d) - %d\n", + printk(KERN_ERR "[Touchkey]: failed to request irq(%d) - %d\n", tkey_i2c->irq, ret); input_unregister_device(input_dev); touchkey_probe = false; @@ -1592,8 +1742,7 @@ static int i2c_touchkey_probe(struct i2c_client *client, #if defined(TK_HAS_FIRMWARE_UPDATE) ret = touchkey_firmware_update(tkey_i2c); if (ret < 0) { - printk(KERN_ERR - "[Touchkey]: failed firmware updating process (%d)\n", + printk(KERN_ERR "[Touchkey]: failed firmware updating process (%d)\n", ret); input_unregister_device(input_dev); touchkey_probe = false; @@ -1605,6 +1754,17 @@ static int i2c_touchkey_probe(struct i2c_client *client, touchkey_autocalibration(tkey_i2c); #endif set_touchkey_debug('K'); + + // init workqueue + tkey_i2c->wq = create_singlethread_workqueue("tkey_i2c_wq"); + if (!tkey_i2c->wq) { + ret = -ENOMEM; + pr_err("%s: could not create workqueue\n", __func__); + } + + /* this is the thread function we run on the work queue */ + INIT_WORK(&tkey_i2c->work, touch_led_timedout_work); + return 0; } @@ -1641,13 +1801,17 @@ static int __init touchkey_init(void) ret = i2c_add_driver(&touchkey_i2c_driver); if (ret) { - printk(KERN_ERR - "[TouchKey] registration failed, module not inserted.ret= %d\n", + printk(KERN_ERR "[TouchKey] registration failed, module not inserted.ret= %d\n", ret); } #ifdef TEST_JIG_MODE i2c_touchkey_write(tkey_i2c->client, &get_touch, 1); #endif + + // init the touchled timer + init_timer(&touch_led_timer); + touch_led_timer.function = touch_led_timedout; + return ret; } |