xref: /openbmc/linux/drivers/platform/x86/x86-android-tablets/lenovo.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
17bf974f6SHans de Goede // SPDX-License-Identifier: GPL-2.0-or-later
27bf974f6SHans de Goede /*
37bf974f6SHans de Goede  * Board info for Lenovo X86 tablets which ship with Android as the factory image
47bf974f6SHans de Goede  * and which have broken DSDT tables. The factory kernels shipped on these
57bf974f6SHans de Goede  * devices typically have a bunch of things hardcoded, rather than specified
67bf974f6SHans de Goede  * in their DSDT.
77bf974f6SHans de Goede  *
87bf974f6SHans de Goede  * Copyright (C) 2021-2023 Hans de Goede <hdegoede@redhat.com>
97bf974f6SHans de Goede  */
107bf974f6SHans de Goede 
117bf974f6SHans de Goede #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
127bf974f6SHans de Goede 
137bf974f6SHans de Goede #include <linux/efi.h>
147bf974f6SHans de Goede #include <linux/gpio/machine.h>
159b1d2662SHans de Goede #include <linux/mfd/intel_soc_pmic.h>
167bf974f6SHans de Goede #include <linux/pinctrl/consumer.h>
177bf974f6SHans de Goede #include <linux/pinctrl/machine.h>
187bf974f6SHans de Goede #include <linux/platform_data/lp855x.h>
197bf974f6SHans de Goede #include <linux/platform_device.h>
207bf974f6SHans de Goede #include <linux/reboot.h>
217bf974f6SHans de Goede #include <linux/rmi.h>
227bf974f6SHans de Goede #include <linux/spi/spi.h>
237bf974f6SHans de Goede 
247bf974f6SHans de Goede #include "shared-psy-info.h"
257bf974f6SHans de Goede #include "x86-android-tablets.h"
267bf974f6SHans de Goede 
27ec5a4565SHans de Goede /*
28ec5a4565SHans de Goede  * Various Lenovo models use a TI LP8557 LED backlight controller with its PWM
29ec5a4565SHans de Goede  * input connected to a PWM output coming from the LCD panel's controller.
30ec5a4565SHans de Goede  * The Android kernels have a hack in the i915 driver to write a non-standard
31ec5a4565SHans de Goede  * panel specific DSI register to set the duty-cycle of the LCD's PWM output.
32ec5a4565SHans de Goede  *
33ec5a4565SHans de Goede  * To avoid having to have a similar hack in the mainline kernel program the
34ec5a4565SHans de Goede  * LP8557 to directly set the level and use the lp855x_bl driver for control.
35ec5a4565SHans de Goede  */
36ec5a4565SHans de Goede static struct lp855x_platform_data lenovo_lp8557_pdata = {
37ec5a4565SHans de Goede 	.device_control = 0x86,
38ec5a4565SHans de Goede 	.initial_brightness = 128,
39ec5a4565SHans de Goede };
40ec5a4565SHans de Goede 
41c69fec50SHans de Goede /* Lenovo Yoga Book X90F / X90L's Android factory img has everything hardcoded */
42c69fec50SHans de Goede 
4395b829f8SHans de Goede static const struct property_entry lenovo_yb1_x90_wacom_props[] = {
4495b829f8SHans de Goede 	PROPERTY_ENTRY_U32("hid-descr-addr", 0x0001),
4595b829f8SHans de Goede 	PROPERTY_ENTRY_U32("post-reset-deassert-delay-ms", 150),
4695b829f8SHans de Goede 	{ }
4795b829f8SHans de Goede };
4895b829f8SHans de Goede 
4995b829f8SHans de Goede static const struct software_node lenovo_yb1_x90_wacom_node = {
5095b829f8SHans de Goede 	.properties = lenovo_yb1_x90_wacom_props,
5195b829f8SHans de Goede };
5295b829f8SHans de Goede 
53c69fec50SHans de Goede /*
5402377e98SHans de Goede  * The HiDeep IST940E touchscreen comes up in I2C-HID mode. The native protocol
5502377e98SHans de Goede  * reports ABS_MT_PRESSURE and ABS_MT_TOUCH_MAJOR which are not reported in HID
5602377e98SHans de Goede  * mode, so using native mode is preferred.
5702377e98SHans de Goede  * It could alternatively be used in HID mode by changing the properties to:
5802377e98SHans de Goede  *	PROPERTY_ENTRY_U32("hid-descr-addr", 0x0020),
5902377e98SHans de Goede  *	PROPERTY_ENTRY_U32("post-reset-deassert-delay-ms", 120),
6002377e98SHans de Goede  * and changing board_info.type to "hid-over-i2c".
61c69fec50SHans de Goede  */
62c69fec50SHans de Goede static const struct property_entry lenovo_yb1_x90_hideep_ts_props[] = {
63c69fec50SHans de Goede 	PROPERTY_ENTRY_U32("touchscreen-size-x", 1200),
64c69fec50SHans de Goede 	PROPERTY_ENTRY_U32("touchscreen-size-y", 1920),
65c69fec50SHans de Goede 	PROPERTY_ENTRY_U32("touchscreen-max-pressure", 16384),
66c69fec50SHans de Goede 	PROPERTY_ENTRY_BOOL("hideep,force-native-protocol"),
67c69fec50SHans de Goede 	{ }
68c69fec50SHans de Goede };
69c69fec50SHans de Goede 
70c69fec50SHans de Goede static const struct software_node lenovo_yb1_x90_hideep_ts_node = {
71c69fec50SHans de Goede 	.properties = lenovo_yb1_x90_hideep_ts_props,
72c69fec50SHans de Goede };
73c69fec50SHans de Goede 
74c69fec50SHans de Goede static const struct x86_i2c_client_info lenovo_yb1_x90_i2c_clients[] __initconst = {
75c69fec50SHans de Goede 	{
76c69fec50SHans de Goede 		/* BQ27542 fuel-gauge */
77c69fec50SHans de Goede 		.board_info = {
78c69fec50SHans de Goede 			.type = "bq27542",
79c69fec50SHans de Goede 			.addr = 0x55,
80c69fec50SHans de Goede 			.dev_name = "bq27542",
81c69fec50SHans de Goede 			.swnode = &fg_bq25890_supply_node,
82c69fec50SHans de Goede 		},
83c69fec50SHans de Goede 		.adapter_path = "\\_SB_.PCI0.I2C1",
84c69fec50SHans de Goede 	}, {
85c69fec50SHans de Goede 		/* Goodix Touchscreen in keyboard half */
86c69fec50SHans de Goede 		.board_info = {
87c69fec50SHans de Goede 			.type = "GDIX1001:00",
88c69fec50SHans de Goede 			.addr = 0x14,
89c69fec50SHans de Goede 			.dev_name = "goodix_ts",
90c69fec50SHans de Goede 		},
91c69fec50SHans de Goede 		.adapter_path = "\\_SB_.PCI0.I2C2",
92c69fec50SHans de Goede 		.irq_data = {
93c69fec50SHans de Goede 			.type = X86_ACPI_IRQ_TYPE_GPIOINT,
94c69fec50SHans de Goede 			.chip = "INT33FF:01",
95c69fec50SHans de Goede 			.index = 56,
96c69fec50SHans de Goede 			.trigger = ACPI_EDGE_SENSITIVE,
97c69fec50SHans de Goede 			.polarity = ACPI_ACTIVE_LOW,
98c69fec50SHans de Goede 		},
99c69fec50SHans de Goede 	}, {
10095b829f8SHans de Goede 		/* Wacom Digitizer in keyboard half */
10195b829f8SHans de Goede 		.board_info = {
10295b829f8SHans de Goede 			.type = "hid-over-i2c",
10395b829f8SHans de Goede 			.addr = 0x09,
10495b829f8SHans de Goede 			.dev_name = "wacom",
10595b829f8SHans de Goede 			.swnode = &lenovo_yb1_x90_wacom_node,
10695b829f8SHans de Goede 		},
10795b829f8SHans de Goede 		.adapter_path = "\\_SB_.PCI0.I2C4",
10895b829f8SHans de Goede 		.irq_data = {
10995b829f8SHans de Goede 			.type = X86_ACPI_IRQ_TYPE_GPIOINT,
11095b829f8SHans de Goede 			.chip = "INT33FF:01",
11195b829f8SHans de Goede 			.index = 49,
11295b829f8SHans de Goede 			.trigger = ACPI_LEVEL_SENSITIVE,
11395b829f8SHans de Goede 			.polarity = ACPI_ACTIVE_LOW,
11495b829f8SHans de Goede 		},
11595b829f8SHans de Goede 	}, {
116c69fec50SHans de Goede 		/* LP8557 Backlight controller */
117c69fec50SHans de Goede 		.board_info = {
118c69fec50SHans de Goede 			.type = "lp8557",
119c69fec50SHans de Goede 			.addr = 0x2c,
120c69fec50SHans de Goede 			.dev_name = "lp8557",
121c69fec50SHans de Goede 			.platform_data = &lenovo_lp8557_pdata,
122c69fec50SHans de Goede 		},
123c69fec50SHans de Goede 		.adapter_path = "\\_SB_.PCI0.I2C4",
124c69fec50SHans de Goede 	}, {
125c69fec50SHans de Goede 		/* HiDeep IST940E Touchscreen in display half */
126c69fec50SHans de Goede 		.board_info = {
127c69fec50SHans de Goede 			.type = "hideep_ts",
128c69fec50SHans de Goede 			.addr = 0x6c,
129c69fec50SHans de Goede 			.dev_name = "hideep_ts",
130c69fec50SHans de Goede 			.swnode = &lenovo_yb1_x90_hideep_ts_node,
131c69fec50SHans de Goede 		},
132c69fec50SHans de Goede 		.adapter_path = "\\_SB_.PCI0.I2C6",
133c69fec50SHans de Goede 		.irq_data = {
134c69fec50SHans de Goede 			.type = X86_ACPI_IRQ_TYPE_GPIOINT,
135c69fec50SHans de Goede 			.chip = "INT33FF:03",
136c69fec50SHans de Goede 			.index = 77,
137c69fec50SHans de Goede 			.trigger = ACPI_LEVEL_SENSITIVE,
138c69fec50SHans de Goede 			.polarity = ACPI_ACTIVE_LOW,
139c69fec50SHans de Goede 		},
140c69fec50SHans de Goede 	},
141c69fec50SHans de Goede };
142c69fec50SHans de Goede 
1431d3f7a31SHans de Goede static const struct platform_device_info lenovo_yb1_x90_pdevs[] __initconst = {
1441d3f7a31SHans de Goede 	{
1451d3f7a31SHans de Goede 		.name = "yogabook-touch-kbd-digitizer-switch",
1461d3f7a31SHans de Goede 		.id = PLATFORM_DEVID_NONE,
1471d3f7a31SHans de Goede 	},
1481d3f7a31SHans de Goede };
1491d3f7a31SHans de Goede 
150c69fec50SHans de Goede /*
151c69fec50SHans de Goede  * DSDT says UART path is "\\_SB.PCIO.URT1" with a letter 'O' instead of
152c69fec50SHans de Goede  * the number '0' add the link manually.
153c69fec50SHans de Goede  */
154c69fec50SHans de Goede static const struct x86_serdev_info lenovo_yb1_x90_serdevs[] __initconst = {
155c69fec50SHans de Goede 	{
156c69fec50SHans de Goede 		.ctrl_hid = "8086228A",
157c69fec50SHans de Goede 		.ctrl_uid = "1",
158c69fec50SHans de Goede 		.ctrl_devname = "serial0",
159c69fec50SHans de Goede 		.serdev_hid = "BCM2E1A",
160c69fec50SHans de Goede 	},
161c69fec50SHans de Goede };
162c69fec50SHans de Goede 
163c69fec50SHans de Goede static const struct x86_gpio_button lenovo_yb1_x90_lid __initconst = {
164c69fec50SHans de Goede 	.button = {
165c69fec50SHans de Goede 		.code = SW_LID,
166c69fec50SHans de Goede 		.active_low = true,
16795b829f8SHans de Goede 		.desc = "lid_sw",
16895b829f8SHans de Goede 		.type = EV_SW,
16995b829f8SHans de Goede 		.wakeup = true,
17095b829f8SHans de Goede 		.debounce_interval = 50,
17195b829f8SHans de Goede 	},
17295b829f8SHans de Goede 	.chip = "INT33FF:02",
17395b829f8SHans de Goede 	.pin = 19,
17495b829f8SHans de Goede };
175c69fec50SHans de Goede 
176c69fec50SHans de Goede static struct gpiod_lookup_table lenovo_yb1_x90_goodix_gpios = {
177c69fec50SHans de Goede 	.dev_id = "i2c-goodix_ts",
17895b829f8SHans de Goede 	.table = {
179c69fec50SHans de Goede 		GPIO_LOOKUP("INT33FF:01", 53, "reset", GPIO_ACTIVE_HIGH),
180c69fec50SHans de Goede 		GPIO_LOOKUP("INT33FF:01", 56, "irq", GPIO_ACTIVE_HIGH),
181c69fec50SHans de Goede 		{ }
182c69fec50SHans de Goede 	},
183c69fec50SHans de Goede };
184c69fec50SHans de Goede 
185c69fec50SHans de Goede static struct gpiod_lookup_table lenovo_yb1_x90_hideep_gpios = {
186c69fec50SHans de Goede 	.dev_id = "i2c-hideep_ts",
187c69fec50SHans de Goede 	.table = {
188c69fec50SHans de Goede 		GPIO_LOOKUP("INT33FF:00", 7, "reset", GPIO_ACTIVE_LOW),
189c69fec50SHans de Goede 		{ }
190c69fec50SHans de Goede 	},
191c69fec50SHans de Goede };
192c69fec50SHans de Goede 
193c69fec50SHans de Goede static struct gpiod_lookup_table lenovo_yb1_x90_wacom_gpios = {
194c69fec50SHans de Goede 	.dev_id = "i2c-wacom",
195c69fec50SHans de Goede 	.table = {
196c69fec50SHans de Goede 		GPIO_LOOKUP("INT33FF:00", 82, "reset", GPIO_ACTIVE_LOW),
197c69fec50SHans de Goede 		{ }
198c69fec50SHans de Goede 	},
199c69fec50SHans de Goede };
200c69fec50SHans de Goede 
201c69fec50SHans de Goede static struct gpiod_lookup_table * const lenovo_yb1_x90_gpios[] = {
202c69fec50SHans de Goede 	&lenovo_yb1_x90_hideep_gpios,
203c69fec50SHans de Goede 	&lenovo_yb1_x90_goodix_gpios,
2041d3f7a31SHans de Goede 	&lenovo_yb1_x90_wacom_gpios,
2051d3f7a31SHans de Goede 	NULL
206c69fec50SHans de Goede };
207c69fec50SHans de Goede 
lenovo_yb1_x90_init(void)208c69fec50SHans de Goede static int __init lenovo_yb1_x90_init(void)
209c69fec50SHans de Goede {
2105f250f8aSHans de Goede 	/* Enable the regulators used by the touchscreens */
2115f250f8aSHans de Goede 
2127bf974f6SHans de Goede 	/* Vprog3B 3.0V used by the goodix touchscreen in the keyboard half */
2137bf974f6SHans de Goede 	intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0x9b, 0x02, 0xff);
2147bf974f6SHans de Goede 
2157bf974f6SHans de Goede 	/* Vprog4D 3.0V used by the HiDeep touchscreen in the display half */
2167bf974f6SHans de Goede 	intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0x9f, 0x02, 0xff);
2177bf974f6SHans de Goede 
2187bf974f6SHans de Goede 	/* Vprog5A 1.8V used by the HiDeep touchscreen in the display half */
2197bf974f6SHans de Goede 	intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0xa0, 0x02, 0xff);
2207bf974f6SHans de Goede 
2217bf974f6SHans de Goede 	/* Vprog5B 1.8V used by the goodix touchscreen in the keyboard half */
2227bf974f6SHans de Goede 	intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0xa1, 0x02, 0xff);
2237bf974f6SHans de Goede 
2245f250f8aSHans de Goede 	return 0;
2255f250f8aSHans de Goede }
2265f250f8aSHans de Goede 
2277bf974f6SHans de Goede const struct x86_dev_info lenovo_yogabook_x90_info __initconst = {
2287bf974f6SHans de Goede 	.i2c_client_info = lenovo_yb1_x90_i2c_clients,
2297bf974f6SHans de Goede 	.i2c_client_count = ARRAY_SIZE(lenovo_yb1_x90_i2c_clients),
2307bf974f6SHans de Goede 	.pdev_info = lenovo_yb1_x90_pdevs,
2317bf974f6SHans de Goede 	.pdev_count = ARRAY_SIZE(lenovo_yb1_x90_pdevs),
2327bf974f6SHans de Goede 	.serdev_info = lenovo_yb1_x90_serdevs,
2337bf974f6SHans de Goede 	.serdev_count = ARRAY_SIZE(lenovo_yb1_x90_serdevs),
2347bf974f6SHans de Goede 	.gpio_button = &lenovo_yb1_x90_lid,
2357bf974f6SHans de Goede 	.gpio_button_count = 1,
2367bf974f6SHans de Goede 	.gpiod_lookup_tables = lenovo_yb1_x90_gpios,
2377bf974f6SHans de Goede 	.init = lenovo_yb1_x90_init,
2387bf974f6SHans de Goede };
2397bf974f6SHans de Goede 
2407bf974f6SHans de Goede /* Lenovo Yoga Book X91F/L Windows tablet needs manual instantiation of the fg client */
2417bf974f6SHans de Goede static const struct x86_i2c_client_info lenovo_yogabook_x91_i2c_clients[] __initconst = {
242dadbc368SHans de Goede 	{
243dadbc368SHans de Goede 		/* BQ27542 fuel-gauge */
244dadbc368SHans de Goede 		.board_info = {
245dadbc368SHans de Goede 			.type = "bq27542",
246dadbc368SHans de Goede 			.addr = 0x55,
247dadbc368SHans de Goede 			.dev_name = "bq27542",
248dadbc368SHans de Goede 			.swnode = &fg_bq25890_supply_node,
249dadbc368SHans de Goede 		},
250dadbc368SHans de Goede 		.adapter_path = "\\_SB_.PCI0.I2C1",
251dadbc368SHans de Goede 	},
252dadbc368SHans de Goede };
253dadbc368SHans de Goede 
254dadbc368SHans de Goede const struct x86_dev_info lenovo_yogabook_x91_info __initconst = {
2557bf974f6SHans de Goede 	.i2c_client_info = lenovo_yogabook_x91_i2c_clients,
2567bf974f6SHans de Goede 	.i2c_client_count = ARRAY_SIZE(lenovo_yogabook_x91_i2c_clients),
2577bf974f6SHans de Goede };
258*e578c943SHans de Goede 
2597bf974f6SHans de Goede /* Lenovo Yoga Tablet 2 1050F/L's Android factory img has everything hardcoded */
260*e578c943SHans de Goede static const struct property_entry lenovo_yoga_tab2_830_1050_bq24190_props[] = {
261*e578c943SHans de Goede 	PROPERTY_ENTRY_STRING_ARRAY_LEN("supplied-from", tusb1211_chg_det_psy, 1),
262*e578c943SHans de Goede 	PROPERTY_ENTRY_REF("monitored-battery", &generic_lipo_hv_4v35_battery_node),
263*e578c943SHans de Goede 	PROPERTY_ENTRY_BOOL("omit-battery-class"),
264*e578c943SHans de Goede 	PROPERTY_ENTRY_BOOL("disable-reset"),
265*e578c943SHans de Goede 	{ }
266*e578c943SHans de Goede };
267*e578c943SHans de Goede 
268*e578c943SHans de Goede static const struct software_node lenovo_yoga_tab2_830_1050_bq24190_node = {
269*e578c943SHans de Goede 	.properties = lenovo_yoga_tab2_830_1050_bq24190_props,
270*e578c943SHans de Goede };
2717bf974f6SHans de Goede 
2727bf974f6SHans de Goede static const struct x86_gpio_button lenovo_yoga_tab2_830_1050_lid __initconst = {
2737bf974f6SHans de Goede 	.button = {
2747bf974f6SHans de Goede 		.code = SW_LID,
2757bf974f6SHans de Goede 		.active_low = true,
2767bf974f6SHans de Goede 		.desc = "lid_sw",
2777bf974f6SHans de Goede 		.type = EV_SW,
2787bf974f6SHans de Goede 		.wakeup = true,
2797bf974f6SHans de Goede 		.debounce_interval = 50,
2807bf974f6SHans de Goede 	},
2817bf974f6SHans de Goede 	.chip = "INT33FC:02",
2827bf974f6SHans de Goede 	.pin = 26,
2837bf974f6SHans de Goede };
2847bf974f6SHans de Goede 
2857bf974f6SHans de Goede /* This gets filled by lenovo_yoga_tab2_830_1050_init() */
2867bf974f6SHans de Goede static struct rmi_device_platform_data lenovo_yoga_tab2_830_1050_rmi_pdata = { };
2877bf974f6SHans de Goede 
2887bf974f6SHans de Goede static struct x86_i2c_client_info lenovo_yoga_tab2_830_1050_i2c_clients[] __initdata = {
2897bf974f6SHans de Goede 	{
2907bf974f6SHans de Goede 		/*
2917bf974f6SHans de Goede 		 * This must be the first entry because lenovo_yoga_tab2_830_1050_init()
2927bf974f6SHans de Goede 		 * may update its swnode. LSM303DA accelerometer + magnetometer.
2937bf974f6SHans de Goede 		 */
2947bf974f6SHans de Goede 		.board_info = {
2957bf974f6SHans de Goede 			.type = "lsm303d",
2967bf974f6SHans de Goede 			.addr = 0x1d,
2977bf974f6SHans de Goede 			.dev_name = "lsm303d",
2987bf974f6SHans de Goede 		},
2997bf974f6SHans de Goede 		.adapter_path = "\\_SB_.I2C5",
3007bf974f6SHans de Goede 	}, {
3017bf974f6SHans de Goede 		/* AL3320A ambient light sensor */
3027bf974f6SHans de Goede 		.board_info = {
3037bf974f6SHans de Goede 			.type = "al3320a",
3047bf974f6SHans de Goede 			.addr = 0x1c,
3057bf974f6SHans de Goede 			.dev_name = "al3320a",
3067bf974f6SHans de Goede 		},
3077bf974f6SHans de Goede 		.adapter_path = "\\_SB_.I2C5",
3087bf974f6SHans de Goede 	}, {
3097bf974f6SHans de Goede 		/* bq24292i battery charger */
3107bf974f6SHans de Goede 		.board_info = {
3117bf974f6SHans de Goede 			.type = "bq24190",
3127bf974f6SHans de Goede 			.addr = 0x6b,
3137bf974f6SHans de Goede 			.dev_name = "bq24292i",
3147bf974f6SHans de Goede 			.swnode = &lenovo_yoga_tab2_830_1050_bq24190_node,
3157bf974f6SHans de Goede 			.platform_data = &bq24190_pdata,
3167bf974f6SHans de Goede 		},
317ec5a4565SHans de Goede 		.adapter_path = "\\_SB_.I2C1",
3187bf974f6SHans de Goede 		.irq_data = {
3197bf974f6SHans de Goede 			.type = X86_ACPI_IRQ_TYPE_GPIOINT,
3207bf974f6SHans de Goede 			.chip = "INT33FC:02",
3217bf974f6SHans de Goede 			.index = 2,
3227bf974f6SHans de Goede 			.trigger = ACPI_EDGE_SENSITIVE,
3237bf974f6SHans de Goede 			.polarity = ACPI_ACTIVE_HIGH,
3247bf974f6SHans de Goede 		},
3257bf974f6SHans de Goede 	}, {
3267bf974f6SHans de Goede 		/* BQ27541 fuel-gauge */
3277bf974f6SHans de Goede 		.board_info = {
3287bf974f6SHans de Goede 			.type = "bq27541",
3297bf974f6SHans de Goede 			.addr = 0x55,
3307bf974f6SHans de Goede 			.dev_name = "bq27541",
3317bf974f6SHans de Goede 			.swnode = &fg_bq24190_supply_node,
3327bf974f6SHans de Goede 		},
3337bf974f6SHans de Goede 		.adapter_path = "\\_SB_.I2C1",
3347bf974f6SHans de Goede 	}, {
3357bf974f6SHans de Goede 		/* Synaptics RMI touchscreen */
3367bf974f6SHans de Goede 		.board_info = {
3377bf974f6SHans de Goede 			.type = "rmi4_i2c",
3387bf974f6SHans de Goede 			.addr = 0x38,
3397bf974f6SHans de Goede 			.dev_name = "rmi4_i2c",
3407bf974f6SHans de Goede 			.platform_data = &lenovo_yoga_tab2_830_1050_rmi_pdata,
3417bf974f6SHans de Goede 		},
3427bf974f6SHans de Goede 		.adapter_path = "\\_SB_.I2C6",
3437bf974f6SHans de Goede 		.irq_data = {
3447bf974f6SHans de Goede 			.type = X86_ACPI_IRQ_TYPE_APIC,
3457bf974f6SHans de Goede 			.index = 0x45,
3467bf974f6SHans de Goede 			.trigger = ACPI_EDGE_SENSITIVE,
3477bf974f6SHans de Goede 			.polarity = ACPI_ACTIVE_HIGH,
3487bf974f6SHans de Goede 		},
3497bf974f6SHans de Goede 	}, {
3507bf974f6SHans de Goede 		/* LP8557 Backlight controller */
3517bf974f6SHans de Goede 		.board_info = {
3527bf974f6SHans de Goede 			.type = "lp8557",
3537bf974f6SHans de Goede 			.addr = 0x2c,
35401862d01SHans de Goede 			.dev_name = "lp8557",
3557bf974f6SHans de Goede 			.platform_data = &lenovo_lp8557_pdata,
35601862d01SHans de Goede 		},
3577bf974f6SHans de Goede 		.adapter_path = "\\_SB_.I2C3",
3587bf974f6SHans de Goede 	},
359dadbc368SHans de Goede };
3607bf974f6SHans de Goede 
3617bf974f6SHans de Goede static struct gpiod_lookup_table lenovo_yoga_tab2_830_1050_int3496_gpios = {
3627bf974f6SHans de Goede 	.dev_id = "intel-int3496",
3637bf974f6SHans de Goede 	.table = {
3647bf974f6SHans de Goede 		GPIO_LOOKUP("INT33FC:02", 1, "mux", GPIO_ACTIVE_LOW),
3657bf974f6SHans de Goede 		GPIO_LOOKUP("INT33FC:02", 24, "id", GPIO_ACTIVE_HIGH),
3667bf974f6SHans de Goede 		{ }
3677bf974f6SHans de Goede 	},
3687bf974f6SHans de Goede };
36901862d01SHans de Goede 
37001862d01SHans de Goede #define LENOVO_YOGA_TAB2_830_1050_CODEC_NAME "spi-10WM5102:00"
371*e578c943SHans de Goede 
372*e578c943SHans de Goede static struct gpiod_lookup_table lenovo_yoga_tab2_830_1050_codec_gpios = {
3737bf974f6SHans de Goede 	.dev_id = LENOVO_YOGA_TAB2_830_1050_CODEC_NAME,
374*e578c943SHans de Goede 	.table = {
375*e578c943SHans de Goede 		GPIO_LOOKUP("gpio_crystalcove", 3, "reset", GPIO_ACTIVE_HIGH),
376*e578c943SHans de Goede 		GPIO_LOOKUP("INT33FC:01", 23, "wlf,ldoena", GPIO_ACTIVE_HIGH),
377*e578c943SHans de Goede 		GPIO_LOOKUP("arizona", 2, "wlf,spkvdd-ena", GPIO_ACTIVE_HIGH),
378*e578c943SHans de Goede 		GPIO_LOOKUP("arizona", 4, "wlf,micd-pol", GPIO_ACTIVE_LOW),
379*e578c943SHans de Goede 		{ }
380*e578c943SHans de Goede 	},
381*e578c943SHans de Goede };
382*e578c943SHans de Goede 
383*e578c943SHans de Goede static struct gpiod_lookup_table * const lenovo_yoga_tab2_830_1050_gpios[] = {
384*e578c943SHans de Goede 	&lenovo_yoga_tab2_830_1050_int3496_gpios,
385*e578c943SHans de Goede 	&lenovo_yoga_tab2_830_1050_codec_gpios,
386*e578c943SHans de Goede 	NULL
387*e578c943SHans de Goede };
388*e578c943SHans de Goede 
38901862d01SHans de Goede static int __init lenovo_yoga_tab2_830_1050_init(void);
3907bf974f6SHans de Goede static void lenovo_yoga_tab2_830_1050_exit(void);
3917bf974f6SHans de Goede 
3927bf974f6SHans de Goede const struct x86_dev_info lenovo_yoga_tab2_830_1050_info __initconst = {
3937bf974f6SHans de Goede 	.i2c_client_info = lenovo_yoga_tab2_830_1050_i2c_clients,
3947bf974f6SHans de Goede 	.i2c_client_count = ARRAY_SIZE(lenovo_yoga_tab2_830_1050_i2c_clients),
3957bf974f6SHans de Goede 	.pdev_info = int3496_pdevs,
3967bf974f6SHans de Goede 	.pdev_count = 1,
3977bf974f6SHans de Goede 	.gpio_button = &lenovo_yoga_tab2_830_1050_lid,
3987bf974f6SHans de Goede 	.gpio_button_count = 1,
3997bf974f6SHans de Goede 	.gpiod_lookup_tables = lenovo_yoga_tab2_830_1050_gpios,
4007bf974f6SHans de Goede 	.bat_swnode = &generic_lipo_hv_4v35_battery_node,
4017bf974f6SHans de Goede 	.modules = bq24190_modules,
4027bf974f6SHans de Goede 	.init = lenovo_yoga_tab2_830_1050_init,
4037bf974f6SHans de Goede 	.exit = lenovo_yoga_tab2_830_1050_exit,
4047bf974f6SHans de Goede };
4057bf974f6SHans de Goede 
406*e578c943SHans de Goede /*
407*e578c943SHans de Goede  * The Lenovo Yoga Tablet 2 830 and 1050 (8" vs 10") versions use the same
4087bf974f6SHans de Goede  * mainboard, but the 830 uses a portrait LCD panel with a landscape touchscreen,
4097bf974f6SHans de Goede  * requiring the touchscreen driver to adjust the touch-coords to match the LCD.
4107bf974f6SHans de Goede  * And requiring the accelerometer to have a mount-matrix set to correct for
4117bf974f6SHans de Goede  * the 90° rotation of the LCD vs the frame.
4127bf974f6SHans de Goede  */
4137bf974f6SHans de Goede static const char * const lenovo_yoga_tab2_830_lms303d_mount_matrix[] = {
4147bf974f6SHans de Goede 	"0", "1", "0",
4157bf974f6SHans de Goede 	"-1", "0", "0",
4167bf974f6SHans de Goede 	"0", "0", "1"
4177bf974f6SHans de Goede };
4187bf974f6SHans de Goede 
4197bf974f6SHans de Goede static const struct property_entry lenovo_yoga_tab2_830_lms303d_props[] = {
4207bf974f6SHans de Goede 	PROPERTY_ENTRY_STRING_ARRAY("mount-matrix", lenovo_yoga_tab2_830_lms303d_mount_matrix),
4217bf974f6SHans de Goede 	{ }
4227bf974f6SHans de Goede };
4237bf974f6SHans de Goede 
4247bf974f6SHans de Goede static const struct software_node lenovo_yoga_tab2_830_lms303d_node = {
4257bf974f6SHans de Goede 	.properties = lenovo_yoga_tab2_830_lms303d_props,
4267bf974f6SHans de Goede };
4277bf974f6SHans de Goede 
lenovo_yoga_tab2_830_1050_init_touchscreen(void)4287bf974f6SHans de Goede static int __init lenovo_yoga_tab2_830_1050_init_touchscreen(void)
4297bf974f6SHans de Goede {
4307bf974f6SHans de Goede 	struct gpio_desc *gpiod;
4317bf974f6SHans de Goede 	int ret;
4327bf974f6SHans de Goede 
4337bf974f6SHans de Goede 	/* Use PMIC GPIO 10 bootstrap pin to differentiate 830 vs 1050 */
4347bf974f6SHans de Goede 	ret = x86_android_tablet_get_gpiod("gpio_crystalcove", 10, &gpiod);
4357bf974f6SHans de Goede 	if (ret)
4367bf974f6SHans de Goede 		return ret;
4377bf974f6SHans de Goede 
4387bf974f6SHans de Goede 	ret = gpiod_get_value_cansleep(gpiod);
4397bf974f6SHans de Goede 	if (ret) {
4407bf974f6SHans de Goede 		pr_info("detected Lenovo Yoga Tablet 2 1050F/L\n");
4417bf974f6SHans de Goede 	} else {
4427bf974f6SHans de Goede 		pr_info("detected Lenovo Yoga Tablet 2 830F/L\n");
4437bf974f6SHans de Goede 		lenovo_yoga_tab2_830_1050_rmi_pdata.sensor_pdata.axis_align.swap_axes = true;
4447bf974f6SHans de Goede 		lenovo_yoga_tab2_830_1050_rmi_pdata.sensor_pdata.axis_align.flip_y = true;
4457bf974f6SHans de Goede 		lenovo_yoga_tab2_830_1050_i2c_clients[0].board_info.swnode =
4467bf974f6SHans de Goede 			&lenovo_yoga_tab2_830_lms303d_node;
4477bf974f6SHans de Goede 	}
4487bf974f6SHans de Goede 
4497bf974f6SHans de Goede 	return 0;
4507bf974f6SHans de Goede }
4517bf974f6SHans de Goede 
4527bf974f6SHans de Goede /* SUS (INT33FC:02) pin 6 needs to be configured as pmu_clk for the audio codec */
4537bf974f6SHans de Goede static const struct pinctrl_map lenovo_yoga_tab2_830_1050_codec_pinctrl_map =
4547bf974f6SHans de Goede 	PIN_MAP_MUX_GROUP(LENOVO_YOGA_TAB2_830_1050_CODEC_NAME, "codec_32khz_clk",
4557bf974f6SHans de Goede 			  "INT33FC:02", "pmu_clk2_grp", "pmu_clk");
4567bf974f6SHans de Goede 
4577bf974f6SHans de Goede static struct pinctrl *lenovo_yoga_tab2_830_1050_codec_pinctrl;
4587bf974f6SHans de Goede static struct sys_off_handler *lenovo_yoga_tab2_830_1050_sys_off_handler;
4597bf974f6SHans de Goede 
lenovo_yoga_tab2_830_1050_init_codec(void)4607bf974f6SHans de Goede static int __init lenovo_yoga_tab2_830_1050_init_codec(void)
4617bf974f6SHans de Goede {
4627bf974f6SHans de Goede 	struct device *codec_dev;
4637bf974f6SHans de Goede 	struct pinctrl *pinctrl;
4647bf974f6SHans de Goede 	int ret;
4657bf974f6SHans de Goede 
4667bf974f6SHans de Goede 	codec_dev = bus_find_device_by_name(&spi_bus_type, NULL,
4677bf974f6SHans de Goede 					    LENOVO_YOGA_TAB2_830_1050_CODEC_NAME);
4687bf974f6SHans de Goede 	if (!codec_dev) {
4697bf974f6SHans de Goede 		pr_err("error cannot find %s device\n", LENOVO_YOGA_TAB2_830_1050_CODEC_NAME);
4707bf974f6SHans de Goede 		return -ENODEV;
4717bf974f6SHans de Goede 	}
4727bf974f6SHans de Goede 
4737bf974f6SHans de Goede 	ret = pinctrl_register_mappings(&lenovo_yoga_tab2_830_1050_codec_pinctrl_map, 1);
4747bf974f6SHans de Goede 	if (ret)
47501862d01SHans de Goede 		goto err_put_device;
4767bf974f6SHans de Goede 
4777bf974f6SHans de Goede 	pinctrl = pinctrl_get_select(codec_dev, "codec_32khz_clk");
4787bf974f6SHans de Goede 	if (IS_ERR(pinctrl)) {
4797bf974f6SHans de Goede 		ret = dev_err_probe(codec_dev, PTR_ERR(pinctrl), "selecting codec_32khz_clk\n");
4807bf974f6SHans de Goede 		goto err_unregister_mappings;
4817bf974f6SHans de Goede 	}
4827bf974f6SHans de Goede 
4837bf974f6SHans de Goede 	/* We're done with the codec_dev now */
4847bf974f6SHans de Goede 	put_device(codec_dev);
4857bf974f6SHans de Goede 
4867bf974f6SHans de Goede 	lenovo_yoga_tab2_830_1050_codec_pinctrl = pinctrl;
4877bf974f6SHans de Goede 	return 0;
4887bf974f6SHans de Goede 
4897bf974f6SHans de Goede err_unregister_mappings:
4907bf974f6SHans de Goede 	pinctrl_unregister_mappings(&lenovo_yoga_tab2_830_1050_codec_pinctrl_map);
4917bf974f6SHans de Goede err_put_device:
4927bf974f6SHans de Goede 	put_device(codec_dev);
4937bf974f6SHans de Goede 	return ret;
4947bf974f6SHans de Goede }
4957bf974f6SHans de Goede 
4967bf974f6SHans de Goede /*
4977bf974f6SHans de Goede  * These tablet's DSDT does not set acpi_gbl_reduced_hardware, so acpi_power_off
4987bf974f6SHans de Goede  * gets used as pm_power_off handler. This causes "poweroff" on these tablets
4997bf974f6SHans de Goede  * to hang hard. Requiring pressing the powerbutton for 30 seconds *twice*
5007bf974f6SHans de Goede  * followed by a normal 3 second press to recover. Avoid this by doing an EFI
5017bf974f6SHans de Goede  * poweroff instead.
5027bf974f6SHans de Goede  */
lenovo_yoga_tab2_830_1050_power_off(struct sys_off_data * data)5037bf974f6SHans de Goede static int lenovo_yoga_tab2_830_1050_power_off(struct sys_off_data *data)
5047bf974f6SHans de Goede {
5057bf974f6SHans de Goede 	efi.reset_system(EFI_RESET_SHUTDOWN, EFI_SUCCESS, 0, NULL);
5067bf974f6SHans de Goede 
5077bf974f6SHans de Goede 	return NOTIFY_DONE;
5087bf974f6SHans de Goede }
5097bf974f6SHans de Goede 
lenovo_yoga_tab2_830_1050_init(void)5107bf974f6SHans de Goede static int __init lenovo_yoga_tab2_830_1050_init(void)
5117bf974f6SHans de Goede {
5127bf974f6SHans de Goede 	int ret;
5137bf974f6SHans de Goede 
5147bf974f6SHans de Goede 	ret = lenovo_yoga_tab2_830_1050_init_touchscreen();
5157bf974f6SHans de Goede 	if (ret)
5167bf974f6SHans de Goede 		return ret;
5177bf974f6SHans de Goede 
5187bf974f6SHans de Goede 	ret = lenovo_yoga_tab2_830_1050_init_codec();
5197bf974f6SHans de Goede 	if (ret)
5207bf974f6SHans de Goede 		return ret;
5217bf974f6SHans de Goede 
5227bf974f6SHans de Goede 	/* SYS_OFF_PRIO_FIRMWARE + 1 so that it runs before acpi_power_off */
5237bf974f6SHans de Goede 	lenovo_yoga_tab2_830_1050_sys_off_handler =
5247bf974f6SHans de Goede 		register_sys_off_handler(SYS_OFF_MODE_POWER_OFF, SYS_OFF_PRIO_FIRMWARE + 1,
5257bf974f6SHans de Goede 					 lenovo_yoga_tab2_830_1050_power_off, NULL);
5267bf974f6SHans de Goede 	if (IS_ERR(lenovo_yoga_tab2_830_1050_sys_off_handler))
5277bf974f6SHans de Goede 		return PTR_ERR(lenovo_yoga_tab2_830_1050_sys_off_handler);
5287bf974f6SHans de Goede 
5297bf974f6SHans de Goede 	return 0;
5307bf974f6SHans de Goede }
5317bf974f6SHans de Goede 
lenovo_yoga_tab2_830_1050_exit(void)5327bf974f6SHans de Goede static void lenovo_yoga_tab2_830_1050_exit(void)
5337bf974f6SHans de Goede {
5347bf974f6SHans de Goede 	unregister_sys_off_handler(lenovo_yoga_tab2_830_1050_sys_off_handler);
5357bf974f6SHans de Goede 
5367bf974f6SHans de Goede 	if (lenovo_yoga_tab2_830_1050_codec_pinctrl) {
5377bf974f6SHans de Goede 		pinctrl_put(lenovo_yoga_tab2_830_1050_codec_pinctrl);
5387bf974f6SHans de Goede 		pinctrl_unregister_mappings(&lenovo_yoga_tab2_830_1050_codec_pinctrl_map);
5397bf974f6SHans de Goede 	}
5407bf974f6SHans de Goede }
5417bf974f6SHans de Goede 
5427bf974f6SHans de Goede /* Lenovo Yoga Tab 3 Pro YT3-X90F */
5439b1d2662SHans de Goede 
5449b1d2662SHans de Goede /*
5459b1d2662SHans de Goede  * There are 2 batteries, with 2 bq27500 fuel-gauges and 2 bq25892 chargers,
5469b1d2662SHans de Goede  * "bq25890-charger-1" is instantiated from: drivers/i2c/busses/i2c-cht-wc.c.
5479b1d2662SHans de Goede  */
5489b1d2662SHans de Goede static const char * const lenovo_yt3_bq25892_0_suppliers[] = { "cht_wcove_pwrsrc" };
5499b1d2662SHans de Goede static const char * const bq25890_1_psy[] = { "bq25890-charger-1" };
5509b1d2662SHans de Goede 
5519b1d2662SHans de Goede static const struct property_entry fg_bq25890_1_supply_props[] = {
5529b1d2662SHans de Goede 	PROPERTY_ENTRY_STRING_ARRAY("supplied-from", bq25890_1_psy),
5539b1d2662SHans de Goede 	{ }
5547bf974f6SHans de Goede };
5557bf974f6SHans de Goede 
5567bf974f6SHans de Goede static const struct software_node fg_bq25890_1_supply_node = {
5577bf974f6SHans de Goede 	.properties = fg_bq25890_1_supply_props,
5587bf974f6SHans de Goede };
5597bf974f6SHans de Goede 
5607bf974f6SHans de Goede /* bq25892 charger settings for the flat lipo battery behind the screen */
5617bf974f6SHans de Goede static const struct property_entry lenovo_yt3_bq25892_0_props[] = {
5627bf974f6SHans de Goede 	PROPERTY_ENTRY_STRING_ARRAY("supplied-from", lenovo_yt3_bq25892_0_suppliers),
5637bf974f6SHans de Goede 	PROPERTY_ENTRY_STRING("linux,power-supply-name", "bq25892-second-chrg"),
5647bf974f6SHans de Goede 	PROPERTY_ENTRY_U32("linux,iinlim-percentage", 40),
5657bf974f6SHans de Goede 	PROPERTY_ENTRY_BOOL("linux,skip-reset"),
5667bf974f6SHans de Goede 	/* Values taken from Android Factory Image */
5677bf974f6SHans de Goede 	PROPERTY_ENTRY_U32("ti,charge-current", 2048000),
5687bf974f6SHans de Goede 	PROPERTY_ENTRY_U32("ti,battery-regulation-voltage", 4352000),
5697bf974f6SHans de Goede 	PROPERTY_ENTRY_U32("ti,termination-current", 128000),
5707bf974f6SHans de Goede 	PROPERTY_ENTRY_U32("ti,precharge-current", 128000),
5717bf974f6SHans de Goede 	PROPERTY_ENTRY_U32("ti,minimum-sys-voltage", 3700000),
5727bf974f6SHans de Goede 	PROPERTY_ENTRY_U32("ti,boost-voltage", 4998000),
5737bf974f6SHans de Goede 	PROPERTY_ENTRY_U32("ti,boost-max-current", 500000),
5747bf974f6SHans de Goede 	PROPERTY_ENTRY_BOOL("ti,use-ilim-pin"),
5757bf974f6SHans de Goede 	{ }
5767bf974f6SHans de Goede };
5777bf974f6SHans de Goede 
5787bf974f6SHans de Goede static const struct software_node lenovo_yt3_bq25892_0_node = {
5797bf974f6SHans de Goede 	.properties = lenovo_yt3_bq25892_0_props,
5807bf974f6SHans de Goede };
5817bf974f6SHans de Goede 
5827bf974f6SHans de Goede static const struct property_entry lenovo_yt3_hideep_ts_props[] = {
5837bf974f6SHans de Goede 	PROPERTY_ENTRY_U32("touchscreen-size-x", 1600),
5847bf974f6SHans de Goede 	PROPERTY_ENTRY_U32("touchscreen-size-y", 2560),
5857bf974f6SHans de Goede 	PROPERTY_ENTRY_U32("touchscreen-max-pressure", 255),
5867bf974f6SHans de Goede 	{ }
5877bf974f6SHans de Goede };
5887bf974f6SHans de Goede 
5899b1d2662SHans de Goede static const struct software_node lenovo_yt3_hideep_ts_node = {
5909b1d2662SHans de Goede 	.properties = lenovo_yt3_hideep_ts_props,
5919b1d2662SHans de Goede };
5929b1d2662SHans de Goede 
5939b1d2662SHans de Goede static const struct x86_i2c_client_info lenovo_yt3_i2c_clients[] __initconst = {
5949b1d2662SHans de Goede 	{
5959b1d2662SHans de Goede 		/* bq27500 fuel-gauge for the flat lipo battery behind the screen */
5969b1d2662SHans de Goede 		.board_info = {
5979b1d2662SHans de Goede 			.type = "bq27500",
5989b1d2662SHans de Goede 			.addr = 0x55,
5999b1d2662SHans de Goede 			.dev_name = "bq27500_0",
6009b1d2662SHans de Goede 			.swnode = &fg_bq25890_supply_node,
6019b1d2662SHans de Goede 		},
6029b1d2662SHans de Goede 		.adapter_path = "\\_SB_.PCI0.I2C1",
6039b1d2662SHans de Goede 	}, {
6049b1d2662SHans de Goede 		/* bq25892 charger for the flat lipo battery behind the screen */
605607fbac0SHans de Goede 		.board_info = {
606607fbac0SHans de Goede 			.type = "bq25892",
607607fbac0SHans de Goede 			.addr = 0x6b,
608607fbac0SHans de Goede 			.dev_name = "bq25892_0",
609607fbac0SHans de Goede 			.swnode = &lenovo_yt3_bq25892_0_node,
610607fbac0SHans de Goede 		},
611ec5a4565SHans de Goede 		.adapter_path = "\\_SB_.PCI0.I2C1",
612607fbac0SHans de Goede 		.irq_data = {
613607fbac0SHans de Goede 			.type = X86_ACPI_IRQ_TYPE_GPIOINT,
6147bf974f6SHans de Goede 			.chip = "INT33FF:01",
6157bf974f6SHans de Goede 			.index = 5,
6167bf974f6SHans de Goede 			.trigger = ACPI_EDGE_SENSITIVE,
6177bf974f6SHans de Goede 			.polarity = ACPI_ACTIVE_LOW,
6187bf974f6SHans de Goede 		},
6197bf974f6SHans de Goede 	}, {
6207bf974f6SHans de Goede 		/* bq27500 fuel-gauge for the round li-ion cells in the hinge */
6217bf974f6SHans de Goede 		.board_info = {
6227bf974f6SHans de Goede 			.type = "bq27500",
6237bf974f6SHans de Goede 			.addr = 0x55,
6247bf974f6SHans de Goede 			.dev_name = "bq27500_1",
6257bf974f6SHans de Goede 			.swnode = &fg_bq25890_1_supply_node,
6267bf974f6SHans de Goede 		},
6277bf974f6SHans de Goede 		.adapter_path = "\\_SB_.PCI0.I2C2",
6287bf974f6SHans de Goede 	}, {
6297bf974f6SHans de Goede 		/* HiDeep IST520E Touchscreen */
6307bf974f6SHans de Goede 		.board_info = {
6317bf974f6SHans de Goede 			.type = "hideep_ts",
6327bf974f6SHans de Goede 			.addr = 0x6c,
6337bf974f6SHans de Goede 			.dev_name = "hideep_ts",
6347bf974f6SHans de Goede 			.swnode = &lenovo_yt3_hideep_ts_node,
6357bf974f6SHans de Goede 		},
6367bf974f6SHans de Goede 		.adapter_path = "\\_SB_.PCI0.I2C6",
6377bf974f6SHans de Goede 		.irq_data = {
6387bf974f6SHans de Goede 			.type = X86_ACPI_IRQ_TYPE_GPIOINT,
6397bf974f6SHans de Goede 			.chip = "INT33FF:03",
6407bf974f6SHans de Goede 			.index = 77,
6417bf974f6SHans de Goede 			.trigger = ACPI_LEVEL_SENSITIVE,
6427bf974f6SHans de Goede 			.polarity = ACPI_ACTIVE_LOW,
6437bf974f6SHans de Goede 		},
6447bf974f6SHans de Goede 	}, {
6457bf974f6SHans de Goede 		/* LP8557 Backlight controller */
6467bf974f6SHans de Goede 		.board_info = {
6477bf974f6SHans de Goede 			.type = "lp8557",
6487bf974f6SHans de Goede 			.addr = 0x2c,
6497bf974f6SHans de Goede 			.dev_name = "lp8557",
6507bf974f6SHans de Goede 			.platform_data = &lenovo_lp8557_pdata,
6517bf974f6SHans de Goede 		},
6527bf974f6SHans de Goede 		.adapter_path = "\\_SB_.PCI0.I2C1",
6537bf974f6SHans de Goede 	}
6549b1d2662SHans de Goede };
6559b1d2662SHans de Goede 
lenovo_yt3_init(void)6569b1d2662SHans de Goede static int __init lenovo_yt3_init(void)
6579b1d2662SHans de Goede {
6587bf974f6SHans de Goede 	struct gpio_desc *gpiod;
6597bf974f6SHans de Goede 	int ret;
6607bf974f6SHans de Goede 
6619b1d2662SHans de Goede 	/*
6629b1d2662SHans de Goede 	 * The "bq25892_0" charger IC has its /CE (Charge-Enable) and OTG pins
6639b1d2662SHans de Goede 	 * connected to GPIOs, rather then having them hardwired to the correct
6649b1d2662SHans de Goede 	 * values as is normally done.
6659b1d2662SHans de Goede 	 *
6669b1d2662SHans de Goede 	 * The bq25890_charger driver controls these through I2C, but this only
6679b1d2662SHans de Goede 	 * works if not overridden by the pins. Set these pins here:
6689b1d2662SHans de Goede 	 * 1. Set /CE to 0 to allow charging.
6699b1d2662SHans de Goede 	 * 2. Set OTG to 0 disable V5 boost output since the 5V boost output of
6709b1d2662SHans de Goede 	 *    the main "bq25892_1" charger is used when necessary.
6719b1d2662SHans de Goede 	 */
6729b1d2662SHans de Goede 
6739b1d2662SHans de Goede 	/* /CE pin */
6747bf974f6SHans de Goede 	ret = x86_android_tablet_get_gpiod("INT33FF:02", 22, &gpiod);
6757bf974f6SHans de Goede 	if (ret < 0)
6767bf974f6SHans de Goede 		return ret;
6779b1d2662SHans de Goede 
6787bf974f6SHans de Goede 	/*
6797bf974f6SHans de Goede 	 * The gpio_desc returned by x86_android_tablet_get_gpiod() is a "raw"
680 	 * gpio_desc, that is there is no way to pass lookup-flags like
681 	 * GPIO_ACTIVE_LOW. Set the GPIO to 0 here to enable charging since
682 	 * the /CE pin is active-low, but not marked as such in the gpio_desc.
683 	 */
684 	gpiod_set_value(gpiod, 0);
685 
686 	/* OTG pin */
687 	ret = x86_android_tablet_get_gpiod("INT33FF:03", 19, &gpiod);
688 	if (ret < 0)
689 		return ret;
690 
691 	gpiod_set_value(gpiod, 0);
692 
693 	/* Enable the regulators used by the touchscreen */
694 	intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0x9b, 0x02, 0xff);
695 	intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0xa0, 0x02, 0xff);
696 
697 	return 0;
698 }
699 
700 static struct gpiod_lookup_table lenovo_yt3_hideep_gpios = {
701 	.dev_id = "i2c-hideep_ts",
702 	.table = {
703 		GPIO_LOOKUP("INT33FF:00", 7, "reset", GPIO_ACTIVE_LOW),
704 		{ }
705 	},
706 };
707 
708 static struct gpiod_lookup_table * const lenovo_yt3_gpios[] = {
709 	&lenovo_yt3_hideep_gpios,
710 	NULL
711 };
712 
713 const struct x86_dev_info lenovo_yt3_info __initconst = {
714 	.i2c_client_info = lenovo_yt3_i2c_clients,
715 	.i2c_client_count = ARRAY_SIZE(lenovo_yt3_i2c_clients),
716 	.gpiod_lookup_tables = lenovo_yt3_gpios,
717 	.init = lenovo_yt3_init,
718 };
719