Loading...
Note: File does not exist in v3.1.
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * DMI based code to deal with broken DSDTs on X86 tablets which ship with
4 * Android as (part of) the factory image. The factory kernels shipped on these
5 * devices typically have a bunch of things hardcoded, rather than specified
6 * in their DSDT.
7 *
8 * Copyright (C) 2021-2022 Hans de Goede <hdegoede@redhat.com>
9 */
10
11#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
12
13#include <linux/acpi.h>
14#include <linux/dmi.h>
15#include <linux/efi.h>
16#include <linux/gpio_keys.h>
17#include <linux/gpio/consumer.h>
18#include <linux/gpio/driver.h>
19#include <linux/gpio/machine.h>
20#include <linux/i2c.h>
21#include <linux/input.h>
22#include <linux/irq.h>
23#include <linux/irqdomain.h>
24#include <linux/module.h>
25#include <linux/mod_devicetable.h>
26#include <linux/pinctrl/consumer.h>
27#include <linux/pinctrl/machine.h>
28#include <linux/platform_data/lp855x.h>
29#include <linux/platform_device.h>
30#include <linux/power/bq24190_charger.h>
31#include <linux/reboot.h>
32#include <linux/rmi.h>
33#include <linux/serdev.h>
34#include <linux/spi/spi.h>
35#include <linux/string.h>
36/* For gpio_get_desc() which is EXPORT_SYMBOL_GPL() */
37#include "../../gpio/gpiolib.h"
38#include "../../gpio/gpiolib-acpi.h"
39
40/*
41 * Helper code to get Linux IRQ numbers given a description of the IRQ source
42 * (either IOAPIC index, or GPIO chip name + pin-number).
43 */
44enum x86_acpi_irq_type {
45 X86_ACPI_IRQ_TYPE_NONE,
46 X86_ACPI_IRQ_TYPE_APIC,
47 X86_ACPI_IRQ_TYPE_GPIOINT,
48 X86_ACPI_IRQ_TYPE_PMIC,
49};
50
51struct x86_acpi_irq_data {
52 char *chip; /* GPIO chip label (GPIOINT) or PMIC ACPI path (PMIC) */
53 enum x86_acpi_irq_type type;
54 enum irq_domain_bus_token domain;
55 int index;
56 int trigger; /* ACPI_EDGE_SENSITIVE / ACPI_LEVEL_SENSITIVE */
57 int polarity; /* ACPI_ACTIVE_HIGH / ACPI_ACTIVE_LOW / ACPI_ACTIVE_BOTH */
58};
59
60static int gpiochip_find_match_label(struct gpio_chip *gc, void *data)
61{
62 return gc->label && !strcmp(gc->label, data);
63}
64
65static int x86_android_tablet_get_gpiod(char *label, int pin, struct gpio_desc **desc)
66{
67 struct gpio_desc *gpiod;
68 struct gpio_chip *chip;
69
70 chip = gpiochip_find(label, gpiochip_find_match_label);
71 if (!chip) {
72 pr_err("error cannot find GPIO chip %s\n", label);
73 return -ENODEV;
74 }
75
76 gpiod = gpiochip_get_desc(chip, pin);
77 if (IS_ERR(gpiod)) {
78 pr_err("error %ld getting GPIO %s %d\n", PTR_ERR(gpiod), label, pin);
79 return PTR_ERR(gpiod);
80 }
81
82 *desc = gpiod;
83 return 0;
84}
85
86static int x86_acpi_irq_helper_get(const struct x86_acpi_irq_data *data)
87{
88 struct irq_fwspec fwspec = { };
89 struct irq_domain *domain;
90 struct acpi_device *adev;
91 struct gpio_desc *gpiod;
92 unsigned int irq_type;
93 acpi_handle handle;
94 acpi_status status;
95 int irq, ret;
96
97 switch (data->type) {
98 case X86_ACPI_IRQ_TYPE_APIC:
99 /*
100 * The DSDT may already reference the GSI in a device skipped by
101 * acpi_quirk_skip_i2c_client_enumeration(). Unregister the GSI
102 * to avoid EBUSY errors in this case.
103 */
104 acpi_unregister_gsi(data->index);
105 irq = acpi_register_gsi(NULL, data->index, data->trigger, data->polarity);
106 if (irq < 0)
107 pr_err("error %d getting APIC IRQ %d\n", irq, data->index);
108
109 return irq;
110 case X86_ACPI_IRQ_TYPE_GPIOINT:
111 /* Like acpi_dev_gpio_irq_get(), but without parsing ACPI resources */
112 ret = x86_android_tablet_get_gpiod(data->chip, data->index, &gpiod);
113 if (ret)
114 return ret;
115
116 irq = gpiod_to_irq(gpiod);
117 if (irq < 0) {
118 pr_err("error %d getting IRQ %s %d\n", irq, data->chip, data->index);
119 return irq;
120 }
121
122 irq_type = acpi_dev_get_irq_type(data->trigger, data->polarity);
123 if (irq_type != IRQ_TYPE_NONE && irq_type != irq_get_trigger_type(irq))
124 irq_set_irq_type(irq, irq_type);
125
126 return irq;
127 case X86_ACPI_IRQ_TYPE_PMIC:
128 status = acpi_get_handle(NULL, data->chip, &handle);
129 if (ACPI_FAILURE(status)) {
130 pr_err("error could not get %s handle\n", data->chip);
131 return -ENODEV;
132 }
133
134 adev = acpi_fetch_acpi_dev(handle);
135 if (!adev) {
136 pr_err("error could not get %s adev\n", data->chip);
137 return -ENODEV;
138 }
139
140 fwspec.fwnode = acpi_fwnode_handle(adev);
141 domain = irq_find_matching_fwspec(&fwspec, data->domain);
142 if (!domain) {
143 pr_err("error could not find IRQ domain for %s\n", data->chip);
144 return -ENODEV;
145 }
146
147 return irq_create_mapping(domain, data->index);
148 default:
149 return 0;
150 }
151}
152
153struct x86_i2c_client_info {
154 struct i2c_board_info board_info;
155 char *adapter_path;
156 struct x86_acpi_irq_data irq_data;
157};
158
159struct x86_serdev_info {
160 const char *ctrl_hid;
161 const char *ctrl_uid;
162 const char *ctrl_devname;
163 /*
164 * ATM the serdev core only supports of or ACPI matching; and sofar all
165 * Android x86 tablets DSDTs have usable serdev nodes, but sometimes
166 * under the wrong controller. So we just tie the existing serdev ACPI
167 * node to the right controller.
168 */
169 const char *serdev_hid;
170};
171
172struct x86_dev_info {
173 char *invalid_aei_gpiochip;
174 const char * const *modules;
175 const struct software_node *bat_swnode;
176 struct gpiod_lookup_table * const *gpiod_lookup_tables;
177 const struct x86_i2c_client_info *i2c_client_info;
178 const struct platform_device_info *pdev_info;
179 const struct x86_serdev_info *serdev_info;
180 int i2c_client_count;
181 int pdev_count;
182 int serdev_count;
183 int (*init)(void);
184 void (*exit)(void);
185};
186
187/* Generic / shared charger / battery settings */
188static const char * const tusb1211_chg_det_psy[] = { "tusb1211-charger-detect" };
189static const char * const bq24190_psy[] = { "bq24190-charger" };
190static const char * const bq25890_psy[] = { "bq25890-charger" };
191
192static const struct property_entry fg_bq24190_supply_props[] = {
193 PROPERTY_ENTRY_STRING_ARRAY("supplied-from", bq24190_psy),
194 { }
195};
196
197static const struct software_node fg_bq24190_supply_node = {
198 .properties = fg_bq24190_supply_props,
199};
200
201static const struct property_entry fg_bq25890_supply_props[] = {
202 PROPERTY_ENTRY_STRING_ARRAY("supplied-from", bq25890_psy),
203 { }
204};
205
206static const struct software_node fg_bq25890_supply_node = {
207 .properties = fg_bq25890_supply_props,
208};
209
210/* LiPo HighVoltage (max 4.35V) settings used by most devs with a HV bat. */
211static const struct property_entry generic_lipo_hv_4v35_battery_props[] = {
212 PROPERTY_ENTRY_STRING("compatible", "simple-battery"),
213 PROPERTY_ENTRY_STRING("device-chemistry", "lithium-ion"),
214 PROPERTY_ENTRY_U32("precharge-current-microamp", 256000),
215 PROPERTY_ENTRY_U32("charge-term-current-microamp", 128000),
216 PROPERTY_ENTRY_U32("constant-charge-current-max-microamp", 1856000),
217 PROPERTY_ENTRY_U32("constant-charge-voltage-max-microvolt", 4352000),
218 PROPERTY_ENTRY_U32("factory-internal-resistance-micro-ohms", 150000),
219 { }
220};
221
222static const struct software_node generic_lipo_hv_4v35_battery_node = {
223 .properties = generic_lipo_hv_4v35_battery_props,
224};
225
226/* For enabling the bq24190 5V boost based on id-pin */
227static struct regulator_consumer_supply intel_int3496_consumer = {
228 .supply = "vbus",
229 .dev_name = "intel-int3496",
230};
231
232static const struct regulator_init_data bq24190_vbus_init_data = {
233 .constraints = {
234 .name = "bq24190_vbus",
235 .valid_ops_mask = REGULATOR_CHANGE_STATUS,
236 },
237 .consumer_supplies = &intel_int3496_consumer,
238 .num_consumer_supplies = 1,
239};
240
241static struct bq24190_platform_data bq24190_pdata = {
242 .regulator_init_data = &bq24190_vbus_init_data,
243};
244
245static const char * const bq24190_modules[] __initconst = {
246 "intel_crystal_cove_charger", /* For the bq24190 IRQ */
247 "bq24190_charger", /* For the Vbus regulator for intel-int3496 */
248 NULL
249};
250
251/* Generic pdevs array and gpio-lookups for micro USB ID pin handling */
252static const struct platform_device_info int3496_pdevs[] __initconst = {
253 {
254 /* For micro USB ID pin handling */
255 .name = "intel-int3496",
256 .id = PLATFORM_DEVID_NONE,
257 },
258};
259
260static struct gpiod_lookup_table int3496_gpo2_pin22_gpios = {
261 .dev_id = "intel-int3496",
262 .table = {
263 GPIO_LOOKUP("INT33FC:02", 22, "id", GPIO_ACTIVE_HIGH),
264 { }
265 },
266};
267
268/*
269 * Advantech MICA-071
270 * This is a standard Windows tablet, but it has an extra "quick launch" button
271 * which is not described in the ACPI tables in anyway.
272 * Use the x86-android-tablets infra to create a gpio-button device for this.
273 */
274static struct gpio_keys_button advantech_mica_071_button = {
275 .code = KEY_PROG1,
276 /* .gpio gets filled in by advantech_mica_071_init() */
277 .active_low = true,
278 .desc = "prog1_key",
279 .type = EV_KEY,
280 .wakeup = false,
281 .debounce_interval = 50,
282};
283
284static const struct gpio_keys_platform_data advantech_mica_071_button_pdata __initconst = {
285 .buttons = &advantech_mica_071_button,
286 .nbuttons = 1,
287 .name = "prog1_key",
288};
289
290static const struct platform_device_info advantech_mica_071_pdevs[] __initconst = {
291 {
292 .name = "gpio-keys",
293 .id = PLATFORM_DEVID_AUTO,
294 .data = &advantech_mica_071_button_pdata,
295 .size_data = sizeof(advantech_mica_071_button_pdata),
296 },
297};
298
299static int __init advantech_mica_071_init(void)
300{
301 struct gpio_desc *gpiod;
302 int ret;
303
304 ret = x86_android_tablet_get_gpiod("INT33FC:00", 2, &gpiod);
305 if (ret < 0)
306 return ret;
307 advantech_mica_071_button.gpio = desc_to_gpio(gpiod);
308
309 return 0;
310}
311
312static const struct x86_dev_info advantech_mica_071_info __initconst = {
313 .pdev_info = advantech_mica_071_pdevs,
314 .pdev_count = ARRAY_SIZE(advantech_mica_071_pdevs),
315 .init = advantech_mica_071_init,
316};
317
318/* Asus ME176C and TF103C tablets shared data */
319static struct gpio_keys_button asus_me176c_tf103c_lid = {
320 .code = SW_LID,
321 /* .gpio gets filled in by asus_me176c_tf103c_init() */
322 .active_low = true,
323 .desc = "lid_sw",
324 .type = EV_SW,
325 .wakeup = true,
326 .debounce_interval = 50,
327};
328
329static const struct gpio_keys_platform_data asus_me176c_tf103c_lid_pdata __initconst = {
330 .buttons = &asus_me176c_tf103c_lid,
331 .nbuttons = 1,
332 .name = "lid_sw",
333};
334
335static const struct platform_device_info asus_me176c_tf103c_pdevs[] __initconst = {
336 {
337 .name = "gpio-keys",
338 .id = PLATFORM_DEVID_AUTO,
339 .data = &asus_me176c_tf103c_lid_pdata,
340 .size_data = sizeof(asus_me176c_tf103c_lid_pdata),
341 },
342 {
343 /* For micro USB ID pin handling */
344 .name = "intel-int3496",
345 .id = PLATFORM_DEVID_NONE,
346 },
347};
348
349static int __init asus_me176c_tf103c_init(void)
350{
351 struct gpio_desc *gpiod;
352 int ret;
353
354 ret = x86_android_tablet_get_gpiod("INT33FC:02", 12, &gpiod);
355 if (ret < 0)
356 return ret;
357 asus_me176c_tf103c_lid.gpio = desc_to_gpio(gpiod);
358
359 return 0;
360}
361
362
363/* Asus ME176C tablets have an Android factory img with everything hardcoded */
364static const char * const asus_me176c_accel_mount_matrix[] = {
365 "-1", "0", "0",
366 "0", "1", "0",
367 "0", "0", "1"
368};
369
370static const struct property_entry asus_me176c_accel_props[] = {
371 PROPERTY_ENTRY_STRING_ARRAY("mount-matrix", asus_me176c_accel_mount_matrix),
372 { }
373};
374
375static const struct software_node asus_me176c_accel_node = {
376 .properties = asus_me176c_accel_props,
377};
378
379static const struct property_entry asus_me176c_bq24190_props[] = {
380 PROPERTY_ENTRY_STRING_ARRAY("supplied-from", tusb1211_chg_det_psy),
381 PROPERTY_ENTRY_REF("monitored-battery", &generic_lipo_hv_4v35_battery_node),
382 PROPERTY_ENTRY_U32("ti,system-minimum-microvolt", 3600000),
383 PROPERTY_ENTRY_BOOL("omit-battery-class"),
384 PROPERTY_ENTRY_BOOL("disable-reset"),
385 { }
386};
387
388static const struct software_node asus_me176c_bq24190_node = {
389 .properties = asus_me176c_bq24190_props,
390};
391
392static const struct property_entry asus_me176c_ug3105_props[] = {
393 PROPERTY_ENTRY_STRING_ARRAY("supplied-from", bq24190_psy),
394 PROPERTY_ENTRY_REF("monitored-battery", &generic_lipo_hv_4v35_battery_node),
395 PROPERTY_ENTRY_U32("upisemi,rsns-microohm", 10000),
396 { }
397};
398
399static const struct software_node asus_me176c_ug3105_node = {
400 .properties = asus_me176c_ug3105_props,
401};
402
403static const struct x86_i2c_client_info asus_me176c_i2c_clients[] __initconst = {
404 {
405 /* bq24297 battery charger */
406 .board_info = {
407 .type = "bq24190",
408 .addr = 0x6b,
409 .dev_name = "bq24297",
410 .swnode = &asus_me176c_bq24190_node,
411 .platform_data = &bq24190_pdata,
412 },
413 .adapter_path = "\\_SB_.I2C1",
414 .irq_data = {
415 .type = X86_ACPI_IRQ_TYPE_PMIC,
416 .chip = "\\_SB_.I2C7.PMIC",
417 .domain = DOMAIN_BUS_WAKEUP,
418 .index = 0,
419 },
420 }, {
421 /* ug3105 battery monitor */
422 .board_info = {
423 .type = "ug3105",
424 .addr = 0x70,
425 .dev_name = "ug3105",
426 .swnode = &asus_me176c_ug3105_node,
427 },
428 .adapter_path = "\\_SB_.I2C1",
429 }, {
430 /* ak09911 compass */
431 .board_info = {
432 .type = "ak09911",
433 .addr = 0x0c,
434 .dev_name = "ak09911",
435 },
436 .adapter_path = "\\_SB_.I2C5",
437 }, {
438 /* kxtj21009 accel */
439 .board_info = {
440 .type = "kxtj21009",
441 .addr = 0x0f,
442 .dev_name = "kxtj21009",
443 .swnode = &asus_me176c_accel_node,
444 },
445 .adapter_path = "\\_SB_.I2C5",
446 .irq_data = {
447 .type = X86_ACPI_IRQ_TYPE_APIC,
448 .index = 0x44,
449 .trigger = ACPI_EDGE_SENSITIVE,
450 .polarity = ACPI_ACTIVE_LOW,
451 },
452 }, {
453 /* goodix touchscreen */
454 .board_info = {
455 .type = "GDIX1001:00",
456 .addr = 0x14,
457 .dev_name = "goodix_ts",
458 },
459 .adapter_path = "\\_SB_.I2C6",
460 .irq_data = {
461 .type = X86_ACPI_IRQ_TYPE_APIC,
462 .index = 0x45,
463 .trigger = ACPI_EDGE_SENSITIVE,
464 .polarity = ACPI_ACTIVE_LOW,
465 },
466 },
467};
468
469static const struct x86_serdev_info asus_me176c_serdevs[] __initconst = {
470 {
471 .ctrl_hid = "80860F0A",
472 .ctrl_uid = "2",
473 .ctrl_devname = "serial0",
474 .serdev_hid = "BCM2E3A",
475 },
476};
477
478static struct gpiod_lookup_table asus_me176c_goodix_gpios = {
479 .dev_id = "i2c-goodix_ts",
480 .table = {
481 GPIO_LOOKUP("INT33FC:00", 60, "reset", GPIO_ACTIVE_HIGH),
482 GPIO_LOOKUP("INT33FC:02", 28, "irq", GPIO_ACTIVE_HIGH),
483 { }
484 },
485};
486
487static struct gpiod_lookup_table * const asus_me176c_gpios[] = {
488 &int3496_gpo2_pin22_gpios,
489 &asus_me176c_goodix_gpios,
490 NULL
491};
492
493static const struct x86_dev_info asus_me176c_info __initconst = {
494 .i2c_client_info = asus_me176c_i2c_clients,
495 .i2c_client_count = ARRAY_SIZE(asus_me176c_i2c_clients),
496 .pdev_info = asus_me176c_tf103c_pdevs,
497 .pdev_count = ARRAY_SIZE(asus_me176c_tf103c_pdevs),
498 .serdev_info = asus_me176c_serdevs,
499 .serdev_count = ARRAY_SIZE(asus_me176c_serdevs),
500 .gpiod_lookup_tables = asus_me176c_gpios,
501 .bat_swnode = &generic_lipo_hv_4v35_battery_node,
502 .modules = bq24190_modules,
503 .invalid_aei_gpiochip = "INT33FC:02",
504 .init = asus_me176c_tf103c_init,
505};
506
507/* Asus TF103C tablets have an Android factory img with everything hardcoded */
508static const char * const asus_tf103c_accel_mount_matrix[] = {
509 "0", "-1", "0",
510 "-1", "0", "0",
511 "0", "0", "1"
512};
513
514static const struct property_entry asus_tf103c_accel_props[] = {
515 PROPERTY_ENTRY_STRING_ARRAY("mount-matrix", asus_tf103c_accel_mount_matrix),
516 { }
517};
518
519static const struct software_node asus_tf103c_accel_node = {
520 .properties = asus_tf103c_accel_props,
521};
522
523static const struct property_entry asus_tf103c_touchscreen_props[] = {
524 PROPERTY_ENTRY_STRING("compatible", "atmel,atmel_mxt_ts"),
525 { }
526};
527
528static const struct software_node asus_tf103c_touchscreen_node = {
529 .properties = asus_tf103c_touchscreen_props,
530};
531
532static const struct property_entry asus_tf103c_battery_props[] = {
533 PROPERTY_ENTRY_STRING("compatible", "simple-battery"),
534 PROPERTY_ENTRY_STRING("device-chemistry", "lithium-ion-polymer"),
535 PROPERTY_ENTRY_U32("precharge-current-microamp", 256000),
536 PROPERTY_ENTRY_U32("charge-term-current-microamp", 128000),
537 PROPERTY_ENTRY_U32("constant-charge-current-max-microamp", 2048000),
538 PROPERTY_ENTRY_U32("constant-charge-voltage-max-microvolt", 4208000),
539 PROPERTY_ENTRY_U32("factory-internal-resistance-micro-ohms", 150000),
540 { }
541};
542
543static const struct software_node asus_tf103c_battery_node = {
544 .properties = asus_tf103c_battery_props,
545};
546
547static const struct property_entry asus_tf103c_bq24190_props[] = {
548 PROPERTY_ENTRY_STRING_ARRAY("supplied-from", tusb1211_chg_det_psy),
549 PROPERTY_ENTRY_REF("monitored-battery", &asus_tf103c_battery_node),
550 PROPERTY_ENTRY_U32("ti,system-minimum-microvolt", 3600000),
551 PROPERTY_ENTRY_BOOL("omit-battery-class"),
552 PROPERTY_ENTRY_BOOL("disable-reset"),
553 { }
554};
555
556static const struct software_node asus_tf103c_bq24190_node = {
557 .properties = asus_tf103c_bq24190_props,
558};
559
560static const struct property_entry asus_tf103c_ug3105_props[] = {
561 PROPERTY_ENTRY_STRING_ARRAY("supplied-from", bq24190_psy),
562 PROPERTY_ENTRY_REF("monitored-battery", &asus_tf103c_battery_node),
563 PROPERTY_ENTRY_U32("upisemi,rsns-microohm", 5000),
564 { }
565};
566
567static const struct software_node asus_tf103c_ug3105_node = {
568 .properties = asus_tf103c_ug3105_props,
569};
570
571static const struct x86_i2c_client_info asus_tf103c_i2c_clients[] __initconst = {
572 {
573 /* bq24297 battery charger */
574 .board_info = {
575 .type = "bq24190",
576 .addr = 0x6b,
577 .dev_name = "bq24297",
578 .swnode = &asus_tf103c_bq24190_node,
579 .platform_data = &bq24190_pdata,
580 },
581 .adapter_path = "\\_SB_.I2C1",
582 .irq_data = {
583 .type = X86_ACPI_IRQ_TYPE_PMIC,
584 .chip = "\\_SB_.I2C7.PMIC",
585 .domain = DOMAIN_BUS_WAKEUP,
586 .index = 0,
587 },
588 }, {
589 /* ug3105 battery monitor */
590 .board_info = {
591 .type = "ug3105",
592 .addr = 0x70,
593 .dev_name = "ug3105",
594 .swnode = &asus_tf103c_ug3105_node,
595 },
596 .adapter_path = "\\_SB_.I2C1",
597 }, {
598 /* ak09911 compass */
599 .board_info = {
600 .type = "ak09911",
601 .addr = 0x0c,
602 .dev_name = "ak09911",
603 },
604 .adapter_path = "\\_SB_.I2C5",
605 }, {
606 /* kxtj21009 accel */
607 .board_info = {
608 .type = "kxtj21009",
609 .addr = 0x0f,
610 .dev_name = "kxtj21009",
611 .swnode = &asus_tf103c_accel_node,
612 },
613 .adapter_path = "\\_SB_.I2C5",
614 }, {
615 /* atmel touchscreen */
616 .board_info = {
617 .type = "atmel_mxt_ts",
618 .addr = 0x4a,
619 .dev_name = "atmel_mxt_ts",
620 .swnode = &asus_tf103c_touchscreen_node,
621 },
622 .adapter_path = "\\_SB_.I2C6",
623 .irq_data = {
624 .type = X86_ACPI_IRQ_TYPE_GPIOINT,
625 .chip = "INT33FC:02",
626 .index = 28,
627 .trigger = ACPI_EDGE_SENSITIVE,
628 .polarity = ACPI_ACTIVE_LOW,
629 },
630 },
631};
632
633static struct gpiod_lookup_table * const asus_tf103c_gpios[] = {
634 &int3496_gpo2_pin22_gpios,
635 NULL
636};
637
638static const struct x86_dev_info asus_tf103c_info __initconst = {
639 .i2c_client_info = asus_tf103c_i2c_clients,
640 .i2c_client_count = ARRAY_SIZE(asus_tf103c_i2c_clients),
641 .pdev_info = asus_me176c_tf103c_pdevs,
642 .pdev_count = ARRAY_SIZE(asus_me176c_tf103c_pdevs),
643 .gpiod_lookup_tables = asus_tf103c_gpios,
644 .bat_swnode = &asus_tf103c_battery_node,
645 .modules = bq24190_modules,
646 .invalid_aei_gpiochip = "INT33FC:02",
647 .init = asus_me176c_tf103c_init,
648};
649
650/*
651 * When booted with the BIOS set to Android mode the Chuwi Hi8 (CWI509) DSDT
652 * contains a whole bunch of bogus ACPI I2C devices and is missing entries
653 * for the touchscreen and the accelerometer.
654 */
655static const struct property_entry chuwi_hi8_gsl1680_props[] = {
656 PROPERTY_ENTRY_U32("touchscreen-size-x", 1665),
657 PROPERTY_ENTRY_U32("touchscreen-size-y", 1140),
658 PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
659 PROPERTY_ENTRY_BOOL("silead,home-button"),
660 PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-chuwi-hi8.fw"),
661 { }
662};
663
664static const struct software_node chuwi_hi8_gsl1680_node = {
665 .properties = chuwi_hi8_gsl1680_props,
666};
667
668static const char * const chuwi_hi8_mount_matrix[] = {
669 "1", "0", "0",
670 "0", "-1", "0",
671 "0", "0", "1"
672};
673
674static const struct property_entry chuwi_hi8_bma250e_props[] = {
675 PROPERTY_ENTRY_STRING_ARRAY("mount-matrix", chuwi_hi8_mount_matrix),
676 { }
677};
678
679static const struct software_node chuwi_hi8_bma250e_node = {
680 .properties = chuwi_hi8_bma250e_props,
681};
682
683static const struct x86_i2c_client_info chuwi_hi8_i2c_clients[] __initconst = {
684 {
685 /* Silead touchscreen */
686 .board_info = {
687 .type = "gsl1680",
688 .addr = 0x40,
689 .swnode = &chuwi_hi8_gsl1680_node,
690 },
691 .adapter_path = "\\_SB_.I2C4",
692 .irq_data = {
693 .type = X86_ACPI_IRQ_TYPE_APIC,
694 .index = 0x44,
695 .trigger = ACPI_EDGE_SENSITIVE,
696 .polarity = ACPI_ACTIVE_HIGH,
697 },
698 }, {
699 /* BMA250E accelerometer */
700 .board_info = {
701 .type = "bma250e",
702 .addr = 0x18,
703 .swnode = &chuwi_hi8_bma250e_node,
704 },
705 .adapter_path = "\\_SB_.I2C3",
706 .irq_data = {
707 .type = X86_ACPI_IRQ_TYPE_GPIOINT,
708 .chip = "INT33FC:02",
709 .index = 23,
710 .trigger = ACPI_LEVEL_SENSITIVE,
711 .polarity = ACPI_ACTIVE_HIGH,
712 },
713 },
714};
715
716static int __init chuwi_hi8_init(void)
717{
718 /*
719 * Avoid the acpi_unregister_gsi() call in x86_acpi_irq_helper_get()
720 * breaking the touchscreen + logging various errors when the Windows
721 * BIOS is used.
722 */
723 if (acpi_dev_present("MSSL0001", NULL, 1))
724 return -ENODEV;
725
726 return 0;
727}
728
729static const struct x86_dev_info chuwi_hi8_info __initconst = {
730 .i2c_client_info = chuwi_hi8_i2c_clients,
731 .i2c_client_count = ARRAY_SIZE(chuwi_hi8_i2c_clients),
732 .init = chuwi_hi8_init,
733};
734
735#define CZC_EC_EXTRA_PORT 0x68
736#define CZC_EC_ANDROID_KEYS 0x63
737
738static int __init czc_p10t_init(void)
739{
740 /*
741 * The device boots up in "Windows 7" mode, when the home button sends a
742 * Windows specific key sequence (Left Meta + D) and the second button
743 * sends an unknown one while also toggling the Radio Kill Switch.
744 * This is a surprising behavior when the second button is labeled "Back".
745 *
746 * The vendor-supplied Android-x86 build switches the device to a "Android"
747 * mode by writing value 0x63 to the I/O port 0x68. This just seems to just
748 * set bit 6 on address 0x96 in the EC region; switching the bit directly
749 * seems to achieve the same result. It uses a "p10t_switcher" to do the
750 * job. It doesn't seem to be able to do anything else, and no other use
751 * of the port 0x68 is known.
752 *
753 * In the Android mode, the home button sends just a single scancode,
754 * which can be handled in Linux userspace more reasonably and the back
755 * button only sends a scancode without toggling the kill switch.
756 * The scancode can then be mapped either to Back or RF Kill functionality
757 * in userspace, depending on how the button is labeled on that particular
758 * model.
759 */
760 outb(CZC_EC_ANDROID_KEYS, CZC_EC_EXTRA_PORT);
761 return 0;
762}
763
764static const struct x86_dev_info czc_p10t __initconst = {
765 .init = czc_p10t_init,
766};
767
768/* Lenovo Yoga Book X90F / X91F / X91L need manual instantiation of the fg client */
769static const struct x86_i2c_client_info lenovo_yogabook_x9x_i2c_clients[] __initconst = {
770 {
771 /* BQ27542 fuel-gauge */
772 .board_info = {
773 .type = "bq27542",
774 .addr = 0x55,
775 .dev_name = "bq27542",
776 .swnode = &fg_bq25890_supply_node,
777 },
778 .adapter_path = "\\_SB_.PCI0.I2C1",
779 },
780};
781
782static const struct x86_dev_info lenovo_yogabook_x9x_info __initconst = {
783 .i2c_client_info = lenovo_yogabook_x9x_i2c_clients,
784 .i2c_client_count = ARRAY_SIZE(lenovo_yogabook_x9x_i2c_clients),
785};
786
787/* Lenovo Yoga Tablet 2 1050F/L's Android factory img has everything hardcoded */
788static const struct property_entry lenovo_yoga_tab2_830_1050_bq24190_props[] = {
789 PROPERTY_ENTRY_STRING_ARRAY("supplied-from", tusb1211_chg_det_psy),
790 PROPERTY_ENTRY_REF("monitored-battery", &generic_lipo_hv_4v35_battery_node),
791 PROPERTY_ENTRY_BOOL("omit-battery-class"),
792 PROPERTY_ENTRY_BOOL("disable-reset"),
793 { }
794};
795
796static const struct software_node lenovo_yoga_tab2_830_1050_bq24190_node = {
797 .properties = lenovo_yoga_tab2_830_1050_bq24190_props,
798};
799
800/* This gets filled by lenovo_yoga_tab2_830_1050_init() */
801static struct rmi_device_platform_data lenovo_yoga_tab2_830_1050_rmi_pdata = { };
802
803static struct lp855x_platform_data lenovo_yoga_tab2_830_1050_lp8557_pdata = {
804 .device_control = 0x86,
805 .initial_brightness = 128,
806};
807
808static const struct x86_i2c_client_info lenovo_yoga_tab2_830_1050_i2c_clients[] __initconst = {
809 {
810 /* bq24292i battery charger */
811 .board_info = {
812 .type = "bq24190",
813 .addr = 0x6b,
814 .dev_name = "bq24292i",
815 .swnode = &lenovo_yoga_tab2_830_1050_bq24190_node,
816 .platform_data = &bq24190_pdata,
817 },
818 .adapter_path = "\\_SB_.I2C1",
819 .irq_data = {
820 .type = X86_ACPI_IRQ_TYPE_GPIOINT,
821 .chip = "INT33FC:02",
822 .index = 2,
823 .trigger = ACPI_EDGE_SENSITIVE,
824 .polarity = ACPI_ACTIVE_HIGH,
825 },
826 }, {
827 /* BQ27541 fuel-gauge */
828 .board_info = {
829 .type = "bq27541",
830 .addr = 0x55,
831 .dev_name = "bq27541",
832 .swnode = &fg_bq24190_supply_node,
833 },
834 .adapter_path = "\\_SB_.I2C1",
835 }, {
836 /* Synaptics RMI touchscreen */
837 .board_info = {
838 .type = "rmi4_i2c",
839 .addr = 0x38,
840 .dev_name = "rmi4_i2c",
841 .platform_data = &lenovo_yoga_tab2_830_1050_rmi_pdata,
842 },
843 .adapter_path = "\\_SB_.I2C6",
844 .irq_data = {
845 .type = X86_ACPI_IRQ_TYPE_APIC,
846 .index = 0x45,
847 .trigger = ACPI_EDGE_SENSITIVE,
848 .polarity = ACPI_ACTIVE_HIGH,
849 },
850 }, {
851 /* LP8557 Backlight controller */
852 .board_info = {
853 .type = "lp8557",
854 .addr = 0x2c,
855 .dev_name = "lp8557",
856 .platform_data = &lenovo_yoga_tab2_830_1050_lp8557_pdata,
857 },
858 .adapter_path = "\\_SB_.I2C3",
859 },
860};
861
862static struct gpiod_lookup_table lenovo_yoga_tab2_830_1050_int3496_gpios = {
863 .dev_id = "intel-int3496",
864 .table = {
865 GPIO_LOOKUP("INT33FC:02", 1, "mux", GPIO_ACTIVE_LOW),
866 GPIO_LOOKUP("INT33FC:02", 24, "id", GPIO_ACTIVE_HIGH),
867 { }
868 },
869};
870
871#define LENOVO_YOGA_TAB2_830_1050_CODEC_NAME "spi-10WM5102:00"
872
873static struct gpiod_lookup_table lenovo_yoga_tab2_830_1050_codec_gpios = {
874 .dev_id = LENOVO_YOGA_TAB2_830_1050_CODEC_NAME,
875 .table = {
876 GPIO_LOOKUP("gpio_crystalcove", 3, "reset", GPIO_ACTIVE_HIGH),
877 GPIO_LOOKUP("INT33FC:01", 23, "wlf,ldoena", GPIO_ACTIVE_HIGH),
878 GPIO_LOOKUP("arizona", 2, "wlf,spkvdd-ena", GPIO_ACTIVE_HIGH),
879 GPIO_LOOKUP("arizona", 4, "wlf,micd-pol", GPIO_ACTIVE_LOW),
880 { }
881 },
882};
883
884static struct gpiod_lookup_table * const lenovo_yoga_tab2_830_1050_gpios[] = {
885 &lenovo_yoga_tab2_830_1050_int3496_gpios,
886 &lenovo_yoga_tab2_830_1050_codec_gpios,
887 NULL
888};
889
890static int __init lenovo_yoga_tab2_830_1050_init(void);
891static void lenovo_yoga_tab2_830_1050_exit(void);
892
893static struct x86_dev_info lenovo_yoga_tab2_830_1050_info __initdata = {
894 .i2c_client_info = lenovo_yoga_tab2_830_1050_i2c_clients,
895 /* i2c_client_count gets set by lenovo_yoga_tab2_830_1050_init() */
896 .pdev_info = int3496_pdevs,
897 .pdev_count = ARRAY_SIZE(int3496_pdevs),
898 .gpiod_lookup_tables = lenovo_yoga_tab2_830_1050_gpios,
899 .bat_swnode = &generic_lipo_hv_4v35_battery_node,
900 .modules = bq24190_modules,
901 .invalid_aei_gpiochip = "INT33FC:02",
902 .init = lenovo_yoga_tab2_830_1050_init,
903 .exit = lenovo_yoga_tab2_830_1050_exit,
904};
905
906/*
907 * The Lenovo Yoga Tablet 2 830 and 1050 (8" vs 10") versions use the same
908 * mainboard, but they need some different treatment related to the display:
909 * 1. The 830 uses a portrait LCD panel with a landscape touchscreen, requiring
910 * the touchscreen driver to adjust the touch-coords to match the LCD.
911 * 2. Both use an TI LP8557 LED backlight controller. On the 1050 the LP8557's
912 * PWM input is connected to the PMIC's PWM output and everything works fine
913 * with the defaults programmed into the LP8557 by the BIOS.
914 * But on the 830 the LP8557's PWM input is connected to a PWM output coming
915 * from the LCD panel's controller. The Android code has a hack in the i915
916 * driver to write the non-standard DSI reg 0x9f with the desired backlight
917 * level to set the duty-cycle of the LCD's PWM output.
918 *
919 * To avoid having to have a similar hack in the mainline kernel the LP8557
920 * entry in lenovo_yoga_tab2_830_1050_i2c_clients instead just programs the
921 * LP8557 to directly set the level, ignoring the PWM input. This means that
922 * the LP8557 i2c_client should only be instantiated on the 830.
923 */
924static int __init lenovo_yoga_tab2_830_1050_init_display(void)
925{
926 struct gpio_desc *gpiod;
927 int ret;
928
929 /* Use PMIC GPIO 10 bootstrap pin to differentiate 830 vs 1050 */
930 ret = x86_android_tablet_get_gpiod("gpio_crystalcove", 10, &gpiod);
931 if (ret)
932 return ret;
933
934 ret = gpiod_get_value_cansleep(gpiod);
935 if (ret) {
936 pr_info("detected Lenovo Yoga Tablet 2 1050F/L\n");
937 lenovo_yoga_tab2_830_1050_info.i2c_client_count =
938 ARRAY_SIZE(lenovo_yoga_tab2_830_1050_i2c_clients) - 1;
939 } else {
940 pr_info("detected Lenovo Yoga Tablet 2 830F/L\n");
941 lenovo_yoga_tab2_830_1050_rmi_pdata.sensor_pdata.axis_align.swap_axes = true;
942 lenovo_yoga_tab2_830_1050_rmi_pdata.sensor_pdata.axis_align.flip_y = true;
943 lenovo_yoga_tab2_830_1050_info.i2c_client_count =
944 ARRAY_SIZE(lenovo_yoga_tab2_830_1050_i2c_clients);
945 }
946
947 return 0;
948}
949
950/* SUS (INT33FC:02) pin 6 needs to be configured as pmu_clk for the audio codec */
951static const struct pinctrl_map lenovo_yoga_tab2_830_1050_codec_pinctrl_map =
952 PIN_MAP_MUX_GROUP(LENOVO_YOGA_TAB2_830_1050_CODEC_NAME, "codec_32khz_clk",
953 "INT33FC:02", "pmu_clk2_grp", "pmu_clk");
954
955static struct pinctrl *lenovo_yoga_tab2_830_1050_codec_pinctrl;
956static struct sys_off_handler *lenovo_yoga_tab2_830_1050_sys_off_handler;
957
958static int __init lenovo_yoga_tab2_830_1050_init_codec(void)
959{
960 struct device *codec_dev;
961 struct pinctrl *pinctrl;
962 int ret;
963
964 codec_dev = bus_find_device_by_name(&spi_bus_type, NULL,
965 LENOVO_YOGA_TAB2_830_1050_CODEC_NAME);
966 if (!codec_dev) {
967 pr_err("error cannot find %s device\n", LENOVO_YOGA_TAB2_830_1050_CODEC_NAME);
968 return -ENODEV;
969 }
970
971 ret = pinctrl_register_mappings(&lenovo_yoga_tab2_830_1050_codec_pinctrl_map, 1);
972 if (ret)
973 goto err_put_device;
974
975 pinctrl = pinctrl_get_select(codec_dev, "codec_32khz_clk");
976 if (IS_ERR(pinctrl)) {
977 ret = dev_err_probe(codec_dev, PTR_ERR(pinctrl), "selecting codec_32khz_clk\n");
978 goto err_unregister_mappings;
979 }
980
981 /* We're done with the codec_dev now */
982 put_device(codec_dev);
983
984 lenovo_yoga_tab2_830_1050_codec_pinctrl = pinctrl;
985 return 0;
986
987err_unregister_mappings:
988 pinctrl_unregister_mappings(&lenovo_yoga_tab2_830_1050_codec_pinctrl_map);
989err_put_device:
990 put_device(codec_dev);
991 return ret;
992}
993
994/*
995 * These tablet's DSDT does not set acpi_gbl_reduced_hardware, so acpi_power_off
996 * gets used as pm_power_off handler. This causes "poweroff" on these tablets
997 * to hang hard. Requiring pressing the powerbutton for 30 seconds *twice*
998 * followed by a normal 3 second press to recover. Avoid this by doing an EFI
999 * poweroff instead.
1000 */
1001static int lenovo_yoga_tab2_830_1050_power_off(struct sys_off_data *data)
1002{
1003 efi.reset_system(EFI_RESET_SHUTDOWN, EFI_SUCCESS, 0, NULL);
1004
1005 return NOTIFY_DONE;
1006}
1007
1008static int __init lenovo_yoga_tab2_830_1050_init(void)
1009{
1010 int ret;
1011
1012 ret = lenovo_yoga_tab2_830_1050_init_display();
1013 if (ret)
1014 return ret;
1015
1016 ret = lenovo_yoga_tab2_830_1050_init_codec();
1017 if (ret)
1018 return ret;
1019
1020 /* SYS_OFF_PRIO_FIRMWARE + 1 so that it runs before acpi_power_off */
1021 lenovo_yoga_tab2_830_1050_sys_off_handler =
1022 register_sys_off_handler(SYS_OFF_MODE_POWER_OFF, SYS_OFF_PRIO_FIRMWARE + 1,
1023 lenovo_yoga_tab2_830_1050_power_off, NULL);
1024 if (IS_ERR(lenovo_yoga_tab2_830_1050_sys_off_handler))
1025 return PTR_ERR(lenovo_yoga_tab2_830_1050_sys_off_handler);
1026
1027 return 0;
1028}
1029
1030static void lenovo_yoga_tab2_830_1050_exit(void)
1031{
1032 unregister_sys_off_handler(lenovo_yoga_tab2_830_1050_sys_off_handler);
1033
1034 if (lenovo_yoga_tab2_830_1050_codec_pinctrl) {
1035 pinctrl_put(lenovo_yoga_tab2_830_1050_codec_pinctrl);
1036 pinctrl_unregister_mappings(&lenovo_yoga_tab2_830_1050_codec_pinctrl_map);
1037 }
1038}
1039
1040/* Lenovo Yoga Tab 3 Pro YT3-X90F */
1041
1042/*
1043 * There are 2 batteries, with 2 bq27500 fuel-gauges and 2 bq25892 chargers,
1044 * "bq25890-charger-1" is instantiated from: drivers/i2c/busses/i2c-cht-wc.c.
1045 */
1046static const char * const lenovo_yt3_bq25892_0_suppliers[] = { "cht_wcove_pwrsrc" };
1047static const char * const bq25890_1_psy[] = { "bq25890-charger-1" };
1048
1049static const struct property_entry fg_bq25890_1_supply_props[] = {
1050 PROPERTY_ENTRY_STRING_ARRAY("supplied-from", bq25890_1_psy),
1051 { }
1052};
1053
1054static const struct software_node fg_bq25890_1_supply_node = {
1055 .properties = fg_bq25890_1_supply_props,
1056};
1057
1058/* bq25892 charger settings for the flat lipo battery behind the screen */
1059static const struct property_entry lenovo_yt3_bq25892_0_props[] = {
1060 PROPERTY_ENTRY_STRING_ARRAY("supplied-from", lenovo_yt3_bq25892_0_suppliers),
1061 PROPERTY_ENTRY_STRING("linux,power-supply-name", "bq25892-second-chrg"),
1062 PROPERTY_ENTRY_U32("linux,iinlim-percentage", 40),
1063 PROPERTY_ENTRY_BOOL("linux,skip-reset"),
1064 /* Values taken from Android Factory Image */
1065 PROPERTY_ENTRY_U32("ti,charge-current", 2048000),
1066 PROPERTY_ENTRY_U32("ti,battery-regulation-voltage", 4352000),
1067 PROPERTY_ENTRY_U32("ti,termination-current", 128000),
1068 PROPERTY_ENTRY_U32("ti,precharge-current", 128000),
1069 PROPERTY_ENTRY_U32("ti,minimum-sys-voltage", 3700000),
1070 PROPERTY_ENTRY_U32("ti,boost-voltage", 4998000),
1071 PROPERTY_ENTRY_U32("ti,boost-max-current", 500000),
1072 PROPERTY_ENTRY_BOOL("ti,use-ilim-pin"),
1073 { }
1074};
1075
1076static const struct software_node lenovo_yt3_bq25892_0_node = {
1077 .properties = lenovo_yt3_bq25892_0_props,
1078};
1079
1080static const struct x86_i2c_client_info lenovo_yt3_i2c_clients[] __initconst = {
1081 {
1082 /* bq27500 fuel-gauge for the flat lipo battery behind the screen */
1083 .board_info = {
1084 .type = "bq27500",
1085 .addr = 0x55,
1086 .dev_name = "bq27500_0",
1087 .swnode = &fg_bq25890_supply_node,
1088 },
1089 .adapter_path = "\\_SB_.PCI0.I2C1",
1090 }, {
1091 /* bq25892 charger for the flat lipo battery behind the screen */
1092 .board_info = {
1093 .type = "bq25892",
1094 .addr = 0x6b,
1095 .dev_name = "bq25892_0",
1096 .swnode = &lenovo_yt3_bq25892_0_node,
1097 },
1098 .adapter_path = "\\_SB_.PCI0.I2C1",
1099 .irq_data = {
1100 .type = X86_ACPI_IRQ_TYPE_GPIOINT,
1101 .chip = "INT33FF:01",
1102 .index = 5,
1103 .trigger = ACPI_EDGE_SENSITIVE,
1104 .polarity = ACPI_ACTIVE_LOW,
1105 },
1106 }, {
1107 /* bq27500 fuel-gauge for the round li-ion cells in the hinge */
1108 .board_info = {
1109 .type = "bq27500",
1110 .addr = 0x55,
1111 .dev_name = "bq27500_1",
1112 .swnode = &fg_bq25890_1_supply_node,
1113 },
1114 .adapter_path = "\\_SB_.PCI0.I2C2",
1115 }
1116};
1117
1118static int __init lenovo_yt3_init(void)
1119{
1120 struct gpio_desc *gpiod;
1121 int ret;
1122
1123 /*
1124 * The "bq25892_0" charger IC has its /CE (Charge-Enable) and OTG pins
1125 * connected to GPIOs, rather then having them hardwired to the correct
1126 * values as is normally done.
1127 *
1128 * The bq25890_charger driver controls these through I2C, but this only
1129 * works if not overridden by the pins. Set these pins here:
1130 * 1. Set /CE to 0 to allow charging.
1131 * 2. Set OTG to 0 disable V5 boost output since the 5V boost output of
1132 * the main "bq25892_1" charger is used when necessary.
1133 */
1134
1135 /* /CE pin */
1136 ret = x86_android_tablet_get_gpiod("INT33FF:02", 22, &gpiod);
1137 if (ret < 0)
1138 return ret;
1139
1140 /*
1141 * The gpio_desc returned by x86_android_tablet_get_gpiod() is a "raw"
1142 * gpio_desc, that is there is no way to pass lookup-flags like
1143 * GPIO_ACTIVE_LOW. Set the GPIO to 0 here to enable charging since
1144 * the /CE pin is active-low, but not marked as such in the gpio_desc.
1145 */
1146 gpiod_set_value(gpiod, 0);
1147
1148 /* OTG pin */
1149 ret = x86_android_tablet_get_gpiod("INT33FF:03", 19, &gpiod);
1150 if (ret < 0)
1151 return ret;
1152
1153 gpiod_set_value(gpiod, 0);
1154
1155 return 0;
1156}
1157
1158static const struct x86_dev_info lenovo_yt3_info __initconst = {
1159 .i2c_client_info = lenovo_yt3_i2c_clients,
1160 .i2c_client_count = ARRAY_SIZE(lenovo_yt3_i2c_clients),
1161 .init = lenovo_yt3_init,
1162};
1163
1164/* Medion Lifetab S10346 tablets have an Android factory img with everything hardcoded */
1165static const char * const medion_lifetab_s10346_accel_mount_matrix[] = {
1166 "0", "1", "0",
1167 "1", "0", "0",
1168 "0", "0", "1"
1169};
1170
1171static const struct property_entry medion_lifetab_s10346_accel_props[] = {
1172 PROPERTY_ENTRY_STRING_ARRAY("mount-matrix", medion_lifetab_s10346_accel_mount_matrix),
1173 { }
1174};
1175
1176static const struct software_node medion_lifetab_s10346_accel_node = {
1177 .properties = medion_lifetab_s10346_accel_props,
1178};
1179
1180/* Note the LCD panel is mounted upside down, this is correctly indicated in the VBT */
1181static const struct property_entry medion_lifetab_s10346_touchscreen_props[] = {
1182 PROPERTY_ENTRY_BOOL("touchscreen-inverted-x"),
1183 PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
1184 { }
1185};
1186
1187static const struct software_node medion_lifetab_s10346_touchscreen_node = {
1188 .properties = medion_lifetab_s10346_touchscreen_props,
1189};
1190
1191static const struct x86_i2c_client_info medion_lifetab_s10346_i2c_clients[] __initconst = {
1192 {
1193 /* kxtj21009 accel */
1194 .board_info = {
1195 .type = "kxtj21009",
1196 .addr = 0x0f,
1197 .dev_name = "kxtj21009",
1198 .swnode = &medion_lifetab_s10346_accel_node,
1199 },
1200 .adapter_path = "\\_SB_.I2C3",
1201 .irq_data = {
1202 .type = X86_ACPI_IRQ_TYPE_GPIOINT,
1203 .chip = "INT33FC:02",
1204 .index = 23,
1205 .trigger = ACPI_EDGE_SENSITIVE,
1206 .polarity = ACPI_ACTIVE_HIGH,
1207 },
1208 }, {
1209 /* goodix touchscreen */
1210 .board_info = {
1211 .type = "GDIX1001:00",
1212 .addr = 0x14,
1213 .dev_name = "goodix_ts",
1214 .swnode = &medion_lifetab_s10346_touchscreen_node,
1215 },
1216 .adapter_path = "\\_SB_.I2C4",
1217 .irq_data = {
1218 .type = X86_ACPI_IRQ_TYPE_APIC,
1219 .index = 0x44,
1220 .trigger = ACPI_EDGE_SENSITIVE,
1221 .polarity = ACPI_ACTIVE_LOW,
1222 },
1223 },
1224};
1225
1226static struct gpiod_lookup_table medion_lifetab_s10346_goodix_gpios = {
1227 .dev_id = "i2c-goodix_ts",
1228 .table = {
1229 GPIO_LOOKUP("INT33FC:01", 26, "reset", GPIO_ACTIVE_HIGH),
1230 GPIO_LOOKUP("INT33FC:02", 3, "irq", GPIO_ACTIVE_HIGH),
1231 { }
1232 },
1233};
1234
1235static struct gpiod_lookup_table * const medion_lifetab_s10346_gpios[] = {
1236 &medion_lifetab_s10346_goodix_gpios,
1237 NULL
1238};
1239
1240static const struct x86_dev_info medion_lifetab_s10346_info __initconst = {
1241 .i2c_client_info = medion_lifetab_s10346_i2c_clients,
1242 .i2c_client_count = ARRAY_SIZE(medion_lifetab_s10346_i2c_clients),
1243 .gpiod_lookup_tables = medion_lifetab_s10346_gpios,
1244};
1245
1246/* Nextbook Ares 8 tablets have an Android factory img with everything hardcoded */
1247static const char * const nextbook_ares8_accel_mount_matrix[] = {
1248 "0", "-1", "0",
1249 "-1", "0", "0",
1250 "0", "0", "1"
1251};
1252
1253static const struct property_entry nextbook_ares8_accel_props[] = {
1254 PROPERTY_ENTRY_STRING_ARRAY("mount-matrix", nextbook_ares8_accel_mount_matrix),
1255 { }
1256};
1257
1258static const struct software_node nextbook_ares8_accel_node = {
1259 .properties = nextbook_ares8_accel_props,
1260};
1261
1262static const struct property_entry nextbook_ares8_touchscreen_props[] = {
1263 PROPERTY_ENTRY_U32("touchscreen-size-x", 800),
1264 PROPERTY_ENTRY_U32("touchscreen-size-y", 1280),
1265 { }
1266};
1267
1268static const struct software_node nextbook_ares8_touchscreen_node = {
1269 .properties = nextbook_ares8_touchscreen_props,
1270};
1271
1272static const struct x86_i2c_client_info nextbook_ares8_i2c_clients[] __initconst = {
1273 {
1274 /* Freescale MMA8653FC accel */
1275 .board_info = {
1276 .type = "mma8653",
1277 .addr = 0x1d,
1278 .dev_name = "mma8653",
1279 .swnode = &nextbook_ares8_accel_node,
1280 },
1281 .adapter_path = "\\_SB_.I2C3",
1282 }, {
1283 /* FT5416DQ9 touchscreen controller */
1284 .board_info = {
1285 .type = "edt-ft5x06",
1286 .addr = 0x38,
1287 .dev_name = "ft5416",
1288 .swnode = &nextbook_ares8_touchscreen_node,
1289 },
1290 .adapter_path = "\\_SB_.I2C4",
1291 .irq_data = {
1292 .type = X86_ACPI_IRQ_TYPE_GPIOINT,
1293 .chip = "INT33FC:02",
1294 .index = 3,
1295 .trigger = ACPI_EDGE_SENSITIVE,
1296 .polarity = ACPI_ACTIVE_LOW,
1297 },
1298 },
1299};
1300
1301static struct gpiod_lookup_table nextbook_ares8_int3496_gpios = {
1302 .dev_id = "intel-int3496",
1303 .table = {
1304 GPIO_LOOKUP("INT33FC:02", 1, "mux", GPIO_ACTIVE_HIGH),
1305 GPIO_LOOKUP("INT33FC:02", 18, "id", GPIO_ACTIVE_HIGH),
1306 { }
1307 },
1308};
1309
1310static struct gpiod_lookup_table * const nextbook_ares8_gpios[] = {
1311 &nextbook_ares8_int3496_gpios,
1312 NULL
1313};
1314
1315static const struct x86_dev_info nextbook_ares8_info __initconst = {
1316 .i2c_client_info = nextbook_ares8_i2c_clients,
1317 .i2c_client_count = ARRAY_SIZE(nextbook_ares8_i2c_clients),
1318 .pdev_info = int3496_pdevs,
1319 .pdev_count = ARRAY_SIZE(int3496_pdevs),
1320 .gpiod_lookup_tables = nextbook_ares8_gpios,
1321 .invalid_aei_gpiochip = "INT33FC:02",
1322};
1323
1324/*
1325 * Whitelabel (sold as various brands) TM800A550L tablets.
1326 * These tablet's DSDT contains a whole bunch of bogus ACPI I2C devices
1327 * (removed through acpi_quirk_skip_i2c_client_enumeration()) and
1328 * the touchscreen fwnode has the wrong GPIOs.
1329 */
1330static const char * const whitelabel_tm800a550l_accel_mount_matrix[] = {
1331 "-1", "0", "0",
1332 "0", "1", "0",
1333 "0", "0", "1"
1334};
1335
1336static const struct property_entry whitelabel_tm800a550l_accel_props[] = {
1337 PROPERTY_ENTRY_STRING_ARRAY("mount-matrix", whitelabel_tm800a550l_accel_mount_matrix),
1338 { }
1339};
1340
1341static const struct software_node whitelabel_tm800a550l_accel_node = {
1342 .properties = whitelabel_tm800a550l_accel_props,
1343};
1344
1345static const struct property_entry whitelabel_tm800a550l_goodix_props[] = {
1346 PROPERTY_ENTRY_STRING("firmware-name", "gt912-tm800a550l.fw"),
1347 PROPERTY_ENTRY_STRING("goodix,config-name", "gt912-tm800a550l.cfg"),
1348 PROPERTY_ENTRY_U32("goodix,main-clk", 54),
1349 { }
1350};
1351
1352static const struct software_node whitelabel_tm800a550l_goodix_node = {
1353 .properties = whitelabel_tm800a550l_goodix_props,
1354};
1355
1356static const struct x86_i2c_client_info whitelabel_tm800a550l_i2c_clients[] __initconst = {
1357 {
1358 /* goodix touchscreen */
1359 .board_info = {
1360 .type = "GDIX1001:00",
1361 .addr = 0x14,
1362 .dev_name = "goodix_ts",
1363 .swnode = &whitelabel_tm800a550l_goodix_node,
1364 },
1365 .adapter_path = "\\_SB_.I2C2",
1366 .irq_data = {
1367 .type = X86_ACPI_IRQ_TYPE_APIC,
1368 .index = 0x44,
1369 .trigger = ACPI_EDGE_SENSITIVE,
1370 .polarity = ACPI_ACTIVE_HIGH,
1371 },
1372 }, {
1373 /* kxcj91008 accel */
1374 .board_info = {
1375 .type = "kxcj91008",
1376 .addr = 0x0f,
1377 .dev_name = "kxcj91008",
1378 .swnode = &whitelabel_tm800a550l_accel_node,
1379 },
1380 .adapter_path = "\\_SB_.I2C3",
1381 },
1382};
1383
1384static struct gpiod_lookup_table whitelabel_tm800a550l_goodix_gpios = {
1385 .dev_id = "i2c-goodix_ts",
1386 .table = {
1387 GPIO_LOOKUP("INT33FC:01", 26, "reset", GPIO_ACTIVE_HIGH),
1388 GPIO_LOOKUP("INT33FC:02", 3, "irq", GPIO_ACTIVE_HIGH),
1389 { }
1390 },
1391};
1392
1393static struct gpiod_lookup_table * const whitelabel_tm800a550l_gpios[] = {
1394 &whitelabel_tm800a550l_goodix_gpios,
1395 NULL
1396};
1397
1398static const struct x86_dev_info whitelabel_tm800a550l_info __initconst = {
1399 .i2c_client_info = whitelabel_tm800a550l_i2c_clients,
1400 .i2c_client_count = ARRAY_SIZE(whitelabel_tm800a550l_i2c_clients),
1401 .gpiod_lookup_tables = whitelabel_tm800a550l_gpios,
1402};
1403
1404/*
1405 * If the EFI bootloader is not Xiaomi's own signed Android loader, then the
1406 * Xiaomi Mi Pad 2 X86 tablet sets OSID in the DSDT to 1 (Windows), causing
1407 * a bunch of devices to be hidden.
1408 *
1409 * This takes care of instantiating the hidden devices manually.
1410 */
1411static const struct x86_i2c_client_info xiaomi_mipad2_i2c_clients[] __initconst = {
1412 {
1413 /* BQ27520 fuel-gauge */
1414 .board_info = {
1415 .type = "bq27520",
1416 .addr = 0x55,
1417 .dev_name = "bq27520",
1418 .swnode = &fg_bq25890_supply_node,
1419 },
1420 .adapter_path = "\\_SB_.PCI0.I2C1",
1421 }, {
1422 /* KTD2026 RGB notification LED controller */
1423 .board_info = {
1424 .type = "ktd2026",
1425 .addr = 0x30,
1426 .dev_name = "ktd2026",
1427 },
1428 .adapter_path = "\\_SB_.PCI0.I2C3",
1429 },
1430};
1431
1432static const struct x86_dev_info xiaomi_mipad2_info __initconst = {
1433 .i2c_client_info = xiaomi_mipad2_i2c_clients,
1434 .i2c_client_count = ARRAY_SIZE(xiaomi_mipad2_i2c_clients),
1435};
1436
1437static const struct dmi_system_id x86_android_tablet_ids[] __initconst = {
1438 {
1439 /* Advantech MICA-071 */
1440 .matches = {
1441 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Advantech"),
1442 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "MICA-071"),
1443 },
1444 .driver_data = (void *)&advantech_mica_071_info,
1445 },
1446 {
1447 /* Asus MeMO Pad 7 ME176C */
1448 .matches = {
1449 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
1450 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ME176C"),
1451 },
1452 .driver_data = (void *)&asus_me176c_info,
1453 },
1454 {
1455 /* Asus TF103C */
1456 .matches = {
1457 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
1458 DMI_MATCH(DMI_PRODUCT_NAME, "TF103C"),
1459 },
1460 .driver_data = (void *)&asus_tf103c_info,
1461 },
1462 {
1463 /* Chuwi Hi8 (CWI509) */
1464 .matches = {
1465 DMI_MATCH(DMI_BOARD_VENDOR, "Hampoo"),
1466 DMI_MATCH(DMI_BOARD_NAME, "BYT-PA03C"),
1467 DMI_MATCH(DMI_SYS_VENDOR, "ilife"),
1468 DMI_MATCH(DMI_PRODUCT_NAME, "S806"),
1469 },
1470 .driver_data = (void *)&chuwi_hi8_info,
1471 },
1472 {
1473 /* CZC P10T */
1474 .ident = "CZC ODEON TPC-10 (\"P10T\")",
1475 .matches = {
1476 DMI_MATCH(DMI_SYS_VENDOR, "CZC"),
1477 DMI_MATCH(DMI_PRODUCT_NAME, "ODEON*TPC-10"),
1478 },
1479 .driver_data = (void *)&czc_p10t,
1480 },
1481 {
1482 /* CZC P10T variant */
1483 .ident = "ViewSonic ViewPad 10",
1484 .matches = {
1485 DMI_MATCH(DMI_SYS_VENDOR, "ViewSonic"),
1486 DMI_MATCH(DMI_PRODUCT_NAME, "VPAD10"),
1487 },
1488 .driver_data = (void *)&czc_p10t,
1489 },
1490 {
1491 /* Lenovo Yoga Book X90F / X91F / X91L */
1492 .matches = {
1493 /* Non exact match to match all versions */
1494 DMI_MATCH(DMI_PRODUCT_NAME, "Lenovo YB1-X9"),
1495 },
1496 .driver_data = (void *)&lenovo_yogabook_x9x_info,
1497 },
1498 {
1499 /*
1500 * Lenovo Yoga Tablet 2 830F/L or 1050F/L (The 8" and 10"
1501 * Lenovo Yoga Tablet 2 use the same mainboard)
1502 */
1503 .matches = {
1504 DMI_MATCH(DMI_SYS_VENDOR, "Intel Corp."),
1505 DMI_MATCH(DMI_PRODUCT_NAME, "VALLEYVIEW C0 PLATFORM"),
1506 DMI_MATCH(DMI_BOARD_NAME, "BYT-T FFD8"),
1507 /* Partial match on beginning of BIOS version */
1508 DMI_MATCH(DMI_BIOS_VERSION, "BLADE_21"),
1509 },
1510 .driver_data = (void *)&lenovo_yoga_tab2_830_1050_info,
1511 },
1512 {
1513 /* Lenovo Yoga Tab 3 Pro YT3-X90F */
1514 .matches = {
1515 DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
1516 DMI_MATCH(DMI_PRODUCT_NAME, "CHERRYVIEW D1 PLATFORM"),
1517 DMI_MATCH(DMI_PRODUCT_VERSION, "Blade3-10A-001"),
1518 },
1519 .driver_data = (void *)&lenovo_yt3_info,
1520 },
1521 {
1522 /* Medion Lifetab S10346 */
1523 .matches = {
1524 DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
1525 DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
1526 /* Above strings are much too generic, also match on BIOS date */
1527 DMI_MATCH(DMI_BIOS_DATE, "10/22/2015"),
1528 },
1529 .driver_data = (void *)&medion_lifetab_s10346_info,
1530 },
1531 {
1532 /* Nextbook Ares 8 */
1533 .matches = {
1534 DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
1535 DMI_MATCH(DMI_PRODUCT_NAME, "M890BAP"),
1536 },
1537 .driver_data = (void *)&nextbook_ares8_info,
1538 },
1539 {
1540 /* Whitelabel (sold as various brands) TM800A550L */
1541 .matches = {
1542 DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
1543 DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
1544 /* Above strings are too generic, also match on BIOS version */
1545 DMI_MATCH(DMI_BIOS_VERSION, "ZY-8-BI-PX4S70VTR400-X423B-005-D"),
1546 },
1547 .driver_data = (void *)&whitelabel_tm800a550l_info,
1548 },
1549 {
1550 /* Xiaomi Mi Pad 2 */
1551 .matches = {
1552 DMI_MATCH(DMI_SYS_VENDOR, "Xiaomi Inc"),
1553 DMI_MATCH(DMI_PRODUCT_NAME, "Mipad2"),
1554 },
1555 .driver_data = (void *)&xiaomi_mipad2_info,
1556 },
1557 { }
1558};
1559MODULE_DEVICE_TABLE(dmi, x86_android_tablet_ids);
1560
1561static int i2c_client_count;
1562static int pdev_count;
1563static int serdev_count;
1564static struct i2c_client **i2c_clients;
1565static struct platform_device **pdevs;
1566static struct serdev_device **serdevs;
1567static struct gpiod_lookup_table * const *gpiod_lookup_tables;
1568static const struct software_node *bat_swnode;
1569static void (*exit_handler)(void);
1570
1571static __init int x86_instantiate_i2c_client(const struct x86_dev_info *dev_info,
1572 int idx)
1573{
1574 const struct x86_i2c_client_info *client_info = &dev_info->i2c_client_info[idx];
1575 struct i2c_board_info board_info = client_info->board_info;
1576 struct i2c_adapter *adap;
1577 acpi_handle handle;
1578 acpi_status status;
1579
1580 board_info.irq = x86_acpi_irq_helper_get(&client_info->irq_data);
1581 if (board_info.irq < 0)
1582 return board_info.irq;
1583
1584 status = acpi_get_handle(NULL, client_info->adapter_path, &handle);
1585 if (ACPI_FAILURE(status)) {
1586 pr_err("Error could not get %s handle\n", client_info->adapter_path);
1587 return -ENODEV;
1588 }
1589
1590 adap = i2c_acpi_find_adapter_by_handle(handle);
1591 if (!adap) {
1592 pr_err("error could not get %s adapter\n", client_info->adapter_path);
1593 return -ENODEV;
1594 }
1595
1596 i2c_clients[idx] = i2c_new_client_device(adap, &board_info);
1597 put_device(&adap->dev);
1598 if (IS_ERR(i2c_clients[idx]))
1599 return dev_err_probe(&adap->dev, PTR_ERR(i2c_clients[idx]),
1600 "creating I2C-client %d\n", idx);
1601
1602 return 0;
1603}
1604
1605static __init int x86_instantiate_serdev(const struct x86_serdev_info *info, int idx)
1606{
1607 struct acpi_device *ctrl_adev, *serdev_adev;
1608 struct serdev_device *serdev;
1609 struct device *ctrl_dev;
1610 int ret = -ENODEV;
1611
1612 ctrl_adev = acpi_dev_get_first_match_dev(info->ctrl_hid, info->ctrl_uid, -1);
1613 if (!ctrl_adev) {
1614 pr_err("error could not get %s/%s ctrl adev\n",
1615 info->ctrl_hid, info->ctrl_uid);
1616 return -ENODEV;
1617 }
1618
1619 serdev_adev = acpi_dev_get_first_match_dev(info->serdev_hid, NULL, -1);
1620 if (!serdev_adev) {
1621 pr_err("error could not get %s serdev adev\n", info->serdev_hid);
1622 goto put_ctrl_adev;
1623 }
1624
1625 /* get_first_physical_node() returns a weak ref, no need to put() it */
1626 ctrl_dev = acpi_get_first_physical_node(ctrl_adev);
1627 if (!ctrl_dev) {
1628 pr_err("error could not get %s/%s ctrl physical dev\n",
1629 info->ctrl_hid, info->ctrl_uid);
1630 goto put_serdev_adev;
1631 }
1632
1633 /* ctrl_dev now points to the controller's parent, get the controller */
1634 ctrl_dev = device_find_child_by_name(ctrl_dev, info->ctrl_devname);
1635 if (!ctrl_dev) {
1636 pr_err("error could not get %s/%s %s ctrl dev\n",
1637 info->ctrl_hid, info->ctrl_uid, info->ctrl_devname);
1638 goto put_serdev_adev;
1639 }
1640
1641 serdev = serdev_device_alloc(to_serdev_controller(ctrl_dev));
1642 if (!serdev) {
1643 ret = -ENOMEM;
1644 goto put_serdev_adev;
1645 }
1646
1647 ACPI_COMPANION_SET(&serdev->dev, serdev_adev);
1648 acpi_device_set_enumerated(serdev_adev);
1649
1650 ret = serdev_device_add(serdev);
1651 if (ret) {
1652 dev_err(&serdev->dev, "error %d adding serdev\n", ret);
1653 serdev_device_put(serdev);
1654 goto put_serdev_adev;
1655 }
1656
1657 serdevs[idx] = serdev;
1658
1659put_serdev_adev:
1660 acpi_dev_put(serdev_adev);
1661put_ctrl_adev:
1662 acpi_dev_put(ctrl_adev);
1663 return ret;
1664}
1665
1666static void x86_android_tablet_cleanup(void)
1667{
1668 int i;
1669
1670 for (i = 0; i < serdev_count; i++) {
1671 if (serdevs[i])
1672 serdev_device_remove(serdevs[i]);
1673 }
1674
1675 kfree(serdevs);
1676
1677 for (i = 0; i < pdev_count; i++)
1678 platform_device_unregister(pdevs[i]);
1679
1680 kfree(pdevs);
1681
1682 for (i = 0; i < i2c_client_count; i++)
1683 i2c_unregister_device(i2c_clients[i]);
1684
1685 kfree(i2c_clients);
1686
1687 if (exit_handler)
1688 exit_handler();
1689
1690 for (i = 0; gpiod_lookup_tables && gpiod_lookup_tables[i]; i++)
1691 gpiod_remove_lookup_table(gpiod_lookup_tables[i]);
1692
1693 software_node_unregister(bat_swnode);
1694}
1695
1696static __init int x86_android_tablet_init(void)
1697{
1698 const struct x86_dev_info *dev_info;
1699 const struct dmi_system_id *id;
1700 struct gpio_chip *chip;
1701 int i, ret = 0;
1702
1703 id = dmi_first_match(x86_android_tablet_ids);
1704 if (!id)
1705 return -ENODEV;
1706
1707 dev_info = id->driver_data;
1708
1709 /*
1710 * The broken DSDTs on these devices often also include broken
1711 * _AEI (ACPI Event Interrupt) handlers, disable these.
1712 */
1713 if (dev_info->invalid_aei_gpiochip) {
1714 chip = gpiochip_find(dev_info->invalid_aei_gpiochip,
1715 gpiochip_find_match_label);
1716 if (!chip) {
1717 pr_err("error cannot find GPIO chip %s\n", dev_info->invalid_aei_gpiochip);
1718 return -ENODEV;
1719 }
1720 acpi_gpiochip_free_interrupts(chip);
1721 }
1722
1723 /*
1724 * Since this runs from module_init() it cannot use -EPROBE_DEFER,
1725 * instead pre-load any modules which are listed as requirements.
1726 */
1727 for (i = 0; dev_info->modules && dev_info->modules[i]; i++)
1728 request_module(dev_info->modules[i]);
1729
1730 bat_swnode = dev_info->bat_swnode;
1731 if (bat_swnode) {
1732 ret = software_node_register(bat_swnode);
1733 if (ret)
1734 return ret;
1735 }
1736
1737 gpiod_lookup_tables = dev_info->gpiod_lookup_tables;
1738 for (i = 0; gpiod_lookup_tables && gpiod_lookup_tables[i]; i++)
1739 gpiod_add_lookup_table(gpiod_lookup_tables[i]);
1740
1741 if (dev_info->init) {
1742 ret = dev_info->init();
1743 if (ret < 0) {
1744 x86_android_tablet_cleanup();
1745 return ret;
1746 }
1747 exit_handler = dev_info->exit;
1748 }
1749
1750 i2c_clients = kcalloc(dev_info->i2c_client_count, sizeof(*i2c_clients), GFP_KERNEL);
1751 if (!i2c_clients) {
1752 x86_android_tablet_cleanup();
1753 return -ENOMEM;
1754 }
1755
1756 i2c_client_count = dev_info->i2c_client_count;
1757 for (i = 0; i < i2c_client_count; i++) {
1758 ret = x86_instantiate_i2c_client(dev_info, i);
1759 if (ret < 0) {
1760 x86_android_tablet_cleanup();
1761 return ret;
1762 }
1763 }
1764
1765 pdevs = kcalloc(dev_info->pdev_count, sizeof(*pdevs), GFP_KERNEL);
1766 if (!pdevs) {
1767 x86_android_tablet_cleanup();
1768 return -ENOMEM;
1769 }
1770
1771 pdev_count = dev_info->pdev_count;
1772 for (i = 0; i < pdev_count; i++) {
1773 pdevs[i] = platform_device_register_full(&dev_info->pdev_info[i]);
1774 if (IS_ERR(pdevs[i])) {
1775 x86_android_tablet_cleanup();
1776 return PTR_ERR(pdevs[i]);
1777 }
1778 }
1779
1780 serdevs = kcalloc(dev_info->serdev_count, sizeof(*serdevs), GFP_KERNEL);
1781 if (!serdevs) {
1782 x86_android_tablet_cleanup();
1783 return -ENOMEM;
1784 }
1785
1786 serdev_count = dev_info->serdev_count;
1787 for (i = 0; i < serdev_count; i++) {
1788 ret = x86_instantiate_serdev(&dev_info->serdev_info[i], i);
1789 if (ret < 0) {
1790 x86_android_tablet_cleanup();
1791 return ret;
1792 }
1793 }
1794
1795 return 0;
1796}
1797
1798module_init(x86_android_tablet_init);
1799module_exit(x86_android_tablet_cleanup);
1800
1801MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
1802MODULE_DESCRIPTION("X86 Android tablets DSDT fixups driver");
1803MODULE_LICENSE("GPL");