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 | |
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')
-rw-r--r-- | drivers/input/keyboard/cypress/cypress-touchkey.c | 186 | ||||
-rw-r--r-- | drivers/input/keyboard/cypress/cypress-touchkey.h | 23 | ||||
-rw-r--r-- | drivers/input/touchscreen/mms_ts.c | 10 |
3 files changed, 208 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; } diff --git a/drivers/input/keyboard/cypress/cypress-touchkey.h b/drivers/input/keyboard/cypress/cypress-touchkey.h new file mode 100644 index 0000000..61abce2 --- /dev/null +++ b/drivers/input/keyboard/cypress/cypress-touchkey.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2012 The CyanogenMod Project + * + * Authors: Daniel Hillenbrand <codeworkx@cyanogenmod.com> + * Marco Hillenbrand <marco.hillenbrand@googlemail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +void touchscreen_state_report(int state); diff --git a/drivers/input/touchscreen/mms_ts.c b/drivers/input/touchscreen/mms_ts.c index 19a5490..3a7070d 100644 --- a/drivers/input/touchscreen/mms_ts.c +++ b/drivers/input/touchscreen/mms_ts.c @@ -51,6 +51,8 @@ #include <asm/unaligned.h> //#include "mms_ts_fw.h" +#include "../keyboard/cypress/cypress-touchkey.h" + #ifdef CONFIG_INPUT_FBSUSPEND #ifdef CONFIG_DRM #include <drm/drm_backlight.h> @@ -891,6 +893,10 @@ static irqreturn_t mms_ts_interrupt(int irq, void *dev_id) , angle, palm); #else if (info->finger_state[id] != 0) { + + // report state to cypress-touchkey for backlight timeout + touchscreen_state_report(0); + #if defined(SEC_TSP_EVENT_DEBUG) && defined(CONFIG_TARGET_LOCALE_KOR) printk(KERN_DEBUG "[TSP] POS[%d](%4d,%4d)[U] tp = %d\n", id, x, y, touch_is_pressed); @@ -936,6 +942,10 @@ static irqreturn_t mms_ts_interrupt(int irq, void *dev_id) #else if (info->finger_state[id] == 0) { info->finger_state[id] = 1; + + // report state to cypress-touchkey for backlight timeout + touchscreen_state_report(1); + #if defined(SEC_TSP_EVENT_DEBUG) && defined(CONFIG_TARGET_LOCALE_KOR) printk(KERN_DEBUG "[TSP] POS[%d](%4d,%4d)[D] tp = %d\n", id, x, y, touch_is_pressed); |