1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Board info for Lenovo X86 tablets which ship with Android as the factory image
4 * and which have broken DSDT tables. The factory kernels shipped on these
5 * devices typically have a bunch of things hardcoded, rather than specified
8 * Copyright (C) 2021-2023 Hans de Goede <hdegoede@redhat.com>
11 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
13 #include <linux/efi.h>
14 #include <linux/gpio/machine.h>
15 #include <linux/mfd/arizona/pdata.h>
16 #include <linux/mfd/arizona/registers.h>
17 #include <linux/mfd/intel_soc_pmic.h>
18 #include <linux/pinctrl/consumer.h>
19 #include <linux/pinctrl/machine.h>
20 #include <linux/platform_data/lp855x.h>
21 #include <linux/platform_device.h>
22 #include <linux/reboot.h>
23 #include <linux/rmi.h>
24 #include <linux/spi/spi.h>
26 #include "shared-psy-info.h"
27 #include "x86-android-tablets.h"
30 * Various Lenovo models use a TI LP8557 LED backlight controller with its PWM
31 * input connected to a PWM output coming from the LCD panel's controller.
32 * The Android kernels have a hack in the i915 driver to write a non-standard
33 * panel specific DSI register to set the duty-cycle of the LCD's PWM output.
35 * To avoid having to have a similar hack in the mainline kernel program the
36 * LP8557 to directly set the level and use the lp855x_bl driver for control.
38 * The LP8557 can either be configured to multiply its PWM input and
39 * the I2C register set level (requiring both to be at 100% for 100% output);
40 * or to only take the I2C register set level into account.
42 * Multiplying the 2 levels is useful because this will turn off the backlight
43 * when the panel goes off and turns off its PWM output.
45 * But on some models the panel's PWM output defaults to a duty-cycle of
46 * much less then 100%, severely limiting max brightness. In this case
47 * the LP8557 should be configured to only take the I2C register into
48 * account and the i915 driver must turn off the panel and the backlight
49 * separately using e.g. VBT MIPI sequences to turn off the backlight.
51 static struct lp855x_platform_data lenovo_lp8557_pwm_and_reg_pdata = {
52 .device_control = 0x86,
53 .initial_brightness = 128,
56 static struct lp855x_platform_data lenovo_lp8557_reg_only_pdata = {
57 .device_control = 0x85,
58 .initial_brightness = 128,
61 /* Lenovo Yoga Book X90F / X90L's Android factory img has everything hardcoded */
63 static const struct property_entry lenovo_yb1_x90_wacom_props[] = {
64 PROPERTY_ENTRY_U32("hid-descr-addr", 0x0001),
65 PROPERTY_ENTRY_U32("post-reset-deassert-delay-ms", 150),
69 static const struct software_node lenovo_yb1_x90_wacom_node = {
70 .properties = lenovo_yb1_x90_wacom_props,
74 * The HiDeep IST940E touchscreen comes up in I2C-HID mode. The native protocol
75 * reports ABS_MT_PRESSURE and ABS_MT_TOUCH_MAJOR which are not reported in HID
76 * mode, so using native mode is preferred.
77 * It could alternatively be used in HID mode by changing the properties to:
78 * PROPERTY_ENTRY_U32("hid-descr-addr", 0x0020),
79 * PROPERTY_ENTRY_U32("post-reset-deassert-delay-ms", 120),
80 * and changing board_info.type to "hid-over-i2c".
82 static const struct property_entry lenovo_yb1_x90_hideep_ts_props[] = {
83 PROPERTY_ENTRY_U32("touchscreen-size-x", 1200),
84 PROPERTY_ENTRY_U32("touchscreen-size-y", 1920),
85 PROPERTY_ENTRY_U32("touchscreen-max-pressure", 16384),
86 PROPERTY_ENTRY_BOOL("hideep,force-native-protocol"),
90 static const struct software_node lenovo_yb1_x90_hideep_ts_node = {
91 .properties = lenovo_yb1_x90_hideep_ts_props,
94 static const struct x86_i2c_client_info lenovo_yb1_x90_i2c_clients[] __initconst = {
96 /* BQ27542 fuel-gauge */
100 .dev_name = "bq27542",
101 .swnode = &fg_bq25890_supply_node,
103 .adapter_path = "\\_SB_.PCI0.I2C1",
105 /* Goodix Touchscreen in keyboard half */
107 .type = "GDIX1001:00",
109 .dev_name = "goodix_ts",
111 .adapter_path = "\\_SB_.PCI0.I2C2",
113 .type = X86_ACPI_IRQ_TYPE_GPIOINT,
114 .chip = "INT33FF:01",
116 .trigger = ACPI_EDGE_SENSITIVE,
117 .polarity = ACPI_ACTIVE_LOW,
118 .con_id = "goodix_ts_irq",
121 /* Wacom Digitizer in keyboard half */
123 .type = "hid-over-i2c",
126 .swnode = &lenovo_yb1_x90_wacom_node,
128 .adapter_path = "\\_SB_.PCI0.I2C4",
130 .type = X86_ACPI_IRQ_TYPE_GPIOINT,
131 .chip = "INT33FF:01",
133 .trigger = ACPI_LEVEL_SENSITIVE,
134 .polarity = ACPI_ACTIVE_LOW,
135 .con_id = "wacom_irq",
138 /* LP8557 Backlight controller */
142 .dev_name = "lp8557",
143 .platform_data = &lenovo_lp8557_pwm_and_reg_pdata,
145 .adapter_path = "\\_SB_.PCI0.I2C4",
147 /* HiDeep IST940E Touchscreen in display half */
151 .dev_name = "hideep_ts",
152 .swnode = &lenovo_yb1_x90_hideep_ts_node,
154 .adapter_path = "\\_SB_.PCI0.I2C6",
156 .type = X86_ACPI_IRQ_TYPE_GPIOINT,
157 .chip = "INT33FF:03",
159 .trigger = ACPI_LEVEL_SENSITIVE,
160 .polarity = ACPI_ACTIVE_LOW,
161 .con_id = "hideep_ts_irq",
166 static const struct platform_device_info lenovo_yb1_x90_pdevs[] __initconst = {
168 .name = "yogabook-touch-kbd-digitizer-switch",
169 .id = PLATFORM_DEVID_NONE,
174 * DSDT says UART path is "\\_SB.PCIO.URT1" with a letter 'O' instead of
175 * the number '0' add the link manually.
177 static const struct x86_serdev_info lenovo_yb1_x90_serdevs[] __initconst = {
179 .ctrl_hid = "8086228A",
181 .ctrl_devname = "serial0",
182 .serdev_hid = "BCM2E1A",
186 static const struct x86_gpio_button lenovo_yb1_x90_lid __initconst = {
193 .debounce_interval = 50,
195 .chip = "INT33FF:02",
199 static struct gpiod_lookup_table lenovo_yb1_x90_goodix_gpios = {
200 .dev_id = "i2c-goodix_ts",
202 GPIO_LOOKUP("INT33FF:01", 53, "reset", GPIO_ACTIVE_HIGH),
203 GPIO_LOOKUP("INT33FF:01", 56, "irq", GPIO_ACTIVE_HIGH),
208 static struct gpiod_lookup_table lenovo_yb1_x90_hideep_gpios = {
209 .dev_id = "i2c-hideep_ts",
211 GPIO_LOOKUP("INT33FF:00", 7, "reset", GPIO_ACTIVE_LOW),
216 static struct gpiod_lookup_table lenovo_yb1_x90_wacom_gpios = {
217 .dev_id = "i2c-wacom",
219 GPIO_LOOKUP("INT33FF:00", 82, "reset", GPIO_ACTIVE_LOW),
224 static struct gpiod_lookup_table * const lenovo_yb1_x90_gpios[] = {
225 &lenovo_yb1_x90_hideep_gpios,
226 &lenovo_yb1_x90_goodix_gpios,
227 &lenovo_yb1_x90_wacom_gpios,
231 static int __init lenovo_yb1_x90_init(void)
233 /* Enable the regulators used by the touchscreens */
235 /* Vprog3B 3.0V used by the goodix touchscreen in the keyboard half */
236 intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0x9b, 0x02, 0xff);
238 /* Vprog4D 3.0V used by the HiDeep touchscreen in the display half */
239 intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0x9f, 0x02, 0xff);
241 /* Vprog5A 1.8V used by the HiDeep touchscreen in the display half */
242 intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0xa0, 0x02, 0xff);
244 /* Vprog5B 1.8V used by the goodix touchscreen in the keyboard half */
245 intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0xa1, 0x02, 0xff);
250 const struct x86_dev_info lenovo_yogabook_x90_info __initconst = {
251 .i2c_client_info = lenovo_yb1_x90_i2c_clients,
252 .i2c_client_count = ARRAY_SIZE(lenovo_yb1_x90_i2c_clients),
253 .pdev_info = lenovo_yb1_x90_pdevs,
254 .pdev_count = ARRAY_SIZE(lenovo_yb1_x90_pdevs),
255 .serdev_info = lenovo_yb1_x90_serdevs,
256 .serdev_count = ARRAY_SIZE(lenovo_yb1_x90_serdevs),
257 .gpio_button = &lenovo_yb1_x90_lid,
258 .gpio_button_count = 1,
259 .gpiod_lookup_tables = lenovo_yb1_x90_gpios,
260 .init = lenovo_yb1_x90_init,
263 /* Lenovo Yoga Book X91F/L Windows tablet needs manual instantiation of the fg client */
264 static const struct x86_i2c_client_info lenovo_yogabook_x91_i2c_clients[] __initconst = {
266 /* BQ27542 fuel-gauge */
270 .dev_name = "bq27542",
271 .swnode = &fg_bq25890_supply_node,
273 .adapter_path = "\\_SB_.PCI0.I2C1",
277 const struct x86_dev_info lenovo_yogabook_x91_info __initconst = {
278 .i2c_client_info = lenovo_yogabook_x91_i2c_clients,
279 .i2c_client_count = ARRAY_SIZE(lenovo_yogabook_x91_i2c_clients),
282 /* Lenovo Yoga Tablet 2 1050F/L's Android factory img has everything hardcoded */
283 static const struct property_entry lenovo_yoga_tab2_830_1050_bq24190_props[] = {
284 PROPERTY_ENTRY_STRING_ARRAY_LEN("supplied-from", tusb1211_chg_det_psy, 1),
285 PROPERTY_ENTRY_REF("monitored-battery", &generic_lipo_hv_4v35_battery_node),
286 PROPERTY_ENTRY_BOOL("omit-battery-class"),
287 PROPERTY_ENTRY_BOOL("disable-reset"),
291 static const struct software_node lenovo_yoga_tab2_830_1050_bq24190_node = {
292 .properties = lenovo_yoga_tab2_830_1050_bq24190_props,
295 static const struct x86_gpio_button lenovo_yoga_tab2_830_1050_lid __initconst = {
302 .debounce_interval = 50,
304 .chip = "INT33FC:02",
308 /* This gets filled by lenovo_yoga_tab2_830_1050_init() */
309 static struct rmi_device_platform_data lenovo_yoga_tab2_830_1050_rmi_pdata = { };
311 static struct x86_i2c_client_info lenovo_yoga_tab2_830_1050_i2c_clients[] __initdata = {
314 * This must be the first entry because lenovo_yoga_tab2_830_1050_init()
315 * may update its swnode. LSM303DA accelerometer + magnetometer.
320 .dev_name = "lsm303d",
322 .adapter_path = "\\_SB_.I2C5",
324 /* AL3320A ambient light sensor */
328 .dev_name = "al3320a",
330 .adapter_path = "\\_SB_.I2C5",
332 /* bq24292i battery charger */
336 .dev_name = "bq24292i",
337 .swnode = &lenovo_yoga_tab2_830_1050_bq24190_node,
338 .platform_data = &bq24190_pdata,
340 .adapter_path = "\\_SB_.I2C1",
342 .type = X86_ACPI_IRQ_TYPE_GPIOINT,
343 .chip = "INT33FC:02",
345 .trigger = ACPI_EDGE_SENSITIVE,
346 .polarity = ACPI_ACTIVE_HIGH,
347 .con_id = "bq24292i_irq",
350 /* BQ27541 fuel-gauge */
354 .dev_name = "bq27541",
355 .swnode = &fg_bq24190_supply_node,
357 .adapter_path = "\\_SB_.I2C1",
359 /* Synaptics RMI touchscreen */
363 .dev_name = "rmi4_i2c",
364 .platform_data = &lenovo_yoga_tab2_830_1050_rmi_pdata,
366 .adapter_path = "\\_SB_.I2C6",
368 .type = X86_ACPI_IRQ_TYPE_APIC,
370 .trigger = ACPI_EDGE_SENSITIVE,
371 .polarity = ACPI_ACTIVE_HIGH,
374 /* LP8557 Backlight controller */
378 .dev_name = "lp8557",
379 .platform_data = &lenovo_lp8557_pwm_and_reg_pdata,
381 .adapter_path = "\\_SB_.I2C3",
385 static struct gpiod_lookup_table lenovo_yoga_tab2_830_1050_int3496_gpios = {
386 .dev_id = "intel-int3496",
388 GPIO_LOOKUP("INT33FC:02", 1, "mux", GPIO_ACTIVE_LOW),
389 GPIO_LOOKUP("INT33FC:02", 24, "id", GPIO_ACTIVE_HIGH),
394 #define LENOVO_YOGA_TAB2_830_1050_CODEC_NAME "spi-10WM5102:00"
396 static struct gpiod_lookup_table lenovo_yoga_tab2_830_1050_codec_gpios = {
397 .dev_id = LENOVO_YOGA_TAB2_830_1050_CODEC_NAME,
399 GPIO_LOOKUP("gpio_crystalcove", 3, "reset", GPIO_ACTIVE_HIGH),
400 GPIO_LOOKUP("INT33FC:01", 23, "wlf,ldoena", GPIO_ACTIVE_HIGH),
401 GPIO_LOOKUP("arizona", 2, "wlf,spkvdd-ena", GPIO_ACTIVE_HIGH),
402 GPIO_LOOKUP("arizona", 4, "wlf,micd-pol", GPIO_ACTIVE_LOW),
407 static struct gpiod_lookup_table * const lenovo_yoga_tab2_830_1050_gpios[] = {
408 &lenovo_yoga_tab2_830_1050_int3496_gpios,
409 &lenovo_yoga_tab2_830_1050_codec_gpios,
413 static int __init lenovo_yoga_tab2_830_1050_init(void);
414 static void lenovo_yoga_tab2_830_1050_exit(void);
416 const struct x86_dev_info lenovo_yoga_tab2_830_1050_info __initconst = {
417 .i2c_client_info = lenovo_yoga_tab2_830_1050_i2c_clients,
418 .i2c_client_count = ARRAY_SIZE(lenovo_yoga_tab2_830_1050_i2c_clients),
419 .pdev_info = int3496_pdevs,
421 .gpio_button = &lenovo_yoga_tab2_830_1050_lid,
422 .gpio_button_count = 1,
423 .gpiod_lookup_tables = lenovo_yoga_tab2_830_1050_gpios,
424 .bat_swnode = &generic_lipo_hv_4v35_battery_node,
425 .modules = bq24190_modules,
426 .init = lenovo_yoga_tab2_830_1050_init,
427 .exit = lenovo_yoga_tab2_830_1050_exit,
431 * The Lenovo Yoga Tablet 2 830 and 1050 (8" vs 10") versions use the same
432 * mainboard, but the 830 uses a portrait LCD panel with a landscape touchscreen,
433 * requiring the touchscreen driver to adjust the touch-coords to match the LCD.
434 * And requiring the accelerometer to have a mount-matrix set to correct for
435 * the 90° rotation of the LCD vs the frame.
437 static const char * const lenovo_yoga_tab2_830_lms303d_mount_matrix[] = {
443 static const struct property_entry lenovo_yoga_tab2_830_lms303d_props[] = {
444 PROPERTY_ENTRY_STRING_ARRAY("mount-matrix", lenovo_yoga_tab2_830_lms303d_mount_matrix),
448 static const struct software_node lenovo_yoga_tab2_830_lms303d_node = {
449 .properties = lenovo_yoga_tab2_830_lms303d_props,
452 static int __init lenovo_yoga_tab2_830_1050_init_touchscreen(void)
454 struct gpio_desc *gpiod;
457 /* Use PMIC GPIO 10 bootstrap pin to differentiate 830 vs 1050 */
458 ret = x86_android_tablet_get_gpiod("gpio_crystalcove", 10, "yoga_bootstrap",
459 false, GPIOD_ASIS, &gpiod);
463 ret = gpiod_get_value_cansleep(gpiod);
465 pr_info("detected Lenovo Yoga Tablet 2 1050F/L\n");
467 pr_info("detected Lenovo Yoga Tablet 2 830F/L\n");
468 lenovo_yoga_tab2_830_1050_rmi_pdata.sensor_pdata.axis_align.swap_axes = true;
469 lenovo_yoga_tab2_830_1050_rmi_pdata.sensor_pdata.axis_align.flip_y = true;
470 lenovo_yoga_tab2_830_1050_i2c_clients[0].board_info.swnode =
471 &lenovo_yoga_tab2_830_lms303d_node;
477 /* SUS (INT33FC:02) pin 6 needs to be configured as pmu_clk for the audio codec */
478 static const struct pinctrl_map lenovo_yoga_tab2_830_1050_codec_pinctrl_map =
479 PIN_MAP_MUX_GROUP(LENOVO_YOGA_TAB2_830_1050_CODEC_NAME, "codec_32khz_clk",
480 "INT33FC:02", "pmu_clk2_grp", "pmu_clk");
482 static struct pinctrl *lenovo_yoga_tab2_830_1050_codec_pinctrl;
483 static struct sys_off_handler *lenovo_yoga_tab2_830_1050_sys_off_handler;
485 static int __init lenovo_yoga_tab2_830_1050_init_codec(void)
487 struct device *codec_dev;
488 struct pinctrl *pinctrl;
491 codec_dev = bus_find_device_by_name(&spi_bus_type, NULL,
492 LENOVO_YOGA_TAB2_830_1050_CODEC_NAME);
494 pr_err("error cannot find %s device\n", LENOVO_YOGA_TAB2_830_1050_CODEC_NAME);
498 ret = pinctrl_register_mappings(&lenovo_yoga_tab2_830_1050_codec_pinctrl_map, 1);
502 pinctrl = pinctrl_get_select(codec_dev, "codec_32khz_clk");
503 if (IS_ERR(pinctrl)) {
504 ret = dev_err_probe(codec_dev, PTR_ERR(pinctrl), "selecting codec_32khz_clk\n");
505 goto err_unregister_mappings;
508 /* We're done with the codec_dev now */
509 put_device(codec_dev);
511 lenovo_yoga_tab2_830_1050_codec_pinctrl = pinctrl;
514 err_unregister_mappings:
515 pinctrl_unregister_mappings(&lenovo_yoga_tab2_830_1050_codec_pinctrl_map);
517 put_device(codec_dev);
522 * These tablet's DSDT does not set acpi_gbl_reduced_hardware, so acpi_power_off
523 * gets used as pm_power_off handler. This causes "poweroff" on these tablets
524 * to hang hard. Requiring pressing the powerbutton for 30 seconds *twice*
525 * followed by a normal 3 second press to recover. Avoid this by doing an EFI
528 static int lenovo_yoga_tab2_830_1050_power_off(struct sys_off_data *data)
530 efi.reset_system(EFI_RESET_SHUTDOWN, EFI_SUCCESS, 0, NULL);
535 static int __init lenovo_yoga_tab2_830_1050_init(void)
539 ret = lenovo_yoga_tab2_830_1050_init_touchscreen();
543 ret = lenovo_yoga_tab2_830_1050_init_codec();
547 /* SYS_OFF_PRIO_FIRMWARE + 1 so that it runs before acpi_power_off */
548 lenovo_yoga_tab2_830_1050_sys_off_handler =
549 register_sys_off_handler(SYS_OFF_MODE_POWER_OFF, SYS_OFF_PRIO_FIRMWARE + 1,
550 lenovo_yoga_tab2_830_1050_power_off, NULL);
551 if (IS_ERR(lenovo_yoga_tab2_830_1050_sys_off_handler))
552 return PTR_ERR(lenovo_yoga_tab2_830_1050_sys_off_handler);
557 static void lenovo_yoga_tab2_830_1050_exit(void)
559 unregister_sys_off_handler(lenovo_yoga_tab2_830_1050_sys_off_handler);
561 if (lenovo_yoga_tab2_830_1050_codec_pinctrl) {
562 pinctrl_put(lenovo_yoga_tab2_830_1050_codec_pinctrl);
563 pinctrl_unregister_mappings(&lenovo_yoga_tab2_830_1050_codec_pinctrl_map);
567 /* Lenovo Yoga Tab 3 Pro YT3-X90F */
570 * There are 2 batteries, with 2 bq27500 fuel-gauges and 2 bq25892 chargers,
571 * "bq25890-charger-1" is instantiated from: drivers/i2c/busses/i2c-cht-wc.c.
573 static const char * const lenovo_yt3_bq25892_0_suppliers[] = { "cht_wcove_pwrsrc" };
574 static const char * const bq25890_1_psy[] = { "bq25890-charger-1" };
576 static const struct property_entry fg_bq25890_1_supply_props[] = {
577 PROPERTY_ENTRY_STRING_ARRAY("supplied-from", bq25890_1_psy),
581 static const struct software_node fg_bq25890_1_supply_node = {
582 .properties = fg_bq25890_1_supply_props,
585 /* bq25892 charger settings for the flat lipo battery behind the screen */
586 static const struct property_entry lenovo_yt3_bq25892_0_props[] = {
587 PROPERTY_ENTRY_STRING_ARRAY("supplied-from", lenovo_yt3_bq25892_0_suppliers),
588 PROPERTY_ENTRY_U32("linux,iinlim-percentage", 40),
589 PROPERTY_ENTRY_BOOL("linux,skip-reset"),
590 /* Values taken from Android Factory Image */
591 PROPERTY_ENTRY_U32("ti,charge-current", 2048000),
592 PROPERTY_ENTRY_U32("ti,battery-regulation-voltage", 4352000),
593 PROPERTY_ENTRY_U32("ti,termination-current", 128000),
594 PROPERTY_ENTRY_U32("ti,precharge-current", 128000),
595 PROPERTY_ENTRY_U32("ti,minimum-sys-voltage", 3700000),
596 PROPERTY_ENTRY_U32("ti,boost-voltage", 4998000),
597 PROPERTY_ENTRY_U32("ti,boost-max-current", 500000),
598 PROPERTY_ENTRY_BOOL("ti,use-ilim-pin"),
602 static const struct software_node lenovo_yt3_bq25892_0_node = {
603 .properties = lenovo_yt3_bq25892_0_props,
606 static const struct property_entry lenovo_yt3_hideep_ts_props[] = {
607 PROPERTY_ENTRY_U32("touchscreen-size-x", 1600),
608 PROPERTY_ENTRY_U32("touchscreen-size-y", 2560),
609 PROPERTY_ENTRY_U32("touchscreen-max-pressure", 255),
613 static const struct software_node lenovo_yt3_hideep_ts_node = {
614 .properties = lenovo_yt3_hideep_ts_props,
617 static const struct x86_i2c_client_info lenovo_yt3_i2c_clients[] __initconst = {
619 /* bq27500 fuel-gauge for the flat lipo battery behind the screen */
623 .dev_name = "bq27500_0",
624 .swnode = &fg_bq25890_supply_node,
626 .adapter_path = "\\_SB_.PCI0.I2C1",
628 /* bq25892 charger for the flat lipo battery behind the screen */
632 .dev_name = "bq25892_0",
633 .swnode = &lenovo_yt3_bq25892_0_node,
635 .adapter_path = "\\_SB_.PCI0.I2C1",
637 .type = X86_ACPI_IRQ_TYPE_GPIOINT,
638 .chip = "INT33FF:01",
640 .trigger = ACPI_EDGE_SENSITIVE,
641 .polarity = ACPI_ACTIVE_LOW,
642 .con_id = "bq25892_0_irq",
645 /* bq27500 fuel-gauge for the round li-ion cells in the hinge */
649 .dev_name = "bq27500_1",
650 .swnode = &fg_bq25890_1_supply_node,
652 .adapter_path = "\\_SB_.PCI0.I2C2",
654 /* HiDeep IST520E Touchscreen */
658 .dev_name = "hideep_ts",
659 .swnode = &lenovo_yt3_hideep_ts_node,
661 .adapter_path = "\\_SB_.PCI0.I2C6",
663 .type = X86_ACPI_IRQ_TYPE_GPIOINT,
664 .chip = "INT33FF:03",
666 .trigger = ACPI_LEVEL_SENSITIVE,
667 .polarity = ACPI_ACTIVE_LOW,
668 .con_id = "hideep_ts_irq",
671 /* LP8557 Backlight controller */
675 .dev_name = "lp8557",
676 .platform_data = &lenovo_lp8557_reg_only_pdata,
678 .adapter_path = "\\_SB_.PCI0.I2C1",
683 * The AOSP 3.5 mm Headset: Accessory Specification gives the following values:
684 * Function A Play/Pause: 0 ohm
685 * Function D Voice assistant: 135 ohm
686 * Function B Volume Up 240 ohm
687 * Function C Volume Down 470 ohm
688 * Minimum Mic DC resistance 1000 ohm
689 * Minimum Ear speaker impedance 16 ohm
690 * Note the first max value below must be less then the min. speaker impedance,
691 * to allow CTIA/OMTP detection to work. The other max values are the closest
692 * value from extcon-arizona.c:arizona_micd_levels halfway 2 button resistances.
694 static const struct arizona_micd_range arizona_micd_aosp_ranges[] = {
695 { .max = 11, .key = KEY_PLAYPAUSE },
696 { .max = 186, .key = KEY_VOICECOMMAND },
697 { .max = 348, .key = KEY_VOLUMEUP },
698 { .max = 752, .key = KEY_VOLUMEDOWN },
701 /* YT3 WM5102 arizona_micd_config comes from Android kernel sources */
702 static struct arizona_micd_config lenovo_yt3_wm5102_micd_config[] = {
704 { ARIZONA_ACCDET_SRC, 2, 1 },
707 static struct arizona_pdata lenovo_yt3_wm5102_pdata = {
708 .irq_flags = IRQF_TRIGGER_LOW,
709 .micd_detect_debounce = 200,
710 .micd_ranges = arizona_micd_aosp_ranges,
711 .num_micd_ranges = ARRAY_SIZE(arizona_micd_aosp_ranges),
712 .hpdet_channel = ARIZONA_ACCDET_MODE_HPL,
714 /* Below settings come from Android kernel sources */
715 .micd_bias_start_time = 1,
717 .micd_configs = lenovo_yt3_wm5102_micd_config,
718 .num_micd_configs = ARRAY_SIZE(lenovo_yt3_wm5102_micd_config),
720 [0] = { /* MICBIAS1 */
727 [1] = { /* MICBIAS2 */
734 [2] = { /* MICBIAS2 */
744 static const struct x86_spi_dev_info lenovo_yt3_spi_devs[] __initconst = {
748 .modalias = "wm5102",
749 .platform_data = &lenovo_yt3_wm5102_pdata,
750 .max_speed_hz = 5000000,
752 .ctrl_path = "\\_SB_.PCI0.SPI1",
754 .type = X86_ACPI_IRQ_TYPE_GPIOINT,
755 .chip = "INT33FF:00",
757 .trigger = ACPI_LEVEL_SENSITIVE,
758 .polarity = ACPI_ACTIVE_LOW,
759 .con_id = "wm5102_irq",
764 static int __init lenovo_yt3_init(void)
769 * The "bq25892_0" charger IC has its /CE (Charge-Enable) and OTG pins
770 * connected to GPIOs, rather then having them hardwired to the correct
771 * values as is normally done.
773 * The bq25890_charger driver controls these through I2C, but this only
774 * works if not overridden by the pins. Set these pins here:
775 * 1. Set /CE to 1 to allow charging.
776 * 2. Set OTG to 0 disable V5 boost output since the 5V boost output of
777 * the main "bq25892_1" charger is used when necessary.
781 ret = x86_android_tablet_get_gpiod("INT33FF:02", 22, "bq25892_0_ce",
782 true, GPIOD_OUT_HIGH, NULL);
787 ret = x86_android_tablet_get_gpiod("INT33FF:03", 19, "bq25892_0_otg",
788 false, GPIOD_OUT_LOW, NULL);
792 /* Enable the regulators used by the touchscreen */
793 intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0x9b, 0x02, 0xff);
794 intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0xa0, 0x02, 0xff);
799 static struct gpiod_lookup_table lenovo_yt3_hideep_gpios = {
800 .dev_id = "i2c-hideep_ts",
802 GPIO_LOOKUP("INT33FF:00", 7, "reset", GPIO_ACTIVE_LOW),
807 static struct gpiod_lookup_table lenovo_yt3_wm5102_gpios = {
810 GPIO_LOOKUP("INT33FF:00", 75, "wlf,spkvdd-ena", GPIO_ACTIVE_HIGH),
811 GPIO_LOOKUP("INT33FF:00", 81, "wlf,ldoena", GPIO_ACTIVE_HIGH),
812 GPIO_LOOKUP("INT33FF:00", 82, "reset", GPIO_ACTIVE_HIGH),
813 GPIO_LOOKUP("arizona", 2, "wlf,micd-pol", GPIO_ACTIVE_HIGH),
818 static struct gpiod_lookup_table * const lenovo_yt3_gpios[] = {
819 &lenovo_yt3_hideep_gpios,
820 &lenovo_yt3_wm5102_gpios,
824 const struct x86_dev_info lenovo_yt3_info __initconst = {
825 .i2c_client_info = lenovo_yt3_i2c_clients,
826 .i2c_client_count = ARRAY_SIZE(lenovo_yt3_i2c_clients),
827 .spi_dev_info = lenovo_yt3_spi_devs,
828 .spi_dev_count = ARRAY_SIZE(lenovo_yt3_spi_devs),
829 .gpiod_lookup_tables = lenovo_yt3_gpios,
830 .init = lenovo_yt3_init,