Commit eca3be9b authored by Hans de Goede's avatar Hans de Goede Committed by Dmitry Torokhov

Input: silead - add support for capactive home button found on some x86 tablets

On some x86 tablets with a silead touchscreen the windows logo on the
front is a capacitive home button. Touching this button results in a touch
with bits 12-15 of the Y coordinates set, while normally only the lower 12
are used.

Detect this and report a KEY_LEFTMETA press when this happens. Note for
now we only respond to the Y coordinate bits 12-15 containing 0x01, on some
tablets *without* a capacative button I've noticed these bits containing
0x04 when crossing the edges of the screen.
Acked-by: default avatarRob Herring <robh@kernel.org>
Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
Signed-off-by: default avatarDmitry Torokhov <dmitry.torokhov@gmail.com>
parent da7bdec4
...@@ -23,6 +23,8 @@ Optional properties: ...@@ -23,6 +23,8 @@ Optional properties:
- touchscreen-inverted-y : See touchscreen.txt - touchscreen-inverted-y : See touchscreen.txt
- touchscreen-swapped-x-y : See touchscreen.txt - touchscreen-swapped-x-y : See touchscreen.txt
- silead,max-fingers : maximum number of fingers the touchscreen can detect - silead,max-fingers : maximum number of fingers the touchscreen can detect
- silead,home-button : Boolean, set to true on devices which have a
capacitive home-button build into the touchscreen
- vddio-supply : regulator phandle for controller VDDIO - vddio-supply : regulator phandle for controller VDDIO
- avdd-supply : regulator phandle for controller AVDD - avdd-supply : regulator phandle for controller AVDD
......
...@@ -56,7 +56,7 @@ ...@@ -56,7 +56,7 @@
#define SILEAD_POINT_Y_MSB_OFF 0x01 #define SILEAD_POINT_Y_MSB_OFF 0x01
#define SILEAD_POINT_X_OFF 0x02 #define SILEAD_POINT_X_OFF 0x02
#define SILEAD_POINT_X_MSB_OFF 0x03 #define SILEAD_POINT_X_MSB_OFF 0x03
#define SILEAD_TOUCH_ID_MASK 0xF0 #define SILEAD_EXTRA_DATA_MASK 0xF0
#define SILEAD_CMD_SLEEP_MIN 10000 #define SILEAD_CMD_SLEEP_MIN 10000
#define SILEAD_CMD_SLEEP_MAX 20000 #define SILEAD_CMD_SLEEP_MAX 20000
...@@ -109,6 +109,9 @@ static int silead_ts_request_input_dev(struct silead_ts_data *data) ...@@ -109,6 +109,9 @@ static int silead_ts_request_input_dev(struct silead_ts_data *data)
INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED | INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED |
INPUT_MT_TRACK); INPUT_MT_TRACK);
if (device_property_read_bool(dev, "silead,home-button"))
input_set_capability(data->input, EV_KEY, KEY_LEFTMETA);
data->input->name = SILEAD_TS_NAME; data->input->name = SILEAD_TS_NAME;
data->input->phys = "input/ts"; data->input->phys = "input/ts";
data->input->id.bustype = BUS_I2C; data->input->id.bustype = BUS_I2C;
...@@ -139,7 +142,8 @@ static void silead_ts_read_data(struct i2c_client *client) ...@@ -139,7 +142,8 @@ static void silead_ts_read_data(struct i2c_client *client)
struct input_dev *input = data->input; struct input_dev *input = data->input;
struct device *dev = &client->dev; struct device *dev = &client->dev;
u8 *bufp, buf[SILEAD_TS_DATA_LEN]; u8 *bufp, buf[SILEAD_TS_DATA_LEN];
int touch_nr, error, i; int touch_nr, softbutton, error, i;
bool softbutton_pressed = false;
error = i2c_smbus_read_i2c_block_data(client, SILEAD_REG_DATA, error = i2c_smbus_read_i2c_block_data(client, SILEAD_REG_DATA,
SILEAD_TS_DATA_LEN, buf); SILEAD_TS_DATA_LEN, buf);
...@@ -148,21 +152,40 @@ static void silead_ts_read_data(struct i2c_client *client) ...@@ -148,21 +152,40 @@ static void silead_ts_read_data(struct i2c_client *client)
return; return;
} }
touch_nr = buf[0]; if (buf[0] > data->max_fingers) {
if (touch_nr > data->max_fingers) {
dev_warn(dev, "More touches reported then supported %d > %d\n", dev_warn(dev, "More touches reported then supported %d > %d\n",
touch_nr, data->max_fingers); buf[0], data->max_fingers);
touch_nr = data->max_fingers; buf[0] = data->max_fingers;
} }
touch_nr = 0;
bufp = buf + SILEAD_POINT_DATA_LEN; bufp = buf + SILEAD_POINT_DATA_LEN;
for (i = 0; i < touch_nr; i++, bufp += SILEAD_POINT_DATA_LEN) { for (i = 0; i < buf[0]; i++, bufp += SILEAD_POINT_DATA_LEN) {
/* Bits 4-7 are the touch id */ softbutton = (bufp[SILEAD_POINT_Y_MSB_OFF] &
data->id[i] = (bufp[SILEAD_POINT_X_MSB_OFF] & SILEAD_EXTRA_DATA_MASK) >> 4;
SILEAD_TOUCH_ID_MASK) >> 4;
touchscreen_set_mt_pos(&data->pos[i], &data->prop, if (softbutton) {
/*
* For now only respond to softbutton == 0x01, some
* tablets *without* a capacative button send 0x04
* when crossing the edges of the screen.
*/
if (softbutton == 0x01)
softbutton_pressed = true;
continue;
}
/*
* Bits 4-7 are the touch id, note not all models have
* hardware touch ids so atm we don't use these.
*/
data->id[touch_nr] = (bufp[SILEAD_POINT_X_MSB_OFF] &
SILEAD_EXTRA_DATA_MASK) >> 4;
touchscreen_set_mt_pos(&data->pos[touch_nr], &data->prop,
get_unaligned_le16(&bufp[SILEAD_POINT_X_OFF]) & 0xfff, get_unaligned_le16(&bufp[SILEAD_POINT_X_OFF]) & 0xfff,
get_unaligned_le16(&bufp[SILEAD_POINT_Y_OFF]) & 0xfff); get_unaligned_le16(&bufp[SILEAD_POINT_Y_OFF]) & 0xfff);
touch_nr++;
} }
input_mt_assign_slots(input, data->slots, data->pos, touch_nr, 0); input_mt_assign_slots(input, data->slots, data->pos, touch_nr, 0);
...@@ -178,6 +201,7 @@ static void silead_ts_read_data(struct i2c_client *client) ...@@ -178,6 +201,7 @@ static void silead_ts_read_data(struct i2c_client *client)
} }
input_mt_sync_frame(input); input_mt_sync_frame(input);
input_report_key(input, KEY_LEFTMETA, softbutton_pressed);
input_sync(input); input_sync(input);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment