* [PATCH] input: mcs5000 - Add MCS5000 touchkey support
@ 2010-05-20 6:44 Joonyoung Shim
2010-05-20 7:06 ` Dmitry Torokhov
0 siblings, 1 reply; 4+ messages in thread
From: Joonyoung Shim @ 2010-05-20 6:44 UTC (permalink / raw)
To: dmitry.torokhov; +Cc: riverful.kim, kyungmin.park, linux-input
The MELPAS MCS5000 can use to touchkey controller. This is patch to
support touchkey at original MCS5000 touchscreen driver.
Signed-off-by: HeungJun Kim <riverful.kim@samsung.com>
Signed-off-by: Joonyoung Shim <jy0922.shim@samsung.com>
Reviewed-by: Kyungmin Park <kyungmin.park@samsung.com>
---
drivers/input/touchscreen/Kconfig | 6 +-
drivers/input/touchscreen/mcs5000_ts.c | 245 ++++++++++++++++++++++++--------
include/linux/i2c/mcs5000_ts.h | 17 ++-
3 files changed, 201 insertions(+), 67 deletions(-)
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index cc47198..d569e87 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -202,11 +202,11 @@ config TOUCHSCREEN_WACOM_W8001
module will be called wacom_w8001.
config TOUCHSCREEN_MCS5000
- tristate "MELFAS MCS-5000 touchscreen"
+ tristate "MELFAS MCS5000 touchscreen/touchkey"
depends on I2C
help
- Say Y here if you have the MELFAS MCS-5000 touchscreen controller
- chip in your system.
+ Say Y here if you have the MELFAS MCS5000 touchscreen/touchkey
+ controller chip in your system.
If unsure, say N.
diff --git a/drivers/input/touchscreen/mcs5000_ts.c b/drivers/input/touchscreen/mcs5000_ts.c
index ce8ab02..87842e3 100644
--- a/drivers/input/touchscreen/mcs5000_ts.c
+++ b/drivers/input/touchscreen/mcs5000_ts.c
@@ -1,10 +1,9 @@
/*
- * mcs5000_ts.c - Touchscreen driver for MELFAS MCS-5000 controller
+ * mcs5000_ts.c - Touchscreen/Touchkey driver for MELFAS MCS5000 controller
*
- * Copyright (C) 2009 Samsung Electronics Co.Ltd
+ * Copyright (C) 2009 - 2010 Samsung Electronics Co.Ltd
* Author: Joonyoung Shim <jy0922.shim@samsung.com>
- *
- * Based on wm97xx-core.c
+ * Author: HeungJun Kim <riverful.kim@samsung.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
@@ -22,7 +21,7 @@
#include <linux/irq.h>
#include <linux/slab.h>
-/* Registers */
+/* Touchscreen Registers */
#define MCS5000_TS_STATUS 0x00
#define STATUS_OFFSET 0
#define STATUS_NO (0 << STATUS_OFFSET)
@@ -92,6 +91,21 @@
#define MCS5000_MAX_XC 0x3ff
#define MCS5000_MAX_YC 0x3ff
+/* Touchkey Registers */
+#define MCS5000_TK_LED_ONOFF 0x01
+#define MCS5000_TK_LED_DIMMING 0x02
+#define MCS5000_TK_RESERVED1 0x03
+#define MCS5000_TK_VALUE_STATUS 0x04
+#define MCS5000_TK_RESERVED2 0x05
+#define MCS5000_TK_HW_VERSION 0x06
+#define MCS5000_TK_FW_VERSION 0x0A
+#define MCS5000_TK_MI_VERSION 0x0B
+
+enum mcs5000_type {
+ MCS5000_TOUCHSCREEN,
+ MCS5000_TOUCHKEY,
+};
+
enum mcs5000_ts_read_offset {
READ_INPUT_INFO,
READ_X_POS_UPPER,
@@ -102,15 +116,59 @@ enum mcs5000_ts_read_offset {
};
/* Each client has this additional data */
-struct mcs5000_ts_data {
+struct mcs5000_data {
struct i2c_client *client;
struct input_dev *input_dev;
- const struct mcs5000_ts_platform_data *platform_data;
+ const struct mcs5000_platform_data *pdata;
+ unsigned int type;
+ unsigned int key_code;
};
-static irqreturn_t mcs5000_ts_interrupt(int irq, void *dev_id)
+static unsigned int mcs5000_get_type(struct mcs5000_data *data)
+{
+ return data->type;
+}
+
+static void mcs5000_tk_interrupt(struct mcs5000_data *data)
+{
+ const struct mcs5000_platform_data *pdata = data->pdata;
+ struct i2c_client *client = data->client;
+ struct input_dev *input = data->input_dev;
+ unsigned int key_val;
+ unsigned int key_code;
+ unsigned int pressed;
+ int val;
+ int i;
+
+ val = i2c_smbus_read_byte_data(client, MCS5000_TK_VALUE_STATUS);
+ if (val < 0) {
+ dev_err(&client->dev, "%s, err[%d]\n", __func__, val);
+ return;
+ }
+
+ key_val = val & 0x7f;
+ pressed = val >> 7;
+
+ if (pressed) {
+ for (i = 0; i < pdata->keymap_size; i++) {
+ if (MCS5000_KEY_VAL(pdata->keymap[i]) == key_val) {
+ key_code = MCS5000_KEY_CODE(pdata->keymap[i]);
+ data->key_code = key_code;
+ break;
+ }
+ }
+ } else
+ key_code = data->key_code;
+
+ input_report_key(input, key_code, pressed ? 1 : 0);
+ input_sync(input);
+
+ dev_dbg(&client->dev, "key %d %d %s\n", key_val, key_code,
+ pressed ? "pressed" : "released");
+}
+
+static void mcs5000_ts_interrupt(struct mcs5000_data *data)
{
- struct mcs5000_ts_data *data = dev_id;
struct i2c_client *client = data->client;
u8 buffer[READ_BLOCK_SIZE];
int err;
@@ -121,7 +179,7 @@ static irqreturn_t mcs5000_ts_interrupt(int irq, void *dev_id)
READ_BLOCK_SIZE, buffer);
if (err < 0) {
dev_err(&client->dev, "%s, err[%d]\n", __func__, err);
- goto out;
+ return;
}
switch (buffer[READ_INPUT_INFO]) {
@@ -157,15 +215,29 @@ static irqreturn_t mcs5000_ts_interrupt(int irq, void *dev_id)
buffer[READ_INPUT_INFO]);
break;
}
+}
+
+static irqreturn_t mcs5000_interrupt(int irq, void *dev_id)
+{
+ struct mcs5000_data *data = dev_id;
+
+ switch (mcs5000_get_type(data)) {
+ case MCS5000_TOUCHSCREEN:
+ mcs5000_ts_interrupt(data);
+ break;
+ case MCS5000_TOUCHKEY:
+ mcs5000_tk_interrupt(data);
+ break;
+ default:
+ break;
+ }
- out:
return IRQ_HANDLED;
}
-static void mcs5000_ts_phys_init(struct mcs5000_ts_data *data)
+static void mcs5000_ts_init(struct mcs5000_data *data)
{
- const struct mcs5000_ts_platform_data *platform_data =
- data->platform_data;
+ const struct mcs5000_platform_data *pdata = data->pdata;
struct i2c_client *client = data->client;
/* Touch reset & sleep mode */
@@ -174,30 +246,32 @@ static void mcs5000_ts_phys_init(struct mcs5000_ts_data *data)
/* Touch size */
i2c_smbus_write_byte_data(client, MCS5000_TS_X_SIZE_UPPER,
- platform_data->x_size >> 8);
+ pdata->x_size >> 8);
i2c_smbus_write_byte_data(client, MCS5000_TS_X_SIZE_LOWER,
- platform_data->x_size & 0xff);
+ pdata->x_size & 0xff);
i2c_smbus_write_byte_data(client, MCS5000_TS_Y_SIZE_UPPER,
- platform_data->y_size >> 8);
+ pdata->y_size >> 8);
i2c_smbus_write_byte_data(client, MCS5000_TS_Y_SIZE_LOWER,
- platform_data->y_size & 0xff);
+ pdata->y_size & 0xff);
/* Touch active mode & 80 report rate */
i2c_smbus_write_byte_data(data->client, MCS5000_TS_OP_MODE,
OP_MODE_ACTIVE | REPORT_RATE_80);
}
-static int __devinit mcs5000_ts_probe(struct i2c_client *client,
+static int __devinit mcs5000_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
- struct mcs5000_ts_data *data;
+ struct mcs5000_data *data;
struct input_dev *input_dev;
+ unsigned long irq_flags = 0;
int ret;
+ int i;
if (!client->dev.platform_data)
return -EINVAL;
- data = kzalloc(sizeof(struct mcs5000_ts_data), GFP_KERNEL);
+ data = kzalloc(sizeof(struct mcs5000_data), GFP_KERNEL);
input_dev = input_allocate_device();
if (!data || !input_dev) {
dev_err(&client->dev, "Failed to allocate memory\n");
@@ -207,25 +281,44 @@ static int __devinit mcs5000_ts_probe(struct i2c_client *client,
data->client = client;
data->input_dev = input_dev;
- data->platform_data = client->dev.platform_data;
+ data->pdata = client->dev.platform_data;
+ data->type = id->driver_data;
+
+ switch (mcs5000_get_type(data)) {
+ case MCS5000_TOUCHSCREEN:
+ input_dev->name = "MELPAS MCS5000 Touchscreen";
+ input_dev->evbit[0] = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY);
+ input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+
+ input_set_abs_params(input_dev, ABS_X, 0, MCS5000_MAX_XC, 0, 0);
+ input_set_abs_params(input_dev, ABS_Y, 0, MCS5000_MAX_YC, 0, 0);
+
+ irq_flags = IRQF_TRIGGER_LOW | IRQF_ONESHOT;
+ break;
+ case MCS5000_TOUCHKEY:
+ input_dev->name = "MELPAS MCS5000 Touchkey";
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);;
+
+ for (i = 0; i < data->pdata->keymap_size; i++)
+ __set_bit(MCS5000_KEY_CODE(data->pdata->keymap[i]),
+ input_dev->keybit);
+
+ irq_flags = IRQF_TRIGGER_FALLING;
+ break;
+ default:
+ break;
+ }
- input_dev->name = "MELPAS MCS-5000 Touchscreen";
input_dev->id.bustype = BUS_I2C;
input_dev->dev.parent = &client->dev;
- __set_bit(EV_ABS, input_dev->evbit);
- __set_bit(EV_KEY, input_dev->evbit);
- __set_bit(BTN_TOUCH, input_dev->keybit);
- input_set_abs_params(input_dev, ABS_X, 0, MCS5000_MAX_XC, 0, 0);
- input_set_abs_params(input_dev, ABS_Y, 0, MCS5000_MAX_YC, 0, 0);
-
input_set_drvdata(input_dev, data);
- if (data->platform_data->cfg_pin)
- data->platform_data->cfg_pin();
+ if (data->pdata->cfg_pin)
+ data->pdata->cfg_pin();
- ret = request_threaded_irq(client->irq, NULL, mcs5000_ts_interrupt,
- IRQF_TRIGGER_LOW | IRQF_ONESHOT, "mcs5000_ts", data);
+ ret = request_threaded_irq(client->irq, NULL, mcs5000_interrupt,
+ irq_flags, client->dev.driver->name, data);
if (ret < 0) {
dev_err(&client->dev, "Failed to register interrupt\n");
@@ -236,7 +329,16 @@ static int __devinit mcs5000_ts_probe(struct i2c_client *client,
if (ret < 0)
goto err_free_irq;
- mcs5000_ts_phys_init(data);
+ switch (mcs5000_get_type(data)) {
+ case MCS5000_TOUCHSCREEN:
+ mcs5000_ts_init(data);
+ break;
+ case MCS5000_TOUCHKEY:
+ break;
+ default:
+ break;
+ }
+
i2c_set_clientdata(client, data);
return 0;
@@ -249,9 +351,9 @@ err_free_mem:
return ret;
}
-static int __devexit mcs5000_ts_remove(struct i2c_client *client)
+static int __devexit mcs5000_remove(struct i2c_client *client)
{
- struct mcs5000_ts_data *data = i2c_get_clientdata(client);
+ struct mcs5000_data *data = i2c_get_clientdata(client);
free_irq(client->irq, data);
input_unregister_device(data->input_dev);
@@ -262,58 +364,79 @@ static int __devexit mcs5000_ts_remove(struct i2c_client *client)
}
#ifdef CONFIG_PM
-static int mcs5000_ts_suspend(struct i2c_client *client, pm_message_t mesg)
+static int mcs5000_suspend(struct i2c_client *client, pm_message_t mesg)
{
- /* Touch sleep mode */
- i2c_smbus_write_byte_data(client, MCS5000_TS_OP_MODE, OP_MODE_SLEEP);
+ struct mcs5000_data *data = i2c_get_clientdata(client);
+
+ switch (mcs5000_get_type(data)) {
+ case MCS5000_TOUCHSCREEN:
+ /* Touch sleep mode */
+ i2c_smbus_write_byte_data(client, MCS5000_TS_OP_MODE,
+ OP_MODE_SLEEP);
+ break;
+ case MCS5000_TOUCHKEY:
+ break;
+ default:
+ break;
+ }
return 0;
}
-static int mcs5000_ts_resume(struct i2c_client *client)
+static int mcs5000_resume(struct i2c_client *client)
{
- struct mcs5000_ts_data *data = i2c_get_clientdata(client);
+ struct mcs5000_data *data = i2c_get_clientdata(client);
- mcs5000_ts_phys_init(data);
+ switch (mcs5000_get_type(data)) {
+ case MCS5000_TOUCHSCREEN:
+ mcs5000_ts_init(data);
+ break;
+ case MCS5000_TOUCHKEY:
+ break;
+ default:
+ break;
+ }
return 0;
}
#else
-#define mcs5000_ts_suspend NULL
-#define mcs5000_ts_resume NULL
+#define mcs5000_suspend NULL
+#define mcs5000_resume NULL
#endif
-static const struct i2c_device_id mcs5000_ts_id[] = {
- { "mcs5000_ts", 0 },
+static const struct i2c_device_id mcs5000_id[] = {
+ { "mcs5000_ts", MCS5000_TOUCHSCREEN },
+ { "mcs5000_tk", MCS5000_TOUCHKEY },
{ }
};
-MODULE_DEVICE_TABLE(i2c, mcs5000_ts_id);
+MODULE_DEVICE_TABLE(i2c, mcs5000_id);
-static struct i2c_driver mcs5000_ts_driver = {
- .probe = mcs5000_ts_probe,
- .remove = __devexit_p(mcs5000_ts_remove),
- .suspend = mcs5000_ts_suspend,
- .resume = mcs5000_ts_resume,
+static struct i2c_driver mcs5000_driver = {
+ .probe = mcs5000_probe,
+ .remove = __devexit_p(mcs5000_remove),
+ .suspend = mcs5000_suspend,
+ .resume = mcs5000_resume,
.driver = {
- .name = "mcs5000_ts",
+ .name = "mcs5000",
},
- .id_table = mcs5000_ts_id,
+ .id_table = mcs5000_id,
};
-static int __init mcs5000_ts_init(void)
+static int __init mcs5000_init(void)
{
- return i2c_add_driver(&mcs5000_ts_driver);
+ return i2c_add_driver(&mcs5000_driver);
}
-static void __exit mcs5000_ts_exit(void)
+static void __exit mcs5000_exit(void)
{
- i2c_del_driver(&mcs5000_ts_driver);
+ i2c_del_driver(&mcs5000_driver);
}
-module_init(mcs5000_ts_init);
-module_exit(mcs5000_ts_exit);
+module_init(mcs5000_init);
+module_exit(mcs5000_exit);
/* Module information */
MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
-MODULE_DESCRIPTION("Touchscreen driver for MELFAS MCS-5000 controller");
+MODULE_AUTHOR("HeungJun Kim <riverful.kim@samsung.com>");
+MODULE_DESCRIPTION("Touchscreen/Touchkey driver for MELFAS MCS5000 controller");
MODULE_LICENSE("GPL");
diff --git a/include/linux/i2c/mcs5000_ts.h b/include/linux/i2c/mcs5000_ts.h
index 5a117b5..578e3e5 100644
--- a/include/linux/i2c/mcs5000_ts.h
+++ b/include/linux/i2c/mcs5000_ts.h
@@ -1,8 +1,9 @@
/*
* mcs5000_ts.h
*
- * Copyright (C) 2009 Samsung Electronics Co.Ltd
+ * Copyright (C) 2009 - 2010 Samsung Electronics Co.Ltd
* Author: Joonyoung Shim <jy0922.shim@samsung.com>
+ * Author: HeungJun Kim <riverful.kim@samsung.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
@@ -14,11 +15,21 @@
#ifndef __LINUX_MCS5000_TS_H
#define __LINUX_MCS5000_TS_H
-/* platform data for the MELFAS MCS-5000 touchscreen driver */
-struct mcs5000_ts_platform_data {
+#define MCS5000_KEY_MAP(v, c) ((((v) & 0xff) << 16) | ((c) & 0xffff))
+#define MCS5000_KEY_VAL(v) (((v) >> 16) & 0xff)
+#define MCS5000_KEY_CODE(v) ((v) & 0xffff)
+
+/* platform data for the MELFAS MCS5000 touchscreen/touchkey driver */
+struct mcs5000_platform_data {
void (*cfg_pin)(void);
+
+ /* touchscreen */
int x_size;
int y_size;
+
+ /* touchkey */
+ const uint32_t *keymap;
+ unsigned int keymap_size;
};
#endif /* __LINUX_MCS5000_TS_H */
--
1.7.0.4
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH] input: mcs5000 - Add MCS5000 touchkey support
2010-05-20 6:44 [PATCH] input: mcs5000 - Add MCS5000 touchkey support Joonyoung Shim
@ 2010-05-20 7:06 ` Dmitry Torokhov
2010-05-20 7:42 ` Joonyoung Shim
0 siblings, 1 reply; 4+ messages in thread
From: Dmitry Torokhov @ 2010-05-20 7:06 UTC (permalink / raw)
To: Joonyoung Shim; +Cc: riverful.kim, kyungmin.park, linux-input
Hi Joonyoung,
On Thu, May 20, 2010 at 03:44:29PM +0900, Joonyoung Shim wrote:
> The MELPAS MCS5000 can use to touchkey controller. This is patch to
> support touchkey at original MCS5000 touchscreen driver.
>
Not much of the touchscreen code ends up being reused it seems. Would
not creating a separate keypad driver make more sense?
Also, please amke sure that driver allows remapping the keymap (by
setting keycode, kmeycodemax, keycodesize in input device).
> +
> + key_val = val & 0x7f;
> + pressed = val >> 7;
> +
> + if (pressed) {
> + for (i = 0; i < pdata->keymap_size; i++) {
> + if (MCS5000_KEY_VAL(pdata->keymap[i]) == key_val) {
> + key_code = MCS5000_KEY_CODE(pdata->keymap[i]);
> + data->key_code = key_code;
> + break;
> + }
> + }
> + } else
> + key_code = data->key_code;
Does that mean that controller does not report code of released key?
And we can't have several keys being pressed at once?
> +
> + input_report_key(input, key_code, pressed ? 1 : 0);
> + input_sync(input);
Please also report EV_MSC/MSC_SCAN.
Thanks.
--
Dmitry
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] input: mcs5000 - Add MCS5000 touchkey support
2010-05-20 7:06 ` Dmitry Torokhov
@ 2010-05-20 7:42 ` Joonyoung Shim
2010-05-20 8:15 ` Dmitry Torokhov
0 siblings, 1 reply; 4+ messages in thread
From: Joonyoung Shim @ 2010-05-20 7:42 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: riverful.kim, kyungmin.park, linux-input
On 5/20/2010 4:06 PM, Dmitry Torokhov wrote:
> Hi Joonyoung,
>
> On Thu, May 20, 2010 at 03:44:29PM +0900, Joonyoung Shim wrote:
>> The MELPAS MCS5000 can use to touchkey controller. This is patch to
>> support touchkey at original MCS5000 touchscreen driver.
>>
>
> Not much of the touchscreen code ends up being reused it seems. Would
> not creating a separate keypad driver make more sense?
>
OK, i will make a separate keypad driver and it will support MCS5080
keypad together.
> Also, please amke sure that driver allows remapping the keymap (by
> setting keycode, kmeycodemax, keycodesize in input device).
>
Do you mean a implementation of setkeycode and getkeycode functions?
>> +
>> + key_val = val & 0x7f;
>> + pressed = val >> 7;
>> +
>> + if (pressed) {
>> + for (i = 0; i < pdata->keymap_size; i++) {
>> + if (MCS5000_KEY_VAL(pdata->keymap[i]) == key_val) {
>> + key_code = MCS5000_KEY_CODE(pdata->keymap[i]);
>> + data->key_code = key_code;
>> + break;
>> + }
>> + }
>> + } else
>> + key_code = data->key_code;
>
> Does that mean that controller does not report code of released key?
> And we can't have several keys being pressed at once?
>
Yes, this keypad doesn't report key values when releases and keypad
cannot detect several keys at once, so i saved and used last key_code.
>> +
>> + input_report_key(input, key_code, pressed ? 1 : 0);
>> + input_sync(input);
>
> Please also report EV_MSC/MSC_SCAN.
>
OK.
Thanks.
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] input: mcs5000 - Add MCS5000 touchkey support
2010-05-20 7:42 ` Joonyoung Shim
@ 2010-05-20 8:15 ` Dmitry Torokhov
0 siblings, 0 replies; 4+ messages in thread
From: Dmitry Torokhov @ 2010-05-20 8:15 UTC (permalink / raw)
To: Joonyoung Shim; +Cc: riverful.kim, kyungmin.park, linux-input
On Thu, May 20, 2010 at 04:42:29PM +0900, Joonyoung Shim wrote:
> On 5/20/2010 4:06 PM, Dmitry Torokhov wrote:
> > Hi Joonyoung,
> >
> > On Thu, May 20, 2010 at 03:44:29PM +0900, Joonyoung Shim wrote:
> >> The MELPAS MCS5000 can use to touchkey controller. This is patch to
> >> support touchkey at original MCS5000 touchscreen driver.
> >>
> >
> > Not much of the touchscreen code ends up being reused it seems. Would
> > not creating a separate keypad driver make more sense?
> >
>
> OK, i will make a separate keypad driver and it will support MCS5080
> keypad together.
>
> > Also, please amke sure that driver allows remapping the keymap (by
> > setting keycode, kmeycodemax, keycodesize in input device).
> >
>
> Do you mean a implementation of setkeycode and getkeycode functions?
>
That is another possibility, it all depends on how you organize the
keymap.
--
Dmitry
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2010-05-20 8:16 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-05-20 6:44 [PATCH] input: mcs5000 - Add MCS5000 touchkey support Joonyoung Shim
2010-05-20 7:06 ` Dmitry Torokhov
2010-05-20 7:42 ` Joonyoung Shim
2010-05-20 8:15 ` Dmitry Torokhov
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).