Input: atmel_mxt_ts - support capacitive keys
Add support for touch keys found in some Atmel touch controller configurations. Reviewed-by: Claudiu Beznea <claudiu.beznea@microchip.com> Reviewed-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: André Apitzsch <git@apitzsch.eu> Link: https://lore.kernel.org/r/20230407-atmel_keys-v2-2-92446a4343cb@apitzsch.eu Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
This commit is contained in:
parent
272a26186a
commit
9780432158
|
@ -55,6 +55,7 @@
|
||||||
#define MXT_TOUCH_KEYARRAY_T15 15
|
#define MXT_TOUCH_KEYARRAY_T15 15
|
||||||
#define MXT_TOUCH_PROXIMITY_T23 23
|
#define MXT_TOUCH_PROXIMITY_T23 23
|
||||||
#define MXT_TOUCH_PROXKEY_T52 52
|
#define MXT_TOUCH_PROXKEY_T52 52
|
||||||
|
#define MXT_TOUCH_PTC_KEYS_T97 97
|
||||||
#define MXT_PROCI_GRIPFACE_T20 20
|
#define MXT_PROCI_GRIPFACE_T20 20
|
||||||
#define MXT_PROCG_NOISE_T22 22
|
#define MXT_PROCG_NOISE_T22 22
|
||||||
#define MXT_PROCI_ONETOUCH_T24 24
|
#define MXT_PROCI_ONETOUCH_T24 24
|
||||||
|
@ -326,9 +327,13 @@ struct mxt_data {
|
||||||
u16 T71_address;
|
u16 T71_address;
|
||||||
u8 T9_reportid_min;
|
u8 T9_reportid_min;
|
||||||
u8 T9_reportid_max;
|
u8 T9_reportid_max;
|
||||||
|
u8 T15_reportid_min;
|
||||||
|
u8 T15_reportid_max;
|
||||||
u16 T18_address;
|
u16 T18_address;
|
||||||
u8 T19_reportid;
|
u8 T19_reportid;
|
||||||
u16 T44_address;
|
u16 T44_address;
|
||||||
|
u8 T97_reportid_min;
|
||||||
|
u8 T97_reportid_max;
|
||||||
u8 T100_reportid_min;
|
u8 T100_reportid_min;
|
||||||
u8 T100_reportid_max;
|
u8 T100_reportid_max;
|
||||||
|
|
||||||
|
@ -344,6 +349,9 @@ struct mxt_data {
|
||||||
u32 *t19_keymap;
|
u32 *t19_keymap;
|
||||||
unsigned int t19_num_keys;
|
unsigned int t19_num_keys;
|
||||||
|
|
||||||
|
u32 *t15_keymap;
|
||||||
|
unsigned int t15_num_keys;
|
||||||
|
|
||||||
enum mxt_suspend_mode suspend_mode;
|
enum mxt_suspend_mode suspend_mode;
|
||||||
|
|
||||||
u32 wakeup_method;
|
u32 wakeup_method;
|
||||||
|
@ -375,6 +383,7 @@ static bool mxt_object_readable(unsigned int type)
|
||||||
case MXT_TOUCH_KEYARRAY_T15:
|
case MXT_TOUCH_KEYARRAY_T15:
|
||||||
case MXT_TOUCH_PROXIMITY_T23:
|
case MXT_TOUCH_PROXIMITY_T23:
|
||||||
case MXT_TOUCH_PROXKEY_T52:
|
case MXT_TOUCH_PROXKEY_T52:
|
||||||
|
case MXT_TOUCH_PTC_KEYS_T97:
|
||||||
case MXT_TOUCH_MULTITOUCHSCREEN_T100:
|
case MXT_TOUCH_MULTITOUCHSCREEN_T100:
|
||||||
case MXT_PROCI_GRIPFACE_T20:
|
case MXT_PROCI_GRIPFACE_T20:
|
||||||
case MXT_PROCG_NOISE_T22:
|
case MXT_PROCG_NOISE_T22:
|
||||||
|
@ -891,6 +900,24 @@ static void mxt_proc_t9_message(struct mxt_data *data, u8 *message)
|
||||||
data->update_input = true;
|
data->update_input = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void mxt_proc_t15_messages(struct mxt_data *data, u8 *message)
|
||||||
|
{
|
||||||
|
struct input_dev *input_dev = data->input_dev;
|
||||||
|
unsigned long keystates = get_unaligned_le32(&message[2]);
|
||||||
|
int key;
|
||||||
|
|
||||||
|
for (key = 0; key < data->t15_num_keys; key++)
|
||||||
|
input_report_key(input_dev, data->t15_keymap[key],
|
||||||
|
keystates & BIT(key));
|
||||||
|
|
||||||
|
data->update_input = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mxt_proc_t97_messages(struct mxt_data *data, u8 *message)
|
||||||
|
{
|
||||||
|
mxt_proc_t15_messages(data, message);
|
||||||
|
}
|
||||||
|
|
||||||
static void mxt_proc_t100_message(struct mxt_data *data, u8 *message)
|
static void mxt_proc_t100_message(struct mxt_data *data, u8 *message)
|
||||||
{
|
{
|
||||||
struct device *dev = &data->client->dev;
|
struct device *dev = &data->client->dev;
|
||||||
|
@ -1017,6 +1044,12 @@ static int mxt_proc_message(struct mxt_data *data, u8 *message)
|
||||||
} else if (report_id >= data->T9_reportid_min &&
|
} else if (report_id >= data->T9_reportid_min &&
|
||||||
report_id <= data->T9_reportid_max) {
|
report_id <= data->T9_reportid_max) {
|
||||||
mxt_proc_t9_message(data, message);
|
mxt_proc_t9_message(data, message);
|
||||||
|
} else if (report_id >= data->T15_reportid_min &&
|
||||||
|
report_id <= data->T15_reportid_max) {
|
||||||
|
mxt_proc_t15_messages(data, message);
|
||||||
|
} else if (report_id >= data->T97_reportid_min &&
|
||||||
|
report_id <= data->T97_reportid_max) {
|
||||||
|
mxt_proc_t97_messages(data, message);
|
||||||
} else if (report_id >= data->T100_reportid_min &&
|
} else if (report_id >= data->T100_reportid_min &&
|
||||||
report_id <= data->T100_reportid_max) {
|
report_id <= data->T100_reportid_max) {
|
||||||
mxt_proc_t100_message(data, message);
|
mxt_proc_t100_message(data, message);
|
||||||
|
@ -1689,9 +1722,13 @@ static void mxt_free_object_table(struct mxt_data *data)
|
||||||
data->T71_address = 0;
|
data->T71_address = 0;
|
||||||
data->T9_reportid_min = 0;
|
data->T9_reportid_min = 0;
|
||||||
data->T9_reportid_max = 0;
|
data->T9_reportid_max = 0;
|
||||||
|
data->T15_reportid_min = 0;
|
||||||
|
data->T15_reportid_max = 0;
|
||||||
data->T18_address = 0;
|
data->T18_address = 0;
|
||||||
data->T19_reportid = 0;
|
data->T19_reportid = 0;
|
||||||
data->T44_address = 0;
|
data->T44_address = 0;
|
||||||
|
data->T97_reportid_min = 0;
|
||||||
|
data->T97_reportid_max = 0;
|
||||||
data->T100_reportid_min = 0;
|
data->T100_reportid_min = 0;
|
||||||
data->T100_reportid_max = 0;
|
data->T100_reportid_max = 0;
|
||||||
data->max_reportid = 0;
|
data->max_reportid = 0;
|
||||||
|
@ -1764,6 +1801,10 @@ static int mxt_parse_object_table(struct mxt_data *data,
|
||||||
object->num_report_ids - 1;
|
object->num_report_ids - 1;
|
||||||
data->num_touchids = object->num_report_ids;
|
data->num_touchids = object->num_report_ids;
|
||||||
break;
|
break;
|
||||||
|
case MXT_TOUCH_KEYARRAY_T15:
|
||||||
|
data->T15_reportid_min = min_id;
|
||||||
|
data->T15_reportid_max = max_id;
|
||||||
|
break;
|
||||||
case MXT_SPT_COMMSCONFIG_T18:
|
case MXT_SPT_COMMSCONFIG_T18:
|
||||||
data->T18_address = object->start_address;
|
data->T18_address = object->start_address;
|
||||||
break;
|
break;
|
||||||
|
@ -1773,6 +1814,10 @@ static int mxt_parse_object_table(struct mxt_data *data,
|
||||||
case MXT_SPT_GPIOPWM_T19:
|
case MXT_SPT_GPIOPWM_T19:
|
||||||
data->T19_reportid = min_id;
|
data->T19_reportid = min_id;
|
||||||
break;
|
break;
|
||||||
|
case MXT_TOUCH_PTC_KEYS_T97:
|
||||||
|
data->T97_reportid_min = min_id;
|
||||||
|
data->T97_reportid_max = max_id;
|
||||||
|
break;
|
||||||
case MXT_TOUCH_MULTITOUCHSCREEN_T100:
|
case MXT_TOUCH_MULTITOUCHSCREEN_T100:
|
||||||
data->multitouch = MXT_TOUCH_MULTITOUCHSCREEN_T100;
|
data->multitouch = MXT_TOUCH_MULTITOUCHSCREEN_T100;
|
||||||
data->T100_reportid_min = min_id;
|
data->T100_reportid_min = min_id;
|
||||||
|
@ -2050,6 +2095,7 @@ static int mxt_initialize_input_device(struct mxt_data *data)
|
||||||
int error;
|
int error;
|
||||||
unsigned int num_mt_slots;
|
unsigned int num_mt_slots;
|
||||||
unsigned int mt_flags = 0;
|
unsigned int mt_flags = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
switch (data->multitouch) {
|
switch (data->multitouch) {
|
||||||
case MXT_TOUCH_MULTI_T9:
|
case MXT_TOUCH_MULTI_T9:
|
||||||
|
@ -2095,6 +2141,10 @@ static int mxt_initialize_input_device(struct mxt_data *data)
|
||||||
input_dev->open = mxt_input_open;
|
input_dev->open = mxt_input_open;
|
||||||
input_dev->close = mxt_input_close;
|
input_dev->close = mxt_input_close;
|
||||||
|
|
||||||
|
input_dev->keycode = data->t15_keymap;
|
||||||
|
input_dev->keycodemax = data->t15_num_keys;
|
||||||
|
input_dev->keycodesize = sizeof(data->t15_keymap[0]);
|
||||||
|
|
||||||
input_set_capability(input_dev, EV_KEY, BTN_TOUCH);
|
input_set_capability(input_dev, EV_KEY, BTN_TOUCH);
|
||||||
|
|
||||||
/* For single touch */
|
/* For single touch */
|
||||||
|
@ -2162,6 +2212,13 @@ static int mxt_initialize_input_device(struct mxt_data *data)
|
||||||
0, 255, 0, 0);
|
0, 255, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* For T15 and T97 Key Array */
|
||||||
|
if (data->T15_reportid_min || data->T97_reportid_min) {
|
||||||
|
for (i = 0; i < data->t15_num_keys; i++)
|
||||||
|
input_set_capability(input_dev,
|
||||||
|
EV_KEY, data->t15_keymap[i]);
|
||||||
|
}
|
||||||
|
|
||||||
input_set_drvdata(input_dev, data);
|
input_set_drvdata(input_dev, data);
|
||||||
|
|
||||||
error = input_register_device(input_dev);
|
error = input_register_device(input_dev);
|
||||||
|
@ -3080,8 +3137,10 @@ static void mxt_input_close(struct input_dev *dev)
|
||||||
static int mxt_parse_device_properties(struct mxt_data *data)
|
static int mxt_parse_device_properties(struct mxt_data *data)
|
||||||
{
|
{
|
||||||
static const char keymap_property[] = "linux,gpio-keymap";
|
static const char keymap_property[] = "linux,gpio-keymap";
|
||||||
|
static const char buttons_property[] = "linux,keycodes";
|
||||||
struct device *dev = &data->client->dev;
|
struct device *dev = &data->client->dev;
|
||||||
u32 *keymap;
|
u32 *keymap;
|
||||||
|
u32 *buttonmap;
|
||||||
int n_keys;
|
int n_keys;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
|
@ -3111,6 +3170,32 @@ static int mxt_parse_device_properties(struct mxt_data *data)
|
||||||
data->t19_num_keys = n_keys;
|
data->t19_num_keys = n_keys;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (device_property_present(dev, buttons_property)) {
|
||||||
|
n_keys = device_property_count_u32(dev, buttons_property);
|
||||||
|
if (n_keys <= 0) {
|
||||||
|
error = n_keys < 0 ? n_keys : -EINVAL;
|
||||||
|
dev_err(dev, "invalid/malformed '%s' property: %d\n",
|
||||||
|
buttons_property, error);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
buttonmap = devm_kmalloc_array(dev, n_keys, sizeof(*buttonmap),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!buttonmap)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
error = device_property_read_u32_array(dev, buttons_property,
|
||||||
|
buttonmap, n_keys);
|
||||||
|
if (error) {
|
||||||
|
dev_err(dev, "failed to parse '%s' property: %d\n",
|
||||||
|
buttons_property, error);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->t15_keymap = buttonmap;
|
||||||
|
data->t15_num_keys = n_keys;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue