-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
yaml --- r: 202202 b: refs/heads/master c: 312e8e8 h: refs/heads/master v: v3
- Loading branch information
Joonyoung Shim
authored and
Dmitry Torokhov
committed
Jul 4, 2010
1 parent
390c707
commit 2d1464c
Showing
7 changed files
with
290 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
--- | ||
refs/heads/master: 866d7d7b4a4e1d502b136bcc8af605091fe4c7b5 | ||
refs/heads/master: 312e8e8a9e2471b0ada7366497fffb3ff1a40e2c |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,239 @@ | ||
/* | ||
* mcs_touchkey.c - Touchkey driver for MELFAS MCS5000/5080 controller | ||
* | ||
* Copyright (C) 2010 Samsung Electronics Co.Ltd | ||
* Author: HeungJun Kim <riverful.kim@samsung.com> | ||
* Author: Joonyoung Shim <jy0922.shim@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 | ||
* Free Software Foundation; either version 2 of the License, or (at your | ||
* option) any later version. | ||
*/ | ||
|
||
#include <linux/module.h> | ||
#include <linux/init.h> | ||
#include <linux/i2c.h> | ||
#include <linux/i2c/mcs.h> | ||
#include <linux/interrupt.h> | ||
#include <linux/input.h> | ||
#include <linux/irq.h> | ||
#include <linux/slab.h> | ||
|
||
/* MCS5000 Touchkey */ | ||
#define MCS5000_TOUCHKEY_STATUS 0x04 | ||
#define MCS5000_TOUCHKEY_STATUS_PRESS 7 | ||
#define MCS5000_TOUCHKEY_FW 0x0a | ||
#define MCS5000_TOUCHKEY_BASE_VAL 0x61 | ||
|
||
/* MCS5080 Touchkey */ | ||
#define MCS5080_TOUCHKEY_STATUS 0x00 | ||
#define MCS5080_TOUCHKEY_STATUS_PRESS 3 | ||
#define MCS5080_TOUCHKEY_FW 0x01 | ||
#define MCS5080_TOUCHKEY_BASE_VAL 0x1 | ||
|
||
enum mcs_touchkey_type { | ||
MCS5000_TOUCHKEY, | ||
MCS5080_TOUCHKEY, | ||
}; | ||
|
||
struct mcs_touchkey_chip { | ||
unsigned int status_reg; | ||
unsigned int pressbit; | ||
unsigned int press_invert; | ||
unsigned int baseval; | ||
}; | ||
|
||
struct mcs_touchkey_data { | ||
struct i2c_client *client; | ||
struct input_dev *input_dev; | ||
struct mcs_touchkey_chip chip; | ||
unsigned int key_code; | ||
unsigned int key_val; | ||
unsigned short keycodes[]; | ||
}; | ||
|
||
static irqreturn_t mcs_touchkey_interrupt(int irq, void *dev_id) | ||
{ | ||
struct mcs_touchkey_data *data = dev_id; | ||
struct mcs_touchkey_chip *chip = &data->chip; | ||
struct i2c_client *client = data->client; | ||
struct input_dev *input = data->input_dev; | ||
unsigned int key_val; | ||
unsigned int pressed; | ||
int val; | ||
|
||
val = i2c_smbus_read_byte_data(client, chip->status_reg); | ||
if (val < 0) { | ||
dev_err(&client->dev, "i2c read error [%d]\n", val); | ||
goto out; | ||
} | ||
|
||
pressed = (val & (1 << chip->pressbit)) >> chip->pressbit; | ||
if (chip->press_invert) | ||
pressed ^= chip->press_invert; | ||
|
||
/* key_val is 0 when released, so we should use key_val of press. */ | ||
if (pressed) { | ||
key_val = val & (0xff >> (8 - chip->pressbit)); | ||
if (!key_val) | ||
goto out; | ||
key_val -= chip->baseval; | ||
data->key_code = data->keycodes[key_val]; | ||
data->key_val = key_val; | ||
} | ||
|
||
input_event(input, EV_MSC, MSC_SCAN, data->key_val); | ||
input_report_key(input, data->key_code, pressed); | ||
input_sync(input); | ||
|
||
dev_dbg(&client->dev, "key %d %d %s\n", data->key_val, data->key_code, | ||
pressed ? "pressed" : "released"); | ||
|
||
out: | ||
return IRQ_HANDLED; | ||
} | ||
|
||
static int __devinit mcs_touchkey_probe(struct i2c_client *client, | ||
const struct i2c_device_id *id) | ||
{ | ||
const struct mcs_platform_data *pdata; | ||
struct mcs_touchkey_data *data; | ||
struct input_dev *input_dev; | ||
unsigned int fw_reg; | ||
int fw_ver; | ||
int error; | ||
int i; | ||
|
||
pdata = client->dev.platform_data; | ||
if (!pdata) { | ||
dev_err(&client->dev, "no platform data defined\n"); | ||
return -EINVAL; | ||
} | ||
|
||
data = kzalloc(sizeof(struct mcs_touchkey_data) + | ||
sizeof(data->keycodes[0]) * (pdata->key_maxval + 1), | ||
GFP_KERNEL); | ||
input_dev = input_allocate_device(); | ||
if (!data || !input_dev) { | ||
dev_err(&client->dev, "Failed to allocate memory\n"); | ||
error = -ENOMEM; | ||
goto err_free_mem; | ||
} | ||
|
||
data->client = client; | ||
data->input_dev = input_dev; | ||
|
||
if (id->driver_data == MCS5000_TOUCHKEY) { | ||
data->chip.status_reg = MCS5000_TOUCHKEY_STATUS; | ||
data->chip.pressbit = MCS5000_TOUCHKEY_STATUS_PRESS; | ||
data->chip.baseval = MCS5000_TOUCHKEY_BASE_VAL; | ||
fw_reg = MCS5000_TOUCHKEY_FW; | ||
} else { | ||
data->chip.status_reg = MCS5080_TOUCHKEY_STATUS; | ||
data->chip.pressbit = MCS5080_TOUCHKEY_STATUS_PRESS; | ||
data->chip.press_invert = 1; | ||
data->chip.baseval = MCS5080_TOUCHKEY_BASE_VAL; | ||
fw_reg = MCS5080_TOUCHKEY_FW; | ||
} | ||
|
||
fw_ver = i2c_smbus_read_byte_data(client, fw_reg); | ||
if (fw_ver < 0) { | ||
error = fw_ver; | ||
dev_err(&client->dev, "i2c read error[%d]\n", error); | ||
goto err_free_mem; | ||
} | ||
dev_info(&client->dev, "Firmware version: %d\n", fw_ver); | ||
|
||
input_dev->name = "MELPAS MCS Touchkey"; | ||
input_dev->id.bustype = BUS_I2C; | ||
input_dev->dev.parent = &client->dev; | ||
input_dev->evbit[0] = BIT_MASK(EV_KEY); | ||
if (!pdata->no_autorepeat) | ||
input_dev->evbit[0] |= BIT_MASK(EV_REP); | ||
input_dev->keycode = data->keycodes; | ||
input_dev->keycodesize = sizeof(data->keycodes[0]); | ||
input_dev->keycodemax = pdata->key_maxval + 1; | ||
|
||
for (i = 0; i < pdata->keymap_size; i++) { | ||
unsigned int val = MCS_KEY_VAL(pdata->keymap[i]); | ||
unsigned int code = MCS_KEY_CODE(pdata->keymap[i]); | ||
|
||
data->keycodes[val] = code; | ||
__set_bit(code, input_dev->keybit); | ||
} | ||
|
||
input_set_capability(input_dev, EV_MSC, MSC_SCAN); | ||
input_set_drvdata(input_dev, data); | ||
|
||
if (pdata->cfg_pin) | ||
pdata->cfg_pin(); | ||
|
||
error = request_threaded_irq(client->irq, NULL, mcs_touchkey_interrupt, | ||
IRQF_TRIGGER_FALLING, client->dev.driver->name, data); | ||
if (error) { | ||
dev_err(&client->dev, "Failed to register interrupt\n"); | ||
goto err_free_mem; | ||
} | ||
|
||
error = input_register_device(input_dev); | ||
if (error) | ||
goto err_free_irq; | ||
|
||
i2c_set_clientdata(client, data); | ||
return 0; | ||
|
||
err_free_irq: | ||
free_irq(client->irq, data); | ||
err_free_mem: | ||
input_free_device(input_dev); | ||
kfree(data); | ||
return error; | ||
} | ||
|
||
static int __devexit mcs_touchkey_remove(struct i2c_client *client) | ||
{ | ||
struct mcs_touchkey_data *data = i2c_get_clientdata(client); | ||
|
||
free_irq(client->irq, data); | ||
input_unregister_device(data->input_dev); | ||
kfree(data); | ||
|
||
return 0; | ||
} | ||
|
||
static const struct i2c_device_id mcs_touchkey_id[] = { | ||
{ "mcs5000_touchkey", MCS5000_TOUCHKEY }, | ||
{ "mcs5080_touchkey", MCS5080_TOUCHKEY }, | ||
{ } | ||
}; | ||
MODULE_DEVICE_TABLE(i2c, mcs_touchkey_id); | ||
|
||
static struct i2c_driver mcs_touchkey_driver = { | ||
.driver = { | ||
.name = "mcs_touchkey", | ||
.owner = THIS_MODULE, | ||
}, | ||
.probe = mcs_touchkey_probe, | ||
.remove = __devexit_p(mcs_touchkey_remove), | ||
.id_table = mcs_touchkey_id, | ||
}; | ||
|
||
static int __init mcs_touchkey_init(void) | ||
{ | ||
return i2c_add_driver(&mcs_touchkey_driver); | ||
} | ||
|
||
static void __exit mcs_touchkey_exit(void) | ||
{ | ||
i2c_del_driver(&mcs_touchkey_driver); | ||
} | ||
|
||
module_init(mcs_touchkey_init); | ||
module_exit(mcs_touchkey_exit); | ||
|
||
/* Module information */ | ||
MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); | ||
MODULE_AUTHOR("HeungJun Kim <riverful.kim@samsung.com>"); | ||
MODULE_DESCRIPTION("Touchkey driver for MELFAS MCS5000/5080 controller"); | ||
MODULE_LICENSE("GPL"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
/* | ||
* 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 | ||
* Free Software Foundation; either version 2 of the License, or (at your | ||
* option) any later version. | ||
* | ||
*/ | ||
|
||
#ifndef __LINUX_MCS_H | ||
#define __LINUX_MCS_H | ||
|
||
#define MCS_KEY_MAP(v, c) ((((v) & 0xff) << 16) | ((c) & 0xffff)) | ||
#define MCS_KEY_VAL(v) (((v) >> 16) & 0xff) | ||
#define MCS_KEY_CODE(v) ((v) & 0xffff) | ||
|
||
struct mcs_platform_data { | ||
void (*cfg_pin)(void); | ||
|
||
/* touchscreen */ | ||
unsigned int x_size; | ||
unsigned int y_size; | ||
|
||
/* touchkey */ | ||
const u32 *keymap; | ||
unsigned int keymap_size; | ||
unsigned int key_maxval; | ||
bool no_autorepeat; | ||
}; | ||
|
||
#endif /* __LINUX_MCS_H */ |
This file was deleted.
Oops, something went wrong.