diff --git a/Input-atmel_mxt_ts-add-support-for-Google-Pixel-2.patch b/Input-atmel_mxt_ts-add-support-for-Google-Pixel-2.patch new file mode 100644 index 000000000..2e8af3375 --- /dev/null +++ b/Input-atmel_mxt_ts-add-support-for-Google-Pixel-2.patch @@ -0,0 +1,223 @@ +From: Dmitry Torokhov +Date: Tue, 7 Apr 2015 16:30:01 -0700 +Subject: [PATCH] Input: atmel_mxt_ts - add support for Google Pixel 2 + +This change allows atmel_mxt_ts to bind to ACPI-enumerated devices in +Google Pixel 2 (2015). + +While newer version of ACPI standard allow use of device-tree-like +properties in device descriptions, the version of ACPI implemented in +Google BIOS does not support them, and we have to resort to DMI data to +specify exact characteristics of the devices (touchpad vs. touchscreen, +GPIO to button mapping, etc). + +Pixel 1 continues to use i2c devices and platform data created by +chromeos-laptop driver, since ACPI does not enumerate them. + +Reviewed-by: Javier Martinez Canillas +Tested-by: Javier Martinez Canillas +Signed-off-by: Dmitry Torokhov +--- + drivers/input/touchscreen/atmel_mxt_ts.c | 141 ++++++++++++++++++++++++++++--- + 1 file changed, 130 insertions(+), 11 deletions(-) + +diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c +index 2875ddf37289..40b98dda8f38 100644 +--- a/drivers/input/touchscreen/atmel_mxt_ts.c ++++ b/drivers/input/touchscreen/atmel_mxt_ts.c +@@ -14,6 +14,8 @@ + * + */ + ++#include ++#include + #include + #include + #include +@@ -2371,7 +2373,7 @@ static void mxt_input_close(struct input_dev *dev) + } + + #ifdef CONFIG_OF +-static struct mxt_platform_data *mxt_parse_dt(struct i2c_client *client) ++static const struct mxt_platform_data *mxt_parse_dt(struct i2c_client *client) + { + struct mxt_platform_data *pdata; + u32 *keymap; +@@ -2379,7 +2381,7 @@ static struct mxt_platform_data *mxt_parse_dt(struct i2c_client *client) + int proplen, i, ret; + + if (!client->dev.of_node) +- return ERR_PTR(-ENODEV); ++ return ERR_PTR(-ENOENT); + + pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) +@@ -2410,25 +2412,132 @@ static struct mxt_platform_data *mxt_parse_dt(struct i2c_client *client) + return pdata; + } + #else +-static struct mxt_platform_data *mxt_parse_dt(struct i2c_client *client) ++static const struct mxt_platform_data *mxt_parse_dt(struct i2c_client *client) + { +- dev_dbg(&client->dev, "No platform data specified\n"); +- return ERR_PTR(-EINVAL); ++ return ERR_PTR(-ENOENT); ++} ++#endif ++ ++#ifdef CONFIG_ACPI ++ ++struct mxt_acpi_platform_data { ++ const char *hid; ++ struct mxt_platform_data pdata; ++}; ++ ++static unsigned int samus_touchpad_buttons[] = { ++ KEY_RESERVED, ++ KEY_RESERVED, ++ KEY_RESERVED, ++ BTN_LEFT ++}; ++ ++static struct mxt_acpi_platform_data samus_platform_data[] = { ++ { ++ /* Touchpad */ ++ .hid = "ATML0000", ++ .pdata = { ++ .t19_num_keys = ARRAY_SIZE(samus_touchpad_buttons), ++ .t19_keymap = samus_touchpad_buttons, ++ }, ++ }, ++ { ++ /* Touchscreen */ ++ .hid = "ATML0001", ++ }, ++ { } ++}; ++ ++static const struct dmi_system_id mxt_dmi_table[] = { ++ { ++ /* 2015 Google Pixel */ ++ .ident = "Chromebook Pixel 2", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "Samus"), ++ }, ++ .driver_data = samus_platform_data, ++ }, ++ { } ++}; ++ ++static const struct mxt_platform_data *mxt_parse_acpi(struct i2c_client *client) ++{ ++ struct acpi_device *adev; ++ const struct dmi_system_id *system_id; ++ const struct mxt_acpi_platform_data *acpi_pdata; ++ ++ /* ++ * Ignore ACPI devices representing bootloader mode. ++ * ++ * This is a bit of a hack: Google Chromebook BIOS creates ACPI ++ * devices for both application and bootloader modes, but we are ++ * interested in application mode only (if device is in bootloader ++ * mode we'll end up switching into application anyway). So far ++ * application mode addresses were all above 0x40, so we'll use it ++ * as a threshold. ++ */ ++ if (client->addr < 0x40) ++ return ERR_PTR(-ENXIO); ++ ++ adev = ACPI_COMPANION(&client->dev); ++ if (!adev) ++ return ERR_PTR(-ENOENT); ++ ++ system_id = dmi_first_match(mxt_dmi_table); ++ if (!system_id) ++ return ERR_PTR(-ENOENT); ++ ++ acpi_pdata = system_id->driver_data; ++ if (!acpi_pdata) ++ return ERR_PTR(-ENOENT); ++ ++ while (acpi_pdata->hid) { ++ if (!strcmp(acpi_device_hid(adev), acpi_pdata->hid)) ++ return &acpi_pdata->pdata; ++ ++ acpi_pdata++; ++ } ++ ++ return ERR_PTR(-ENOENT); ++} ++#else ++static const struct mxt_platform_data *mxt_parse_acpi(struct i2c_client *client) ++{ ++ return ERR_PTR(-ENOENT); + } + #endif + ++static const struct mxt_platform_data * ++mxt_get_platform_data(struct i2c_client *client) ++{ ++ const struct mxt_platform_data *pdata; ++ ++ pdata = dev_get_platdata(&client->dev); ++ if (pdata) ++ return pdata; ++ ++ pdata = mxt_parse_dt(client); ++ if (!IS_ERR(pdata) || PTR_ERR(pdata) != -ENOENT) ++ return pdata; ++ ++ pdata = mxt_parse_acpi(client); ++ if (!IS_ERR(pdata) || PTR_ERR(pdata) != -ENOENT) ++ return pdata; ++ ++ dev_err(&client->dev, "No platform data specified\n"); ++ return ERR_PTR(-EINVAL); ++} ++ + static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id) + { + struct mxt_data *data; + const struct mxt_platform_data *pdata; + int error; + +- pdata = dev_get_platdata(&client->dev); +- if (!pdata) { +- pdata = mxt_parse_dt(client); +- if (IS_ERR(pdata)) +- return PTR_ERR(pdata); +- } ++ pdata = mxt_get_platform_data(client); ++ if (IS_ERR(pdata)) ++ return PTR_ERR(pdata); + + data = kzalloc(sizeof(struct mxt_data), GFP_KERNEL); + if (!data) { +@@ -2536,6 +2645,15 @@ static const struct of_device_id mxt_of_match[] = { + }; + MODULE_DEVICE_TABLE(of, mxt_of_match); + ++#ifdef CONFIG_ACPI ++static const struct acpi_device_id mxt_acpi_id[] = { ++ { "ATML0000", 0 }, /* Touchpad */ ++ { "ATML0001", 0 }, /* Touchscreen */ ++ { } ++}; ++MODULE_DEVICE_TABLE(acpi, mxt_acpi_id); ++#endif ++ + static const struct i2c_device_id mxt_id[] = { + { "qt602240_ts", 0 }, + { "atmel_mxt_ts", 0 }, +@@ -2550,6 +2668,7 @@ static struct i2c_driver mxt_driver = { + .name = "atmel_mxt_ts", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(mxt_of_match), ++ .acpi_match_table = ACPI_PTR(mxt_acpi_id), + .pm = &mxt_pm_ops, + }, + .probe = mxt_probe, +-- +2.1.0 + diff --git a/Input-atmel_mxt_ts-implement-support-for-T100-touch-.patch b/Input-atmel_mxt_ts-implement-support-for-T100-touch-.patch new file mode 100644 index 000000000..8dbdfb1cb --- /dev/null +++ b/Input-atmel_mxt_ts-implement-support-for-T100-touch-.patch @@ -0,0 +1,515 @@ +From: Nick Dyer +Date: Mon, 6 Apr 2015 11:25:13 -0700 +Subject: [PATCH] Input: atmel_mxt_ts - implement support for T100 touch object + +Add support for the new T100 object which replaces the previous T9 +multitouch touchscreen object in recent maXTouch devices. T100 provides +improved reporting with selectable auxiliary information, and a type field +for hover/stylus/glove reporting. + +The hovering finger support was based on Chung-Yih's work in the ChromiumOS +downstream kernel: + +https://chromium-review.googlesource.com/#/c/219280/ + +Signed-off-by: Nick Dyer +Acked-by: Yufeng Shen +[javier: Factor out T9 and T100 init functions and rework hover support] +Signed-off-by: Javier Martinez Canillas +Signed-off-by: Dmitry Torokhov +--- + drivers/input/touchscreen/atmel_mxt_ts.c | 345 ++++++++++++++++++++++++++++--- + 1 file changed, 318 insertions(+), 27 deletions(-) + +diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c +index 95ee92a91bd2..1b3b845d92f4 100644 +--- a/drivers/input/touchscreen/atmel_mxt_ts.c ++++ b/drivers/input/touchscreen/atmel_mxt_ts.c +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + + /* Version */ + #define MXT_VER_20 20 +@@ -79,6 +80,7 @@ + #define MXT_SPT_DIGITIZER_T43 43 + #define MXT_SPT_MESSAGECOUNT_T44 44 + #define MXT_SPT_CTECONFIG_T46 46 ++#define MXT_TOUCH_MULTITOUCHSCREEN_T100 100 + + /* MXT_GEN_MESSAGE_T5 object */ + #define MXT_RPTID_NOMSG 0xff +@@ -185,6 +187,36 @@ struct t9_range { + #define MXT_RESET_VALUE 0x01 + #define MXT_BACKUP_VALUE 0x55 + ++/* T100 Multiple Touch Touchscreen */ ++#define MXT_T100_CTRL 0 ++#define MXT_T100_CFG1 1 ++#define MXT_T100_TCHAUX 3 ++#define MXT_T100_XRANGE 13 ++#define MXT_T100_YRANGE 24 ++ ++#define MXT_T100_CFG_SWITCHXY BIT(5) ++ ++#define MXT_T100_TCHAUX_VECT BIT(0) ++#define MXT_T100_TCHAUX_AMPL BIT(1) ++#define MXT_T100_TCHAUX_AREA BIT(2) ++ ++#define MXT_T100_DETECT BIT(7) ++#define MXT_T100_TYPE_MASK 0x70 ++ ++enum t100_type { ++ MXT_T100_TYPE_FINGER = 1, ++ MXT_T100_TYPE_PASSIVE_STYLUS = 2, ++ MXT_T100_TYPE_HOVERING_FINGER = 4, ++ MXT_T100_TYPE_GLOVE = 5, ++ MXT_T100_TYPE_LARGE_TOUCH = 6, ++}; ++ ++#define MXT_DISTANCE_ACTIVE_TOUCH 0 ++#define MXT_DISTANCE_HOVERING 1 ++ ++#define MXT_TOUCH_MAJOR_DEFAULT 1 ++#define MXT_PRESSURE_DEFAULT 1 ++ + /* Delay times */ + #define MXT_BACKUP_TIME 50 /* msec */ + #define MXT_RESET_TIME 200 /* msec */ +@@ -244,6 +276,9 @@ struct mxt_data { + unsigned int max_y; + bool in_bootloader; + u16 mem_size; ++ u8 t100_aux_ampl; ++ u8 t100_aux_area; ++ u8 t100_aux_vect; + u8 max_reportid; + u32 config_crc; + u32 info_crc; +@@ -253,6 +288,7 @@ struct mxt_data { + bool update_input; + u8 last_message_count; + u8 num_touchids; ++ u8 multitouch; + + /* Cached parameters from object table */ + u16 T5_address; +@@ -264,6 +300,8 @@ struct mxt_data { + u8 T9_reportid_max; + u8 T19_reportid; + u16 T44_address; ++ u8 T100_reportid_min; ++ u8 T100_reportid_max; + + /* for fw update in bootloader */ + struct completion bl_completion; +@@ -771,6 +809,114 @@ static void mxt_proc_t9_message(struct mxt_data *data, u8 *message) + data->update_input = true; + } + ++static void mxt_proc_t100_message(struct mxt_data *data, u8 *message) ++{ ++ struct device *dev = &data->client->dev; ++ struct input_dev *input_dev = data->input_dev; ++ int id; ++ u8 status; ++ u8 type = 0; ++ u16 x; ++ u16 y; ++ int distance = 0; ++ int tool = 0; ++ u8 major = 0; ++ u8 pressure = 0; ++ u8 orientation = 0; ++ ++ id = message[0] - data->T100_reportid_min - 2; ++ ++ /* ignore SCRSTATUS events */ ++ if (id < 0) ++ return; ++ ++ status = message[1]; ++ x = get_unaligned_le16(&message[2]); ++ y = get_unaligned_le16(&message[4]); ++ ++ if (status & MXT_T100_DETECT) { ++ type = (status & MXT_T100_TYPE_MASK) >> 4; ++ ++ switch (type) { ++ case MXT_T100_TYPE_HOVERING_FINGER: ++ tool = MT_TOOL_FINGER; ++ distance = MXT_DISTANCE_HOVERING; ++ ++ if (data->t100_aux_vect) ++ orientation = message[data->t100_aux_vect]; ++ ++ break; ++ ++ case MXT_T100_TYPE_FINGER: ++ case MXT_T100_TYPE_GLOVE: ++ tool = MT_TOOL_FINGER; ++ distance = MXT_DISTANCE_ACTIVE_TOUCH; ++ ++ if (data->t100_aux_area) ++ major = message[data->t100_aux_area]; ++ ++ if (data->t100_aux_ampl) ++ pressure = message[data->t100_aux_ampl]; ++ ++ if (data->t100_aux_vect) ++ orientation = message[data->t100_aux_vect]; ++ ++ break; ++ ++ case MXT_T100_TYPE_PASSIVE_STYLUS: ++ tool = MT_TOOL_PEN; ++ ++ /* ++ * Passive stylus is reported with size zero so ++ * hardcode. ++ */ ++ major = MXT_TOUCH_MAJOR_DEFAULT; ++ ++ if (data->t100_aux_ampl) ++ pressure = message[data->t100_aux_ampl]; ++ ++ break; ++ ++ case MXT_T100_TYPE_LARGE_TOUCH: ++ /* Ignore suppressed touch */ ++ break; ++ ++ default: ++ dev_dbg(dev, "Unexpected T100 type\n"); ++ return; ++ } ++ } ++ ++ /* ++ * Values reported should be non-zero if tool is touching the ++ * device ++ */ ++ if (!pressure && type != MXT_T100_TYPE_HOVERING_FINGER) ++ pressure = MXT_PRESSURE_DEFAULT; ++ ++ input_mt_slot(input_dev, id); ++ ++ if (status & MXT_T100_DETECT) { ++ dev_dbg(dev, "[%u] type:%u x:%u y:%u a:%02X p:%02X v:%02X\n", ++ id, type, x, y, major, pressure, orientation); ++ ++ input_mt_report_slot_state(input_dev, tool, 1); ++ input_report_abs(input_dev, ABS_MT_POSITION_X, x); ++ input_report_abs(input_dev, ABS_MT_POSITION_Y, y); ++ input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, major); ++ input_report_abs(input_dev, ABS_MT_PRESSURE, pressure); ++ input_report_abs(input_dev, ABS_MT_DISTANCE, distance); ++ input_report_abs(input_dev, ABS_MT_ORIENTATION, orientation); ++ } else { ++ dev_dbg(dev, "[%u] release\n", id); ++ ++ /* close out slot */ ++ input_mt_report_slot_state(input_dev, 0, 0); ++ } ++ ++ data->update_input = true; ++} ++ + static int mxt_proc_message(struct mxt_data *data, u8 *message) + { + u8 report_id = message[0]; +@@ -786,9 +932,12 @@ static int mxt_proc_message(struct mxt_data *data, u8 *message) + * is not yet registered. + */ + mxt_dump_message(data, message); +- } else if (report_id >= data->T9_reportid_min +- && report_id <= data->T9_reportid_max) { ++ } else if (report_id >= data->T9_reportid_min && ++ report_id <= data->T9_reportid_max) { + mxt_proc_t9_message(data, message); ++ } else if (report_id >= data->T100_reportid_min && ++ report_id <= data->T100_reportid_max) { ++ mxt_proc_t100_message(data, message); + } else if (report_id == data->T19_reportid) { + mxt_input_button(data, message); + data->update_input = true; +@@ -1411,6 +1560,8 @@ static void mxt_free_object_table(struct mxt_data *data) + data->T9_reportid_max = 0; + data->T19_reportid = 0; + data->T44_address = 0; ++ data->T100_reportid_min = 0; ++ data->T100_reportid_max = 0; + data->max_reportid = 0; + } + +@@ -1487,6 +1638,7 @@ static int mxt_get_object_table(struct mxt_data *data) + data->T7_address = object->start_address; + break; + case MXT_TOUCH_MULTI_T9: ++ data->multitouch = MXT_TOUCH_MULTI_T9; + data->T9_reportid_min = min_id; + data->T9_reportid_max = max_id; + data->num_touchids = object->num_report_ids +@@ -1498,6 +1650,13 @@ static int mxt_get_object_table(struct mxt_data *data) + case MXT_SPT_GPIOPWM_T19: + data->T19_reportid = min_id; + break; ++ case MXT_TOUCH_MULTITOUCHSCREEN_T100: ++ data->multitouch = MXT_TOUCH_MULTITOUCHSCREEN_T100; ++ data->T100_reportid_min = min_id; ++ data->T100_reportid_max = max_id; ++ /* first two report IDs reserved */ ++ data->num_touchids = object->num_report_ids - 2; ++ break; + } + + end_address = object->start_address +@@ -1582,10 +1741,88 @@ static int mxt_read_t9_resolution(struct mxt_data *data) + return 0; + } + ++static int mxt_read_t100_config(struct mxt_data *data) ++{ ++ struct i2c_client *client = data->client; ++ int error; ++ struct mxt_object *object; ++ u16 range_x, range_y; ++ u8 cfg, tchaux; ++ u8 aux; ++ ++ object = mxt_get_object(data, MXT_TOUCH_MULTITOUCHSCREEN_T100); ++ if (!object) ++ return -EINVAL; ++ ++ error = __mxt_read_reg(client, ++ object->start_address + MXT_T100_XRANGE, ++ sizeof(range_x), &range_x); ++ if (error) ++ return error; ++ ++ le16_to_cpus(&range_x); ++ ++ error = __mxt_read_reg(client, ++ object->start_address + MXT_T100_YRANGE, ++ sizeof(range_y), &range_y); ++ if (error) ++ return error; ++ ++ le16_to_cpus(&range_y); ++ ++ error = __mxt_read_reg(client, ++ object->start_address + MXT_T100_CFG1, ++ 1, &cfg); ++ if (error) ++ return error; ++ ++ error = __mxt_read_reg(client, ++ object->start_address + MXT_T100_TCHAUX, ++ 1, &tchaux); ++ if (error) ++ return error; ++ ++ /* Handle default values */ ++ if (range_x == 0) ++ range_x = 1023; ++ ++ if (range_y == 0) ++ range_y = 1023; ++ ++ if (cfg & MXT_T100_CFG_SWITCHXY) { ++ data->max_x = range_y; ++ data->max_y = range_x; ++ } else { ++ data->max_x = range_x; ++ data->max_y = range_y; ++ } ++ ++ /* allocate aux bytes */ ++ aux = 6; ++ ++ if (tchaux & MXT_T100_TCHAUX_VECT) ++ data->t100_aux_vect = aux++; ++ ++ if (tchaux & MXT_T100_TCHAUX_AMPL) ++ data->t100_aux_ampl = aux++; ++ ++ if (tchaux & MXT_T100_TCHAUX_AREA) ++ data->t100_aux_area = aux++; ++ ++ dev_dbg(&client->dev, ++ "T100 aux mappings vect:%u ampl:%u area:%u\n", ++ data->t100_aux_vect, data->t100_aux_ampl, data->t100_aux_area); ++ ++ dev_info(&client->dev, ++ "T100 Touchscreen size X%uY%u\n", data->max_x, data->max_y); ++ ++ return 0; ++} ++ + static int mxt_input_open(struct input_dev *dev); + static void mxt_input_close(struct input_dev *dev); + +-static int mxt_initialize_t9_input_device(struct mxt_data *data) ++static int mxt_initialize_input_device(struct mxt_data *data) + { + struct device *dev = &data->client->dev; + const struct mxt_platform_data *pdata = data->pdata; +@@ -1595,9 +1832,25 @@ static int mxt_initialize_t9_input_device(struct mxt_data *data) + unsigned int mt_flags = 0; + int i; + +- error = mxt_read_t9_resolution(data); +- if (error) +- dev_warn(dev, "Failed to initialize T9 resolution\n"); ++ switch (data->multitouch) { ++ case MXT_TOUCH_MULTI_T9: ++ num_mt_slots = data->T9_reportid_max - data->T9_reportid_min + 1; ++ error = mxt_read_t9_resolution(data); ++ if (error) ++ dev_warn(dev, "Failed to initialize T9 resolution\n"); ++ break; ++ ++ case MXT_TOUCH_MULTITOUCHSCREEN_T100: ++ num_mt_slots = data->num_touchids; ++ error = mxt_read_t100_config(data); ++ if (error) ++ dev_warn(dev, "Failed to read T100 config\n"); ++ break; ++ ++ default: ++ dev_err(dev, "Invalid multitouch object\n"); ++ return -EINVAL; ++ } + + input_dev = input_allocate_device(); + if (!input_dev) { +@@ -1612,9 +1865,7 @@ static int mxt_initialize_t9_input_device(struct mxt_data *data) + input_dev->open = mxt_input_open; + input_dev->close = mxt_input_close; + +- __set_bit(EV_ABS, input_dev->evbit); +- __set_bit(EV_KEY, input_dev->evbit); +- __set_bit(BTN_TOUCH, input_dev->keybit); ++ input_set_capability(input_dev, EV_KEY, BTN_TOUCH); + + if (pdata->t19_num_keys) { + __set_bit(INPUT_PROP_BUTTONPAD, input_dev->propbit); +@@ -1637,29 +1888,67 @@ static int mxt_initialize_t9_input_device(struct mxt_data *data) + } + + /* For single touch */ +- input_set_abs_params(input_dev, ABS_X, +- 0, data->max_x, 0, 0); +- input_set_abs_params(input_dev, ABS_Y, +- 0, data->max_y, 0, 0); +- input_set_abs_params(input_dev, ABS_PRESSURE, +- 0, 255, 0, 0); ++ input_set_abs_params(input_dev, ABS_X, 0, data->max_x, 0, 0); ++ input_set_abs_params(input_dev, ABS_Y, 0, data->max_y, 0, 0); ++ ++ if (data->multitouch == MXT_TOUCH_MULTI_T9 || ++ (data->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100 && ++ data->t100_aux_ampl)) { ++ input_set_abs_params(input_dev, ABS_PRESSURE, 0, 255, 0, 0); ++ } + + /* For multi touch */ +- num_mt_slots = data->T9_reportid_max - data->T9_reportid_min + 1; + error = input_mt_init_slots(input_dev, num_mt_slots, mt_flags); + if (error) { + dev_err(dev, "Error %d initialising slots\n", error); + goto err_free_mem; + } + +- input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, +- 0, MXT_MAX_AREA, 0, 0); ++ if (data->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100) { ++ input_set_abs_params(input_dev, ABS_MT_TOOL_TYPE, ++ 0, MT_TOOL_MAX, 0, 0); ++ input_set_abs_params(input_dev, ABS_MT_DISTANCE, ++ MXT_DISTANCE_ACTIVE_TOUCH, ++ MXT_DISTANCE_HOVERING, ++ 0, 0); ++ } ++ + input_set_abs_params(input_dev, ABS_MT_POSITION_X, + 0, data->max_x, 0, 0); + input_set_abs_params(input_dev, ABS_MT_POSITION_Y, + 0, data->max_y, 0, 0); +- input_set_abs_params(input_dev, ABS_MT_PRESSURE, +- 0, 255, 0, 0); ++ ++ if (data->multitouch == MXT_TOUCH_MULTI_T9 || ++ (data->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100 && ++ data->t100_aux_area)) { ++ input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, ++ 0, MXT_MAX_AREA, 0, 0); ++ } ++ ++ if (data->multitouch == MXT_TOUCH_MULTI_T9 || ++ (data->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100 && ++ data->t100_aux_ampl)) { ++ input_set_abs_params(input_dev, ABS_MT_PRESSURE, ++ 0, 255, 0, 0); ++ } ++ ++ if (data->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100 && ++ data->t100_aux_vect) { ++ input_set_abs_params(input_dev, ABS_MT_ORIENTATION, ++ 0, 255, 0, 0); ++ } ++ ++ if (data->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100 && ++ data->t100_aux_ampl) { ++ input_set_abs_params(input_dev, ABS_MT_PRESSURE, ++ 0, 255, 0, 0); ++ } ++ ++ if (data->multitouch == MXT_TOUCH_MULTITOUCHSCREEN_T100 && ++ data->t100_aux_vect) { ++ input_set_abs_params(input_dev, ABS_MT_ORIENTATION, ++ 0, 255, 0, 0); ++ } + + input_set_drvdata(input_dev, data); + +@@ -1765,9 +2054,13 @@ static int mxt_configure_objects(struct mxt_data *data, + dev_warn(dev, "Error %d updating config\n", error); + } + +- error = mxt_initialize_t9_input_device(data); +- if (error) +- return error; ++ if (data->multitouch) { ++ error = mxt_initialize_input_device(data); ++ if (error) ++ return error; ++ } else { ++ dev_warn(dev, "No touch object detected\n"); ++ } + + dev_info(dev, + "Family: %u Variant: %u Firmware V%u.%u.%02X Objects: %u\n", +@@ -2044,15 +2337,13 @@ static const struct attribute_group mxt_attr_group = { + static void mxt_start(struct mxt_data *data) + { + /* Touch enable */ +- mxt_write_object(data, +- MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, 0x83); ++ mxt_write_object(data, data->multitouch, MXT_TOUCH_CTRL, 0x83); + } + + static void mxt_stop(struct mxt_data *data) + { + /* Touch disable */ +- mxt_write_object(data, +- MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, 0); ++ mxt_write_object(data, data->multitouch, MXT_TOUCH_CTRL, 0); + } + + static int mxt_input_open(struct input_dev *dev) +-- +2.1.0 + diff --git a/Input-atmel_mxt_ts-split-out-touchpad-initialisation.patch b/Input-atmel_mxt_ts-split-out-touchpad-initialisation.patch new file mode 100644 index 000000000..c7600614b --- /dev/null +++ b/Input-atmel_mxt_ts-split-out-touchpad-initialisation.patch @@ -0,0 +1,103 @@ +From: Sjoerd Simons +Date: Mon, 6 Apr 2015 13:10:30 -0700 +Subject: [PATCH] Input: atmel_mxt_ts - split out touchpad initialisation logic + +If the "linux,gpio-keymap" DT property is defined, the T19 keys are +configured and the device is setup as a touchpad rather than a touchscreen. +The logic is part of the input device initialization routine but it can be +factored out to its own function to simplify the former. + +Signed-off-by: Sjoerd Simons +Signed-off-by: Javier Martinez Canillas +Signed-off-by: Dmitry Torokhov +--- + drivers/input/touchscreen/atmel_mxt_ts.c | 52 ++++++++++++++++++-------------- + 1 file changed, 30 insertions(+), 22 deletions(-) + +diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c +index 1b3b845d92f4..2875ddf37289 100644 +--- a/drivers/input/touchscreen/atmel_mxt_ts.c ++++ b/drivers/input/touchscreen/atmel_mxt_ts.c +@@ -1822,15 +1822,37 @@ static int mxt_read_t100_config(struct mxt_data *data) + static int mxt_input_open(struct input_dev *dev); + static void mxt_input_close(struct input_dev *dev); + ++static void mxt_set_up_as_touchpad(struct input_dev *input_dev, ++ struct mxt_data *data) ++{ ++ const struct mxt_platform_data *pdata = data->pdata; ++ int i; ++ ++ input_dev->name = "Atmel maXTouch Touchpad"; ++ ++ __set_bit(INPUT_PROP_BUTTONPAD, input_dev->propbit); ++ ++ input_abs_set_res(input_dev, ABS_X, MXT_PIXELS_PER_MM); ++ input_abs_set_res(input_dev, ABS_Y, MXT_PIXELS_PER_MM); ++ input_abs_set_res(input_dev, ABS_MT_POSITION_X, ++ MXT_PIXELS_PER_MM); ++ input_abs_set_res(input_dev, ABS_MT_POSITION_Y, ++ MXT_PIXELS_PER_MM); ++ ++ for (i = 0; i < pdata->t19_num_keys; i++) ++ if (pdata->t19_keymap[i] != KEY_RESERVED) ++ input_set_capability(input_dev, EV_KEY, ++ pdata->t19_keymap[i]); ++} ++ + static int mxt_initialize_input_device(struct mxt_data *data) + { +- struct device *dev = &data->client->dev; + const struct mxt_platform_data *pdata = data->pdata; ++ struct device *dev = &data->client->dev; + struct input_dev *input_dev; + int error; + unsigned int num_mt_slots; + unsigned int mt_flags = 0; +- int i; + + switch (data->multitouch) { + case MXT_TOUCH_MULTI_T9: +@@ -1867,26 +1889,6 @@ static int mxt_initialize_input_device(struct mxt_data *data) + + input_set_capability(input_dev, EV_KEY, BTN_TOUCH); + +- if (pdata->t19_num_keys) { +- __set_bit(INPUT_PROP_BUTTONPAD, input_dev->propbit); +- +- for (i = 0; i < pdata->t19_num_keys; i++) +- if (pdata->t19_keymap[i] != KEY_RESERVED) +- input_set_capability(input_dev, EV_KEY, +- pdata->t19_keymap[i]); +- +- mt_flags |= INPUT_MT_POINTER; +- +- input_abs_set_res(input_dev, ABS_X, MXT_PIXELS_PER_MM); +- input_abs_set_res(input_dev, ABS_Y, MXT_PIXELS_PER_MM); +- input_abs_set_res(input_dev, ABS_MT_POSITION_X, +- MXT_PIXELS_PER_MM); +- input_abs_set_res(input_dev, ABS_MT_POSITION_Y, +- MXT_PIXELS_PER_MM); +- +- input_dev->name = "Atmel maXTouch Touchpad"; +- } +- + /* For single touch */ + input_set_abs_params(input_dev, ABS_X, 0, data->max_x, 0, 0); + input_set_abs_params(input_dev, ABS_Y, 0, data->max_y, 0, 0); +@@ -1897,6 +1899,12 @@ static int mxt_initialize_input_device(struct mxt_data *data) + input_set_abs_params(input_dev, ABS_PRESSURE, 0, 255, 0, 0); + } + ++ /* If device has buttons we assume it is a touchpad */ ++ if (pdata->t19_num_keys) { ++ mxt_set_up_as_touchpad(input_dev, data); ++ mt_flags |= INPUT_MT_POINTER; ++ } ++ + /* For multi touch */ + error = input_mt_init_slots(input_dev, num_mt_slots, mt_flags); + if (error) { +-- +2.1.0 + diff --git a/kernel.spec b/kernel.spec index 1f3cf4852..4733d6b49 100644 --- a/kernel.spec +++ b/kernel.spec @@ -630,6 +630,11 @@ Patch26178: pty-Fix-input-race-when-closing.patch #rhbz 1210801 Patch26179: HID-logitech-hidpp-add-a-module-parameter-to-keep-fi.patch +#rhbz 1209088 +Patch26180: Input-atmel_mxt_ts-implement-support-for-T100-touch-.patch +Patch26181: Input-atmel_mxt_ts-split-out-touchpad-initialisation.patch +Patch26182: Input-atmel_mxt_ts-add-support-for-Google-Pixel-2.patch + # END OF PATCH DEFINITIONS %endif @@ -1375,6 +1380,11 @@ ApplyPatch pty-Fix-input-race-when-closing.patch #rhbz 1210801 ApplyPatch HID-logitech-hidpp-add-a-module-parameter-to-keep-fi.patch +#rhbz 1209088 +ApplyPatch Input-atmel_mxt_ts-implement-support-for-T100-touch-.patch +ApplyPatch Input-atmel_mxt_ts-split-out-touchpad-initialisation.patch +ApplyPatch Input-atmel_mxt_ts-add-support-for-Google-Pixel-2.patch + # END OF PATCH APPLICATIONS %endif @@ -2226,6 +2236,7 @@ fi # %changelog * Fri Apr 17 2015 Josh Boyer +- Add support for touchpad on Google Pixel 2 (rhbz 1209088) - Allow disabling raw mode in logitech-hidpp (rhbz 1210801) * Wed Apr 15 2015 Josh Boyer