diff --git a/arch/arm/mach-s5pv210/include/mach/gpio-settings.h b/arch/arm/mach-s5pv210/include/mach/gpio-settings.h index 3cb7820..0af183d 100644 --- a/arch/arm/mach-s5pv210/include/mach/gpio-settings.h +++ b/arch/arm/mach-s5pv210/include/mach/gpio-settings.h @@ -486,7 +486,7 @@ static unsigned int sleep_gpio_table[][3] = // GPJ3 ------------------------------------------------- {S5PV210_GPJ3(0), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN}, //_3_TOUCH_SDA_28V {S5PV210_GPJ3(1), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN}, //_3_TOUCH_SCL_28V - {S5PV210_GPJ3(2), S3C_GPIO_SLP_OUT0, S3C_GPIO_PULL_NONE}, //_3_GPIO_TOUCH_EN + {S5PV210_GPJ3(2), S3C_GPIO_SLP_PREV, S3C_GPIO_PULL_NONE}, //_3_GPIO_TOUCH_EN {S5PV210_GPJ3(3), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_DOWN}, //GPIO_GPJ33 {S5PV210_GPJ3(4), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE}, //GPIO_USB_SDA_28V {S5PV210_GPJ3(5), S3C_GPIO_SLP_INPUT, S3C_GPIO_PULL_NONE}, //GPIO_USB_SCL_28V diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 68b59bc..61a5003 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -445,5 +445,13 @@ config KEYPAD_S3C To compile this driver as a module, choose M here: the module will be called s3c-keypad. +config KEYPAD_CYPRESS_TOUCH_BLN + bool "Cypress touch keypad: use backlight notification" + depends on KEYPAD_CYPRESS_TOUCH + default y + help + Say Y here to enable the backlight notification + for android led-notification (modified liblight needed) + endif diff --git a/drivers/input/keyboard/cypress/cypress-touchkey.c b/drivers/input/keyboard/cypress/cypress-touchkey.c index 1605985..a0b0ad8 100644 --- a/drivers/input/keyboard/cypress/cypress-touchkey.c +++ b/drivers/input/keyboard/cypress/cypress-touchkey.c @@ -1,6 +1,7 @@ /* * Copyright 2006-2010, Cypress Semiconductor Corporation. * Copyright (C) 2010, Samsung Electronics Co. Ltd. All Rights Reserved. + * Copyright (C) 2011, Michael Richter (alias neldar) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -47,6 +48,16 @@ #define DEVICE_NAME "melfas_touchkey" +#ifdef CONFIG_KEYPAD_CYPRESS_TOUCH_BLN +#include +#define BACKLIGHTNOTIFICATION_VERSION 8 + +bool bln_enabled = false; // indicates if BLN function is enabled/allowed (default: false, app enables it on boot) +bool bln_notification_ongoing= false; // indicates ongoing LED Notification +bool bln_blink_enabled = false; // indicates blink is set +struct cypress_touchkey_devdata *bln_devdata; // keep a reference to the devdata +#endif + struct cypress_touchkey_devdata { struct i2c_client *client; struct input_dev *input_dev; @@ -229,6 +240,14 @@ static void cypress_touchkey_early_suspend(struct early_suspend *h) return; disable_irq(devdata->client->irq); + +#ifdef CONFIG_KEYPAD_CYPRESS_TOUCH_BLN + /* + * Disallow powering off the touchkey controller + * while a led notification is ongoing + */ + if(!bln_notification_ongoing) +#endif devdata->pdata->touchkey_onoff(TOUCHKEY_OFF); all_keys_up(devdata); @@ -514,6 +533,178 @@ static DEVICE_ATTR(brightness, 0664, NULL, static DEVICE_ATTR(enable_disable, 0664, NULL, touchkey_enable_disable); #endif + +#ifdef CONFIG_KEYPAD_CYPRESS_TOUCH_BLN +/* bln start */ + +static void enable_touchkey_backlights(void){ + i2c_touchkey_write_byte(bln_devdata, bln_devdata->backlight_on); +} + +static void disable_touchkey_backlights(void){ + i2c_touchkey_write_byte(bln_devdata, bln_devdata->backlight_off); +} + +static void enable_led_notification(void){ + if (bln_enabled){ + /* is_powering_on signals whether touchkey lights are used for touchmode */ + pr_info("%s: bln interface enabled\n", __FUNCTION__); //remove me + + if (bln_devdata->is_powering_on){ + pr_info("%s: not in touchmode\n", __FUNCTION__); //remove me + /* signal ongoing led notification */ + bln_notification_ongoing = true; + + /* + * power on the touchkey controller + * This is actually not needed, but it is intentionally + * left for the case that the early_resume() function + * did not power on the touchkey controller for some reasons + */ + pr_info("%s: enable vdd\n", __FUNCTION__); //remove me + bln_devdata->pdata->touchkey_onoff(TOUCHKEY_ON); + + /* write to i2cbus, enable backlights */ + pr_info("%s: enable lights\n", __FUNCTION__); //remove me + enable_touchkey_backlights(); + + pr_info("%s: notification led enabled\n", __FUNCTION__); + } + else + pr_info("%s: cannot set notification led, touchkeys are enabled\n",__FUNCTION__); + } +} + +static void disable_led_notification(void){ + pr_info("%s: notification led disabled\n", __FUNCTION__); + + /* disable the blink state */ + bln_blink_enabled = false; + + /* if touchkeys lights are not used for touchmode */ + if (bln_devdata->is_powering_on){ + disable_touchkey_backlights(); + } + + /* signal led notification is disabled */ + bln_notification_ongoing = false; +} + +static ssize_t backlightnotification_status_read(struct device *dev, struct device_attribute *attr, char *buf) { + return sprintf(buf,"%u\n",(bln_enabled ? 1 : 0)); +} +static ssize_t backlightnotification_status_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + unsigned int data; + if(sscanf(buf, "%u\n", &data) == 1) { + pr_devel("%s: %u \n", __FUNCTION__, data); + if(data == 0 || data == 1){ + + if(data == 1){ + pr_info("%s: backlightnotification function enabled\n", __FUNCTION__); + bln_enabled = true; + } + + if(data == 0){ + pr_info("%s: backlightnotification function disabled\n", __FUNCTION__); + bln_enabled = false; + if (bln_notification_ongoing) + disable_led_notification(); + } + } + else + pr_info("%s: invalid input range %u\n", __FUNCTION__, data); + } + else + pr_info("%s: invalid input\n", __FUNCTION__); + + return size; +} + +static ssize_t notification_led_status_read(struct device *dev, struct device_attribute *attr, char *buf) { + return sprintf(buf,"%u\n", (bln_notification_ongoing ? 1 : 0)); +} + +static ssize_t notification_led_status_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + unsigned int data; + + if(sscanf(buf, "%u\n", &data) == 1) { + if(data == 0 || data == 1){ + pr_devel("%s: %u \n", __FUNCTION__, data); + if (data == 1) + enable_led_notification(); + + if(data == 0) + disable_led_notification(); + + } else + pr_info("%s: wrong input %u\n", __FUNCTION__, data); + } else + pr_info("%s: input error\n", __FUNCTION__); + + return size; +} + +static ssize_t blink_control_read(struct device *dev, struct device_attribute *attr, char *buf) { + return sprintf(buf,"%u\n", (bln_blink_enabled ? 1 : 0)); +} + +static ssize_t blink_control_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) +{ + unsigned int data; + + if(sscanf(buf, "%u\n", &data) == 1) { + if(data == 0 || data == 1){ + if (bln_notification_ongoing){ + pr_devel("%s: %u \n", __FUNCTION__, data); + if (data == 1){ + bln_blink_enabled = true; + disable_touchkey_backlights(); + } + + if(data == 0){ + bln_blink_enabled = false; + enable_touchkey_backlights(); + } + } + + } else + pr_info("%s: wrong input %u\n", __FUNCTION__, data); + } else + pr_info("%s: input error\n", __FUNCTION__); + + return size; +} + +static ssize_t backlightnotification_version(struct device *dev, struct device_attribute *attr, char *buf) { + return sprintf(buf, "%u\n", BACKLIGHTNOTIFICATION_VERSION); +} + +static DEVICE_ATTR(blink_control, S_IRUGO | S_IWUGO , blink_control_read, blink_control_write); +static DEVICE_ATTR(enabled, S_IRUGO | S_IWUGO , backlightnotification_status_read, backlightnotification_status_write); +static DEVICE_ATTR(notification_led, S_IRUGO | S_IWUGO , notification_led_status_read, notification_led_status_write); +static DEVICE_ATTR(version, S_IRUGO , backlightnotification_version, NULL); + +static struct attribute *bln_interface_attributes[] = { + &dev_attr_blink_control.attr, + &dev_attr_enabled.attr, + &dev_attr_notification_led.attr, + &dev_attr_version.attr, + NULL +}; + +static struct attribute_group bln_interface_attributes_group = { + .attrs = bln_interface_attributes, +}; + +static struct miscdevice backlightnotification_device = { + .minor = MISC_DYNAMIC_MINOR, + .name = "backlightnotification", +}; +/* bln end */ +#endif + static int cypress_touchkey_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -665,6 +856,27 @@ static int cypress_touchkey_probe(struct i2c_client *client, data[1], data[2]); #endif +#ifdef CONFIG_KEYPAD_CYPRESS_TOUCH_BLN + pr_info("%s misc_register(%s)\n", __FUNCTION__, backlightnotification_device.name); + err = misc_register(&backlightnotification_device); + if (err) { + pr_err("%s misc_register(%s) fail\n", __FUNCTION__, backlightnotification_device.name); + }else { + /* + * keep a reference to the devdata, + * misc driver does not give access to it (or i missed that somewhere) + */ + bln_devdata = devdata; + + /* add the backlightnotification attributes */ + if (sysfs_create_group(&backlightnotification_device.this_device->kobj, &bln_interface_attributes_group) < 0) + { + pr_err("%s sysfs_create_group fail\n", __FUNCTION__); + pr_err("Failed to create sysfs group for device (%s)!\n", backlightnotification_device.name); + } + } +#endif + return 0; err_req_irq: @@ -684,6 +896,10 @@ err_null_keycodes: static int __devexit i2c_touchkey_remove(struct i2c_client *client) { struct cypress_touchkey_devdata *devdata = i2c_get_clientdata(client); + +#ifdef CONFIG_KEYPAD_CYPRESS_TOUCH_BLN + misc_deregister(&backlightnotification_device); +#endif unregister_early_suspend(&devdata->early_suspend); /* If the device is dead IRQs are disabled, we need to rebalance them */