aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2015-04-07 19:30:01 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2015-04-15 13:52:48 -0400
commit4f8d808889d05807f494f82f8cfaa6c113c2f761 (patch)
tree53e2b96f5d895ff0057dbbc14610a6e9d9fccd59 /drivers/input
parent0604949ce3b9a59cff419daf706272620a9a0df0 (diff)
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 <javier.martinez@collabora.co.uk> Tested-by: Javier Martinez Canillas <javier.martinez@collabora.co.uk> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/touchscreen/atmel_mxt_ts.c141
1 files 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 @@
14 * 14 *
15 */ 15 */
16 16
17#include <linux/acpi.h>
18#include <linux/dmi.h>
17#include <linux/module.h> 19#include <linux/module.h>
18#include <linux/init.h> 20#include <linux/init.h>
19#include <linux/completion.h> 21#include <linux/completion.h>
@@ -2371,7 +2373,7 @@ static void mxt_input_close(struct input_dev *dev)
2371} 2373}
2372 2374
2373#ifdef CONFIG_OF 2375#ifdef CONFIG_OF
2374static struct mxt_platform_data *mxt_parse_dt(struct i2c_client *client) 2376static const struct mxt_platform_data *mxt_parse_dt(struct i2c_client *client)
2375{ 2377{
2376 struct mxt_platform_data *pdata; 2378 struct mxt_platform_data *pdata;
2377 u32 *keymap; 2379 u32 *keymap;
@@ -2379,7 +2381,7 @@ static struct mxt_platform_data *mxt_parse_dt(struct i2c_client *client)
2379 int proplen, i, ret; 2381 int proplen, i, ret;
2380 2382
2381 if (!client->dev.of_node) 2383 if (!client->dev.of_node)
2382 return ERR_PTR(-ENODEV); 2384 return ERR_PTR(-ENOENT);
2383 2385
2384 pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL); 2386 pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
2385 if (!pdata) 2387 if (!pdata)
@@ -2410,25 +2412,132 @@ static struct mxt_platform_data *mxt_parse_dt(struct i2c_client *client)
2410 return pdata; 2412 return pdata;
2411} 2413}
2412#else 2414#else
2413static struct mxt_platform_data *mxt_parse_dt(struct i2c_client *client) 2415static const struct mxt_platform_data *mxt_parse_dt(struct i2c_client *client)
2414{ 2416{
2415 dev_dbg(&client->dev, "No platform data specified\n"); 2417 return ERR_PTR(-ENOENT);
2416 return ERR_PTR(-EINVAL); 2418}
2419#endif
2420
2421#ifdef CONFIG_ACPI
2422
2423struct mxt_acpi_platform_data {
2424 const char *hid;
2425 struct mxt_platform_data pdata;
2426};
2427
2428static unsigned int samus_touchpad_buttons[] = {
2429 KEY_RESERVED,
2430 KEY_RESERVED,
2431 KEY_RESERVED,
2432 BTN_LEFT
2433};
2434
2435static struct mxt_acpi_platform_data samus_platform_data[] = {
2436 {
2437 /* Touchpad */
2438 .hid = "ATML0000",
2439 .pdata = {
2440 .t19_num_keys = ARRAY_SIZE(samus_touchpad_buttons),
2441 .t19_keymap = samus_touchpad_buttons,
2442 },
2443 },
2444 {
2445 /* Touchscreen */
2446 .hid = "ATML0001",
2447 },
2448 { }
2449};
2450
2451static const struct dmi_system_id mxt_dmi_table[] = {
2452 {
2453 /* 2015 Google Pixel */
2454 .ident = "Chromebook Pixel 2",
2455 .matches = {
2456 DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
2457 DMI_MATCH(DMI_PRODUCT_NAME, "Samus"),
2458 },
2459 .driver_data = samus_platform_data,
2460 },
2461 { }
2462};
2463
2464static const struct mxt_platform_data *mxt_parse_acpi(struct i2c_client *client)
2465{
2466 struct acpi_device *adev;
2467 const struct dmi_system_id *system_id;
2468 const struct mxt_acpi_platform_data *acpi_pdata;
2469
2470 /*
2471 * Ignore ACPI devices representing bootloader mode.
2472 *
2473 * This is a bit of a hack: Google Chromebook BIOS creates ACPI
2474 * devices for both application and bootloader modes, but we are
2475 * interested in application mode only (if device is in bootloader
2476 * mode we'll end up switching into application anyway). So far
2477 * application mode addresses were all above 0x40, so we'll use it
2478 * as a threshold.
2479 */
2480 if (client->addr < 0x40)
2481 return ERR_PTR(-ENXIO);
2482
2483 adev = ACPI_COMPANION(&client->dev);
2484 if (!adev)
2485 return ERR_PTR(-ENOENT);
2486
2487 system_id = dmi_first_match(mxt_dmi_table);
2488 if (!system_id)
2489 return ERR_PTR(-ENOENT);
2490
2491 acpi_pdata = system_id->driver_data;
2492 if (!acpi_pdata)
2493 return ERR_PTR(-ENOENT);
2494
2495 while (acpi_pdata->hid) {
2496 if (!strcmp(acpi_device_hid(adev), acpi_pdata->hid))
2497 return &acpi_pdata->pdata;
2498
2499 acpi_pdata++;
2500 }
2501
2502 return ERR_PTR(-ENOENT);
2503}
2504#else
2505static const struct mxt_platform_data *mxt_parse_acpi(struct i2c_client *client)
2506{
2507 return ERR_PTR(-ENOENT);
2417} 2508}
2418#endif 2509#endif
2419 2510
2511static const struct mxt_platform_data *
2512mxt_get_platform_data(struct i2c_client *client)
2513{
2514 const struct mxt_platform_data *pdata;
2515
2516 pdata = dev_get_platdata(&client->dev);
2517 if (pdata)
2518 return pdata;
2519
2520 pdata = mxt_parse_dt(client);
2521 if (!IS_ERR(pdata) || PTR_ERR(pdata) != -ENOENT)
2522 return pdata;
2523
2524 pdata = mxt_parse_acpi(client);
2525 if (!IS_ERR(pdata) || PTR_ERR(pdata) != -ENOENT)
2526 return pdata;
2527
2528 dev_err(&client->dev, "No platform data specified\n");
2529 return ERR_PTR(-EINVAL);
2530}
2531
2420static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id) 2532static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id)
2421{ 2533{
2422 struct mxt_data *data; 2534 struct mxt_data *data;
2423 const struct mxt_platform_data *pdata; 2535 const struct mxt_platform_data *pdata;
2424 int error; 2536 int error;
2425 2537
2426 pdata = dev_get_platdata(&client->dev); 2538 pdata = mxt_get_platform_data(client);
2427 if (!pdata) { 2539 if (IS_ERR(pdata))
2428 pdata = mxt_parse_dt(client); 2540 return PTR_ERR(pdata);
2429 if (IS_ERR(pdata))
2430 return PTR_ERR(pdata);
2431 }
2432 2541
2433 data = kzalloc(sizeof(struct mxt_data), GFP_KERNEL); 2542 data = kzalloc(sizeof(struct mxt_data), GFP_KERNEL);
2434 if (!data) { 2543 if (!data) {
@@ -2536,6 +2645,15 @@ static const struct of_device_id mxt_of_match[] = {
2536}; 2645};
2537MODULE_DEVICE_TABLE(of, mxt_of_match); 2646MODULE_DEVICE_TABLE(of, mxt_of_match);
2538 2647
2648#ifdef CONFIG_ACPI
2649static const struct acpi_device_id mxt_acpi_id[] = {
2650 { "ATML0000", 0 }, /* Touchpad */
2651 { "ATML0001", 0 }, /* Touchscreen */
2652 { }
2653};
2654MODULE_DEVICE_TABLE(acpi, mxt_acpi_id);
2655#endif
2656
2539static const struct i2c_device_id mxt_id[] = { 2657static const struct i2c_device_id mxt_id[] = {
2540 { "qt602240_ts", 0 }, 2658 { "qt602240_ts", 0 },
2541 { "atmel_mxt_ts", 0 }, 2659 { "atmel_mxt_ts", 0 },
@@ -2550,6 +2668,7 @@ static struct i2c_driver mxt_driver = {
2550 .name = "atmel_mxt_ts", 2668 .name = "atmel_mxt_ts",
2551 .owner = THIS_MODULE, 2669 .owner = THIS_MODULE,
2552 .of_match_table = of_match_ptr(mxt_of_match), 2670 .of_match_table = of_match_ptr(mxt_of_match),
2671 .acpi_match_table = ACPI_PTR(mxt_acpi_id),
2553 .pm = &mxt_pm_ops, 2672 .pm = &mxt_pm_ops,
2554 }, 2673 },
2555 .probe = mxt_probe, 2674 .probe = mxt_probe,