aboutsummaryrefslogtreecommitdiffstats
path: root/recipes/linux/linux-2.6.26/boc01/012-081222-cy3218-btns.patch
diff options
context:
space:
mode:
Diffstat (limited to 'recipes/linux/linux-2.6.26/boc01/012-081222-cy3218-btns.patch')
-rw-r--r--recipes/linux/linux-2.6.26/boc01/012-081222-cy3218-btns.patch223
1 files changed, 223 insertions, 0 deletions
diff --git a/recipes/linux/linux-2.6.26/boc01/012-081222-cy3218-btns.patch b/recipes/linux/linux-2.6.26/boc01/012-081222-cy3218-btns.patch
new file mode 100644
index 0000000000..b3cb9b461b
--- /dev/null
+++ b/recipes/linux/linux-2.6.26/boc01/012-081222-cy3218-btns.patch
@@ -0,0 +1,223 @@
+diff -urN linux-2.6.26.orig/drivers/input/misc/cy3218-btns.c linux-2.6.26/drivers/input/misc/cy3218-btns.c
+--- linux-2.6.26.orig/drivers/input/misc/cy3218-btns.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.6.26/drivers/input/misc/cy3218-btns.c 2008-12-22 12:54:47.000000000 +0100
+@@ -0,0 +1,195 @@
++/*
++ * CAPSENSE Interface driver
++ *
++ *
++ * Copyright (C) 2007, CenoSYS (www.cenosys.com).
++ *
++ * Guillaume Ligneul <guillaume.ligneul@gmail.com>
++ * Jeremy Lainé <jeremy.laine@bolloretelecom.eu>
++ *
++ * This software program is licensed subject to the GNU General Public License
++ * (GPL).Version 2,June 1991, available at http://www.fsf.org/copyleft/gpl.html
++ */
++
++#include <linux/init.h>
++#include <linux/input-polldev.h>
++#include <linux/ioport.h>
++#include <linux/module.h>
++#include <linux/i2c.h>
++
++static int capsense_attach_adapter(struct i2c_adapter *adapter);
++static int capsense_detach_client(struct i2c_client *client);
++
++#define CAPSENSE_NAME "Capsense"
++/* i2c configuration */
++#define CAPSENSE_I2C_ADDR 0x25
++// To debug (may be add in include/linux/i2c-id.h)
++#define I2C_DRIVERID_CAPSENSE 98
++#define BUTTONS_POLL_INTERVAL 30 /* msec */
++#define CAP_STATE_GP0 0x88
++#define CAP_STATE_GP1 0x89
++#define MASK0 0x10
++#define MASK1 0x4
++#define MASK2 0x8
++#define MASK3 0x1
++
++
++static int poll_interval = BUTTONS_POLL_INTERVAL;
++module_param_named(poll, poll_interval, uint, 0);
++MODULE_PARM_DESC(poll, "poll interval in msec (30=default)");
++
++static const unsigned short normal_i2c[] = {
++ CAPSENSE_I2C_ADDR , I2C_CLIENT_END
++};
++I2C_CLIENT_INSMOD;
++
++static struct i2c_driver capsense_driver = {
++ .driver = {
++ .name = CAPSENSE_NAME,
++ },
++ .id = I2C_DRIVERID_CAPSENSE,
++ .attach_adapter = &capsense_attach_adapter,
++ .detach_client = &capsense_detach_client,
++};
++
++struct cy3218 {
++ struct input_polled_dev *ipdev;
++ struct i2c_client client;
++ unsigned char key_state;
++};
++
++unsigned short keymap[] = {
++ // GP0
++ KEY_F1,
++ KEY_ENTER,
++ KEY_DOWN,
++ KEY_BACKSPACE,
++ // GP1
++ KEY_UP,
++};
++
++static void handle_buttons(struct input_polled_dev *dev)
++{
++ struct cy3218 *capsense = dev->private;
++ u8 port_value;
++ u8 new_state = 0;
++ u8 changed;
++ int i;
++
++ // read status
++ port_value = i2c_smbus_read_byte_data(&capsense->client, CAP_STATE_GP0);
++ if (port_value & MASK0) new_state |= 0x01;
++ if (port_value & MASK1) new_state |= 0x02;
++ if (port_value & MASK2) new_state |= 0x04;
++ if (port_value & MASK3) new_state |= 0x08;
++
++ port_value = i2c_smbus_read_byte_data(&capsense->client, CAP_STATE_GP1);
++ if (port_value & MASK0) new_state |= 0x10;
++
++ // update keyboard state
++ changed = capsense->key_state ^ new_state;
++ for (i = 0; i < ARRAY_SIZE(keymap); i++)
++ if (changed & (1 << i))
++ input_report_key(dev->input, keymap[i], (new_state & (1 << i)));
++ capsense->key_state = new_state;
++ input_sync(dev->input);
++}
++
++static int
++capsense_probe(struct i2c_adapter *adapter, int addr, int kind)
++{
++ struct cy3218 *capsense;
++ struct input_polled_dev *ipdev;
++ struct input_dev *input;
++ int rc = 0, err = -ENOMEM, i=0;
++
++ capsense = kzalloc(sizeof(*capsense), GFP_KERNEL);
++ if (!capsense)
++ goto failout;
++
++ if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
++ goto failout;
++ }
++
++ ipdev = input_allocate_polled_device();
++ if (!ipdev)
++ goto failout;
++
++ capsense->key_state = 0;
++ capsense->ipdev = ipdev;
++ capsense->client.adapter = adapter;
++ capsense->client.addr = addr;
++ capsense->client.driver = &capsense_driver;
++ strlcpy(capsense->client.name, CAPSENSE_NAME, I2C_NAME_SIZE);
++ i2c_set_clientdata(&capsense->client, capsense);
++
++ rc = i2c_attach_client(&capsense->client);
++ if (rc)
++ goto out_attach;
++
++ ipdev->poll = handle_buttons;
++ ipdev->private = capsense;
++ ipdev->poll_interval = poll_interval;
++
++ input = ipdev->input;
++ input->name = "Capsense buttons";
++ input->phys = "capsense/input0";
++ input->id.bustype = BUS_I2C;
++ input->dev.parent = &capsense->client.dev;
++
++ input->keycode = keymap;
++ input->keycodemax = ARRAY_SIZE(keymap);
++ input->keycodesize = sizeof(unsigned short);
++
++ input_set_capability(input, EV_MSC, MSC_SCAN);
++ set_bit(EV_KEY, ipdev->input->evbit);
++
++ for (i = 0; i < ARRAY_SIZE(keymap); i++)
++ set_bit(keymap[i], ipdev->input->keybit);
++
++ rc = input_register_polled_device(ipdev);
++ if(rc)
++ goto out_polled;
++
++ return 0;
++
++out_polled:
++ i2c_detach_client(&capsense->client);
++out_attach:
++ input_free_polled_device(ipdev);
++failout:
++ return err;
++}
++
++static int
++capsense_attach_adapter (struct i2c_adapter *adapter)
++{
++ return i2c_probe(adapter, &addr_data, capsense_probe);
++}
++
++static int
++capsense_detach_client(struct i2c_client *client)
++{
++ struct cy3218 *capsense = i2c_get_clientdata(client);
++
++ input_unregister_polled_device(capsense->ipdev);
++ i2c_detach_client(&capsense->client);
++ input_free_polled_device(capsense->ipdev);
++ return 0;
++}
++
++static int __init capsense_buttons_init(void)
++{
++ return i2c_add_driver(&capsense_driver);
++}
++
++static void __exit capsense_buttons_exit(void)
++{
++ i2c_del_driver(&capsense_driver);
++}
++
++MODULE_AUTHOR("Guillaume Ligneul <guillaume.ligneul@cenosys.com>");
++MODULE_DESCRIPTION("Capsense CY3218 Input driver");
++MODULE_LICENSE("GPL");
++module_init(capsense_buttons_init);
++module_exit(capsense_buttons_exit);
+diff -urN linux-2.6.26.orig/drivers/input/misc/Kconfig linux-2.6.26/drivers/input/misc/Kconfig
+--- linux-2.6.26.orig/drivers/input/misc/Kconfig 2008-07-13 23:51:29.000000000 +0200
++++ linux-2.6.26/drivers/input/misc/Kconfig 2008-12-22 07:47:08.000000000 +0100
+@@ -197,4 +197,12 @@
+ Say Y here if you want to support the built-in real time clock
+ of the HP SDC controller.
+
++config INPUT_CAPSENSE_BTNS
++ tristate "CAPSENSE CY3218 button interface"
++ select INPUT_POLLDEV
++ help
++ To compile this driver as a module, choose M here: the
++ module will be called cy3218-btns.
++ To change poll interval, invoque poll parameter in msecs.
++
+ endif
+diff -urN linux-2.6.26.orig/drivers/input/misc/Makefile linux-2.6.26/drivers/input/misc/Makefile
+--- linux-2.6.26.orig/drivers/input/misc/Makefile 2008-07-13 23:51:29.000000000 +0200
++++ linux-2.6.26/drivers/input/misc/Makefile 2008-12-22 07:47:19.000000000 +0100
+@@ -19,3 +19,4 @@
+ obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o
+ obj-$(CONFIG_INPUT_UINPUT) += uinput.o
+ obj-$(CONFIG_INPUT_APANEL) += apanel.o
++obj-$(CONFIG_INPUT_CAPSENSE_BTNS) +=cy3218-btns.o