Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v6.3 1803 lines 52 kB view raw
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-0" }; 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");