1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
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
6  * in their DSDT.
7  *
8  * Copyright (C) 2021-2023 Hans de Goede <hdegoede@redhat.com>
9  */
10 
11 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
12 
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>
25 
26 #include "shared-psy-info.h"
27 #include "x86-android-tablets.h"
28 
29 /*
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.
34  *
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.
37  *
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.
41  *
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.
44  *
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.
50  */
51 static struct lp855x_platform_data lenovo_lp8557_pwm_and_reg_pdata = {
52 	.device_control = 0x86,
53 	.initial_brightness = 128,
54 };
55 
56 static struct lp855x_platform_data lenovo_lp8557_reg_only_pdata = {
57 	.device_control = 0x85,
58 	.initial_brightness = 128,
59 };
60 
61 /* Lenovo Yoga Book X90F / X90L's Android factory img has everything hardcoded */
62 
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),
66 	{ }
67 };
68 
69 static const struct software_node lenovo_yb1_x90_wacom_node = {
70 	.properties = lenovo_yb1_x90_wacom_props,
71 };
72 
73 /*
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".
81  */
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"),
87 	{ }
88 };
89 
90 static const struct software_node lenovo_yb1_x90_hideep_ts_node = {
91 	.properties = lenovo_yb1_x90_hideep_ts_props,
92 };
93 
94 static const struct x86_i2c_client_info lenovo_yb1_x90_i2c_clients[] __initconst = {
95 	{
96 		/* BQ27542 fuel-gauge */
97 		.board_info = {
98 			.type = "bq27542",
99 			.addr = 0x55,
100 			.dev_name = "bq27542",
101 			.swnode = &fg_bq25890_supply_node,
102 		},
103 		.adapter_path = "\\_SB_.PCI0.I2C1",
104 	}, {
105 		/* Goodix Touchscreen in keyboard half */
106 		.board_info = {
107 			.type = "GDIX1001:00",
108 			.addr = 0x14,
109 			.dev_name = "goodix_ts",
110 		},
111 		.adapter_path = "\\_SB_.PCI0.I2C2",
112 		.irq_data = {
113 			.type = X86_ACPI_IRQ_TYPE_GPIOINT,
114 			.chip = "INT33FF:01",
115 			.index = 56,
116 			.trigger = ACPI_EDGE_SENSITIVE,
117 			.polarity = ACPI_ACTIVE_LOW,
118 			.con_id = "goodix_ts_irq",
119 		},
120 	}, {
121 		/* Wacom Digitizer in keyboard half */
122 		.board_info = {
123 			.type = "hid-over-i2c",
124 			.addr = 0x09,
125 			.dev_name = "wacom",
126 			.swnode = &lenovo_yb1_x90_wacom_node,
127 		},
128 		.adapter_path = "\\_SB_.PCI0.I2C4",
129 		.irq_data = {
130 			.type = X86_ACPI_IRQ_TYPE_GPIOINT,
131 			.chip = "INT33FF:01",
132 			.index = 49,
133 			.trigger = ACPI_LEVEL_SENSITIVE,
134 			.polarity = ACPI_ACTIVE_LOW,
135 			.con_id = "wacom_irq",
136 		},
137 	}, {
138 		/* LP8557 Backlight controller */
139 		.board_info = {
140 			.type = "lp8557",
141 			.addr = 0x2c,
142 			.dev_name = "lp8557",
143 			.platform_data = &lenovo_lp8557_pwm_and_reg_pdata,
144 		},
145 		.adapter_path = "\\_SB_.PCI0.I2C4",
146 	}, {
147 		/* HiDeep IST940E Touchscreen in display half */
148 		.board_info = {
149 			.type = "hideep_ts",
150 			.addr = 0x6c,
151 			.dev_name = "hideep_ts",
152 			.swnode = &lenovo_yb1_x90_hideep_ts_node,
153 		},
154 		.adapter_path = "\\_SB_.PCI0.I2C6",
155 		.irq_data = {
156 			.type = X86_ACPI_IRQ_TYPE_GPIOINT,
157 			.chip = "INT33FF:03",
158 			.index = 77,
159 			.trigger = ACPI_LEVEL_SENSITIVE,
160 			.polarity = ACPI_ACTIVE_LOW,
161 			.con_id = "hideep_ts_irq",
162 		},
163 	},
164 };
165 
166 static const struct platform_device_info lenovo_yb1_x90_pdevs[] __initconst = {
167 	{
168 		.name = "yogabook-touch-kbd-digitizer-switch",
169 		.id = PLATFORM_DEVID_NONE,
170 	},
171 };
172 
173 /*
174  * DSDT says UART path is "\\_SB.PCIO.URT1" with a letter 'O' instead of
175  * the number '0' add the link manually.
176  */
177 static const struct x86_serdev_info lenovo_yb1_x90_serdevs[] __initconst = {
178 	{
179 		.ctrl_hid = "8086228A",
180 		.ctrl_uid = "1",
181 		.ctrl_devname = "serial0",
182 		.serdev_hid = "BCM2E1A",
183 	},
184 };
185 
186 static const struct x86_gpio_button lenovo_yb1_x90_lid __initconst = {
187 	.button = {
188 		.code = SW_LID,
189 		.active_low = true,
190 		.desc = "lid_sw",
191 		.type = EV_SW,
192 		.wakeup = true,
193 		.debounce_interval = 50,
194 	},
195 	.chip = "INT33FF:02",
196 	.pin = 19,
197 };
198 
199 static struct gpiod_lookup_table lenovo_yb1_x90_goodix_gpios = {
200 	.dev_id = "i2c-goodix_ts",
201 	.table = {
202 		GPIO_LOOKUP("INT33FF:01", 53, "reset", GPIO_ACTIVE_HIGH),
203 		GPIO_LOOKUP("INT33FF:01", 56, "irq", GPIO_ACTIVE_HIGH),
204 		{ }
205 	},
206 };
207 
208 static struct gpiod_lookup_table lenovo_yb1_x90_hideep_gpios = {
209 	.dev_id = "i2c-hideep_ts",
210 	.table = {
211 		GPIO_LOOKUP("INT33FF:00", 7, "reset", GPIO_ACTIVE_LOW),
212 		{ }
213 	},
214 };
215 
216 static struct gpiod_lookup_table lenovo_yb1_x90_wacom_gpios = {
217 	.dev_id = "i2c-wacom",
218 	.table = {
219 		GPIO_LOOKUP("INT33FF:00", 82, "reset", GPIO_ACTIVE_LOW),
220 		{ }
221 	},
222 };
223 
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,
228 	NULL
229 };
230 
231 static int __init lenovo_yb1_x90_init(void)
232 {
233 	/* Enable the regulators used by the touchscreens */
234 
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);
237 
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);
240 
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);
243 
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);
246 
247 	return 0;
248 }
249 
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,
261 };
262 
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 = {
265 	{
266 		/* BQ27542 fuel-gauge */
267 		.board_info = {
268 			.type = "bq27542",
269 			.addr = 0x55,
270 			.dev_name = "bq27542",
271 			.swnode = &fg_bq25890_supply_node,
272 		},
273 		.adapter_path = "\\_SB_.PCI0.I2C1",
274 	},
275 };
276 
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),
280 };
281 
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"),
288 	{ }
289 };
290 
291 static const struct software_node lenovo_yoga_tab2_830_1050_bq24190_node = {
292 	.properties = lenovo_yoga_tab2_830_1050_bq24190_props,
293 };
294 
295 static const struct x86_gpio_button lenovo_yoga_tab2_830_1050_lid __initconst = {
296 	.button = {
297 		.code = SW_LID,
298 		.active_low = true,
299 		.desc = "lid_sw",
300 		.type = EV_SW,
301 		.wakeup = true,
302 		.debounce_interval = 50,
303 	},
304 	.chip = "INT33FC:02",
305 	.pin = 26,
306 };
307 
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 = { };
310 
311 static struct x86_i2c_client_info lenovo_yoga_tab2_830_1050_i2c_clients[] __initdata = {
312 	{
313 		/*
314 		 * This must be the first entry because lenovo_yoga_tab2_830_1050_init()
315 		 * may update its swnode. LSM303DA accelerometer + magnetometer.
316 		 */
317 		.board_info = {
318 			.type = "lsm303d",
319 			.addr = 0x1d,
320 			.dev_name = "lsm303d",
321 		},
322 		.adapter_path = "\\_SB_.I2C5",
323 	}, {
324 		/* AL3320A ambient light sensor */
325 		.board_info = {
326 			.type = "al3320a",
327 			.addr = 0x1c,
328 			.dev_name = "al3320a",
329 		},
330 		.adapter_path = "\\_SB_.I2C5",
331 	}, {
332 		/* bq24292i battery charger */
333 		.board_info = {
334 			.type = "bq24190",
335 			.addr = 0x6b,
336 			.dev_name = "bq24292i",
337 			.swnode = &lenovo_yoga_tab2_830_1050_bq24190_node,
338 			.platform_data = &bq24190_pdata,
339 		},
340 		.adapter_path = "\\_SB_.I2C1",
341 		.irq_data = {
342 			.type = X86_ACPI_IRQ_TYPE_GPIOINT,
343 			.chip = "INT33FC:02",
344 			.index = 2,
345 			.trigger = ACPI_EDGE_SENSITIVE,
346 			.polarity = ACPI_ACTIVE_HIGH,
347 			.con_id = "bq24292i_irq",
348 		},
349 	}, {
350 		/* BQ27541 fuel-gauge */
351 		.board_info = {
352 			.type = "bq27541",
353 			.addr = 0x55,
354 			.dev_name = "bq27541",
355 			.swnode = &fg_bq24190_supply_node,
356 		},
357 		.adapter_path = "\\_SB_.I2C1",
358 	}, {
359 		/* Synaptics RMI touchscreen */
360 		.board_info = {
361 			.type = "rmi4_i2c",
362 			.addr = 0x38,
363 			.dev_name = "rmi4_i2c",
364 			.platform_data = &lenovo_yoga_tab2_830_1050_rmi_pdata,
365 		},
366 		.adapter_path = "\\_SB_.I2C6",
367 		.irq_data = {
368 			.type = X86_ACPI_IRQ_TYPE_APIC,
369 			.index = 0x45,
370 			.trigger = ACPI_EDGE_SENSITIVE,
371 			.polarity = ACPI_ACTIVE_HIGH,
372 		},
373 	}, {
374 		/* LP8557 Backlight controller */
375 		.board_info = {
376 			.type = "lp8557",
377 			.addr = 0x2c,
378 			.dev_name = "lp8557",
379 			.platform_data = &lenovo_lp8557_pwm_and_reg_pdata,
380 		},
381 		.adapter_path = "\\_SB_.I2C3",
382 	},
383 };
384 
385 static struct gpiod_lookup_table lenovo_yoga_tab2_830_1050_int3496_gpios = {
386 	.dev_id = "intel-int3496",
387 	.table = {
388 		GPIO_LOOKUP("INT33FC:02", 1, "mux", GPIO_ACTIVE_LOW),
389 		GPIO_LOOKUP("INT33FC:02", 24, "id", GPIO_ACTIVE_HIGH),
390 		{ }
391 	},
392 };
393 
394 #define LENOVO_YOGA_TAB2_830_1050_CODEC_NAME "spi-10WM5102:00"
395 
396 static struct gpiod_lookup_table lenovo_yoga_tab2_830_1050_codec_gpios = {
397 	.dev_id = LENOVO_YOGA_TAB2_830_1050_CODEC_NAME,
398 	.table = {
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),
403 		{ }
404 	},
405 };
406 
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,
410 	NULL
411 };
412 
413 static int __init lenovo_yoga_tab2_830_1050_init(void);
414 static void lenovo_yoga_tab2_830_1050_exit(void);
415 
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,
420 	.pdev_count = 1,
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,
428 };
429 
430 /*
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.
436  */
437 static const char * const lenovo_yoga_tab2_830_lms303d_mount_matrix[] = {
438 	"0", "1", "0",
439 	"-1", "0", "0",
440 	"0", "0", "1"
441 };
442 
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),
445 	{ }
446 };
447 
448 static const struct software_node lenovo_yoga_tab2_830_lms303d_node = {
449 	.properties = lenovo_yoga_tab2_830_lms303d_props,
450 };
451 
452 static int __init lenovo_yoga_tab2_830_1050_init_touchscreen(void)
453 {
454 	struct gpio_desc *gpiod;
455 	int ret;
456 
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);
460 	if (ret)
461 		return ret;
462 
463 	ret = gpiod_get_value_cansleep(gpiod);
464 	if (ret) {
465 		pr_info("detected Lenovo Yoga Tablet 2 1050F/L\n");
466 	} else {
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;
472 	}
473 
474 	return 0;
475 }
476 
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");
481 
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;
484 
485 static int __init lenovo_yoga_tab2_830_1050_init_codec(void)
486 {
487 	struct device *codec_dev;
488 	struct pinctrl *pinctrl;
489 	int ret;
490 
491 	codec_dev = bus_find_device_by_name(&spi_bus_type, NULL,
492 					    LENOVO_YOGA_TAB2_830_1050_CODEC_NAME);
493 	if (!codec_dev) {
494 		pr_err("error cannot find %s device\n", LENOVO_YOGA_TAB2_830_1050_CODEC_NAME);
495 		return -ENODEV;
496 	}
497 
498 	ret = pinctrl_register_mappings(&lenovo_yoga_tab2_830_1050_codec_pinctrl_map, 1);
499 	if (ret)
500 		goto err_put_device;
501 
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;
506 	}
507 
508 	/* We're done with the codec_dev now */
509 	put_device(codec_dev);
510 
511 	lenovo_yoga_tab2_830_1050_codec_pinctrl = pinctrl;
512 	return 0;
513 
514 err_unregister_mappings:
515 	pinctrl_unregister_mappings(&lenovo_yoga_tab2_830_1050_codec_pinctrl_map);
516 err_put_device:
517 	put_device(codec_dev);
518 	return ret;
519 }
520 
521 /*
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
526  * poweroff instead.
527  */
528 static int lenovo_yoga_tab2_830_1050_power_off(struct sys_off_data *data)
529 {
530 	efi.reset_system(EFI_RESET_SHUTDOWN, EFI_SUCCESS, 0, NULL);
531 
532 	return NOTIFY_DONE;
533 }
534 
535 static int __init lenovo_yoga_tab2_830_1050_init(void)
536 {
537 	int ret;
538 
539 	ret = lenovo_yoga_tab2_830_1050_init_touchscreen();
540 	if (ret)
541 		return ret;
542 
543 	ret = lenovo_yoga_tab2_830_1050_init_codec();
544 	if (ret)
545 		return ret;
546 
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);
553 
554 	return 0;
555 }
556 
557 static void lenovo_yoga_tab2_830_1050_exit(void)
558 {
559 	unregister_sys_off_handler(lenovo_yoga_tab2_830_1050_sys_off_handler);
560 
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);
564 	}
565 }
566 
567 /* Lenovo Yoga Tab 3 Pro YT3-X90F */
568 
569 /*
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.
572  */
573 static const char * const lenovo_yt3_bq25892_0_suppliers[] = { "cht_wcove_pwrsrc" };
574 static const char * const bq25890_1_psy[] = { "bq25890-charger-1" };
575 
576 static const struct property_entry fg_bq25890_1_supply_props[] = {
577 	PROPERTY_ENTRY_STRING_ARRAY("supplied-from", bq25890_1_psy),
578 	{ }
579 };
580 
581 static const struct software_node fg_bq25890_1_supply_node = {
582 	.properties = fg_bq25890_1_supply_props,
583 };
584 
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"),
599 	{ }
600 };
601 
602 static const struct software_node lenovo_yt3_bq25892_0_node = {
603 	.properties = lenovo_yt3_bq25892_0_props,
604 };
605 
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),
610 	{ }
611 };
612 
613 static const struct software_node lenovo_yt3_hideep_ts_node = {
614 	.properties = lenovo_yt3_hideep_ts_props,
615 };
616 
617 static const struct x86_i2c_client_info lenovo_yt3_i2c_clients[] __initconst = {
618 	{
619 		/* bq27500 fuel-gauge for the flat lipo battery behind the screen */
620 		.board_info = {
621 			.type = "bq27500",
622 			.addr = 0x55,
623 			.dev_name = "bq27500_0",
624 			.swnode = &fg_bq25890_supply_node,
625 		},
626 		.adapter_path = "\\_SB_.PCI0.I2C1",
627 	}, {
628 		/* bq25892 charger for the flat lipo battery behind the screen */
629 		.board_info = {
630 			.type = "bq25892",
631 			.addr = 0x6b,
632 			.dev_name = "bq25892_0",
633 			.swnode = &lenovo_yt3_bq25892_0_node,
634 		},
635 		.adapter_path = "\\_SB_.PCI0.I2C1",
636 		.irq_data = {
637 			.type = X86_ACPI_IRQ_TYPE_GPIOINT,
638 			.chip = "INT33FF:01",
639 			.index = 5,
640 			.trigger = ACPI_EDGE_SENSITIVE,
641 			.polarity = ACPI_ACTIVE_LOW,
642 			.con_id = "bq25892_0_irq",
643 		},
644 	}, {
645 		/* bq27500 fuel-gauge for the round li-ion cells in the hinge */
646 		.board_info = {
647 			.type = "bq27500",
648 			.addr = 0x55,
649 			.dev_name = "bq27500_1",
650 			.swnode = &fg_bq25890_1_supply_node,
651 		},
652 		.adapter_path = "\\_SB_.PCI0.I2C2",
653 	}, {
654 		/* HiDeep IST520E Touchscreen */
655 		.board_info = {
656 			.type = "hideep_ts",
657 			.addr = 0x6c,
658 			.dev_name = "hideep_ts",
659 			.swnode = &lenovo_yt3_hideep_ts_node,
660 		},
661 		.adapter_path = "\\_SB_.PCI0.I2C6",
662 		.irq_data = {
663 			.type = X86_ACPI_IRQ_TYPE_GPIOINT,
664 			.chip = "INT33FF:03",
665 			.index = 77,
666 			.trigger = ACPI_LEVEL_SENSITIVE,
667 			.polarity = ACPI_ACTIVE_LOW,
668 			.con_id = "hideep_ts_irq",
669 		},
670 	}, {
671 		/* LP8557 Backlight controller */
672 		.board_info = {
673 			.type = "lp8557",
674 			.addr = 0x2c,
675 			.dev_name = "lp8557",
676 			.platform_data = &lenovo_lp8557_reg_only_pdata,
677 		},
678 		.adapter_path = "\\_SB_.PCI0.I2C1",
679 	}
680 };
681 
682 /*
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.
693  */
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 },
699 };
700 
701 /* YT3 WM5102 arizona_micd_config comes from Android kernel sources */
702 static struct arizona_micd_config lenovo_yt3_wm5102_micd_config[] = {
703 	{ 0, 1, 0 },
704 	{ ARIZONA_ACCDET_SRC, 2, 1 },
705 };
706 
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,
713 
714 	/* Below settings come from Android kernel sources */
715 	.micd_bias_start_time = 1,
716 	.micd_rate = 6,
717 	.micd_configs = lenovo_yt3_wm5102_micd_config,
718 	.num_micd_configs = ARRAY_SIZE(lenovo_yt3_wm5102_micd_config),
719 	.micbias = {
720 		[0] = { /* MICBIAS1 */
721 			.mV = 2800,
722 			.ext_cap = 1,
723 			.discharge = 1,
724 			.soft_start = 0,
725 			.bypass = 0,
726 		},
727 		[1] = { /* MICBIAS2 */
728 			.mV = 2800,
729 			.ext_cap = 1,
730 			.discharge = 1,
731 			.soft_start = 0,
732 			.bypass = 0,
733 		},
734 		[2] = { /* MICBIAS2 */
735 			.mV = 2800,
736 			.ext_cap = 1,
737 			.discharge = 1,
738 			.soft_start = 0,
739 			.bypass = 0,
740 		},
741 	},
742 };
743 
744 static const struct x86_spi_dev_info lenovo_yt3_spi_devs[] __initconst = {
745 	{
746 		/* WM5102 codec */
747 		.board_info = {
748 			.modalias = "wm5102",
749 			.platform_data = &lenovo_yt3_wm5102_pdata,
750 			.max_speed_hz = 5000000,
751 		},
752 		.ctrl_path = "\\_SB_.PCI0.SPI1",
753 		.irq_data = {
754 			.type = X86_ACPI_IRQ_TYPE_GPIOINT,
755 			.chip = "INT33FF:00",
756 			.index = 91,
757 			.trigger = ACPI_LEVEL_SENSITIVE,
758 			.polarity = ACPI_ACTIVE_LOW,
759 			.con_id = "wm5102_irq",
760 		},
761 	}
762 };
763 
764 static int __init lenovo_yt3_init(void)
765 {
766 	int ret;
767 
768 	/*
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.
772 	 *
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.
778 	 */
779 
780 	/* /CE pin */
781 	ret = x86_android_tablet_get_gpiod("INT33FF:02", 22, "bq25892_0_ce",
782 					   true, GPIOD_OUT_HIGH, NULL);
783 	if (ret < 0)
784 		return ret;
785 
786 	/* OTG pin */
787 	ret = x86_android_tablet_get_gpiod("INT33FF:03", 19, "bq25892_0_otg",
788 					   false, GPIOD_OUT_LOW, NULL);
789 	if (ret < 0)
790 		return ret;
791 
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);
795 
796 	return 0;
797 }
798 
799 static struct gpiod_lookup_table lenovo_yt3_hideep_gpios = {
800 	.dev_id = "i2c-hideep_ts",
801 	.table = {
802 		GPIO_LOOKUP("INT33FF:00", 7, "reset", GPIO_ACTIVE_LOW),
803 		{ }
804 	},
805 };
806 
807 static struct gpiod_lookup_table lenovo_yt3_wm5102_gpios = {
808 	.dev_id = "spi1.0",
809 	.table = {
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),
814 		{ }
815 	},
816 };
817 
818 static struct gpiod_lookup_table * const lenovo_yt3_gpios[] = {
819 	&lenovo_yt3_hideep_gpios,
820 	&lenovo_yt3_wm5102_gpios,
821 	NULL
822 };
823 
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,
831 };
832