xref: /linux/drivers/platform/x86/x86-android-tablets/lenovo.c (revision 4b660dbd9ee2059850fd30e0df420ca7a38a1856)
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 			.free_gpio = true,
120 		},
121 	}, {
122 		/* Wacom Digitizer in keyboard half */
123 		.board_info = {
124 			.type = "hid-over-i2c",
125 			.addr = 0x09,
126 			.dev_name = "wacom",
127 			.swnode = &lenovo_yb1_x90_wacom_node,
128 		},
129 		.adapter_path = "\\_SB_.PCI0.I2C4",
130 		.irq_data = {
131 			.type = X86_ACPI_IRQ_TYPE_GPIOINT,
132 			.chip = "INT33FF:01",
133 			.index = 49,
134 			.trigger = ACPI_LEVEL_SENSITIVE,
135 			.polarity = ACPI_ACTIVE_LOW,
136 			.con_id = "wacom_irq",
137 		},
138 	}, {
139 		/* LP8557 Backlight controller */
140 		.board_info = {
141 			.type = "lp8557",
142 			.addr = 0x2c,
143 			.dev_name = "lp8557",
144 			.platform_data = &lenovo_lp8557_pwm_and_reg_pdata,
145 		},
146 		.adapter_path = "\\_SB_.PCI0.I2C4",
147 	}, {
148 		/* HiDeep IST940E Touchscreen in display half */
149 		.board_info = {
150 			.type = "hideep_ts",
151 			.addr = 0x6c,
152 			.dev_name = "hideep_ts",
153 			.swnode = &lenovo_yb1_x90_hideep_ts_node,
154 		},
155 		.adapter_path = "\\_SB_.PCI0.I2C6",
156 		.irq_data = {
157 			.type = X86_ACPI_IRQ_TYPE_GPIOINT,
158 			.chip = "INT33FF:03",
159 			.index = 77,
160 			.trigger = ACPI_LEVEL_SENSITIVE,
161 			.polarity = ACPI_ACTIVE_LOW,
162 			.con_id = "hideep_ts_irq",
163 		},
164 	},
165 };
166 
167 static const struct platform_device_info lenovo_yb1_x90_pdevs[] __initconst = {
168 	{
169 		.name = "yogabook-touch-kbd-digitizer-switch",
170 		.id = PLATFORM_DEVID_NONE,
171 	},
172 };
173 
174 /*
175  * DSDT says UART path is "\\_SB.PCIO.URT1" with a letter 'O' instead of
176  * the number '0' add the link manually.
177  */
178 static const struct x86_serdev_info lenovo_yb1_x90_serdevs[] __initconst = {
179 	{
180 		.ctrl_hid = "8086228A",
181 		.ctrl_uid = "1",
182 		.ctrl_devname = "serial0",
183 		.serdev_hid = "BCM2E1A",
184 	},
185 };
186 
187 static const struct x86_gpio_button lenovo_yb1_x90_lid __initconst = {
188 	.button = {
189 		.code = SW_LID,
190 		.active_low = true,
191 		.desc = "lid_sw",
192 		.type = EV_SW,
193 		.wakeup = true,
194 		.debounce_interval = 50,
195 	},
196 	.chip = "INT33FF:02",
197 	.pin = 19,
198 };
199 
200 static struct gpiod_lookup_table lenovo_yb1_x90_goodix_gpios = {
201 	.dev_id = "i2c-goodix_ts",
202 	.table = {
203 		GPIO_LOOKUP("INT33FF:01", 53, "reset", GPIO_ACTIVE_HIGH),
204 		GPIO_LOOKUP("INT33FF:01", 56, "irq", GPIO_ACTIVE_HIGH),
205 		{ }
206 	},
207 };
208 
209 static struct gpiod_lookup_table lenovo_yb1_x90_hideep_gpios = {
210 	.dev_id = "i2c-hideep_ts",
211 	.table = {
212 		GPIO_LOOKUP("INT33FF:00", 7, "reset", GPIO_ACTIVE_LOW),
213 		{ }
214 	},
215 };
216 
217 static struct gpiod_lookup_table lenovo_yb1_x90_wacom_gpios = {
218 	.dev_id = "i2c-wacom",
219 	.table = {
220 		GPIO_LOOKUP("INT33FF:00", 82, "reset", GPIO_ACTIVE_LOW),
221 		{ }
222 	},
223 };
224 
225 static struct gpiod_lookup_table * const lenovo_yb1_x90_gpios[] = {
226 	&lenovo_yb1_x90_hideep_gpios,
227 	&lenovo_yb1_x90_goodix_gpios,
228 	&lenovo_yb1_x90_wacom_gpios,
229 	NULL
230 };
231 
232 static int __init lenovo_yb1_x90_init(void)
233 {
234 	/* Enable the regulators used by the touchscreens */
235 
236 	/* Vprog3B 3.0V used by the goodix touchscreen in the keyboard half */
237 	intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0x9b, 0x02, 0xff);
238 
239 	/* Vprog4D 3.0V used by the HiDeep touchscreen in the display half */
240 	intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0x9f, 0x02, 0xff);
241 
242 	/* Vprog5A 1.8V used by the HiDeep touchscreen in the display half */
243 	intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0xa0, 0x02, 0xff);
244 
245 	/* Vprog5B 1.8V used by the goodix touchscreen in the keyboard half */
246 	intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0xa1, 0x02, 0xff);
247 
248 	return 0;
249 }
250 
251 const struct x86_dev_info lenovo_yogabook_x90_info __initconst = {
252 	.i2c_client_info = lenovo_yb1_x90_i2c_clients,
253 	.i2c_client_count = ARRAY_SIZE(lenovo_yb1_x90_i2c_clients),
254 	.pdev_info = lenovo_yb1_x90_pdevs,
255 	.pdev_count = ARRAY_SIZE(lenovo_yb1_x90_pdevs),
256 	.serdev_info = lenovo_yb1_x90_serdevs,
257 	.serdev_count = ARRAY_SIZE(lenovo_yb1_x90_serdevs),
258 	.gpio_button = &lenovo_yb1_x90_lid,
259 	.gpio_button_count = 1,
260 	.gpiod_lookup_tables = lenovo_yb1_x90_gpios,
261 	.init = lenovo_yb1_x90_init,
262 };
263 
264 /* Lenovo Yoga Book X91F/L Windows tablet needs manual instantiation of the fg client */
265 static const struct x86_i2c_client_info lenovo_yogabook_x91_i2c_clients[] __initconst = {
266 	{
267 		/* BQ27542 fuel-gauge */
268 		.board_info = {
269 			.type = "bq27542",
270 			.addr = 0x55,
271 			.dev_name = "bq27542",
272 			.swnode = &fg_bq25890_supply_node,
273 		},
274 		.adapter_path = "\\_SB_.PCI0.I2C1",
275 	},
276 };
277 
278 const struct x86_dev_info lenovo_yogabook_x91_info __initconst = {
279 	.i2c_client_info = lenovo_yogabook_x91_i2c_clients,
280 	.i2c_client_count = ARRAY_SIZE(lenovo_yogabook_x91_i2c_clients),
281 };
282 
283 /* Lenovo Yoga Tablet 2 1050F/L's Android factory img has everything hardcoded */
284 static const struct property_entry lenovo_yoga_tab2_830_1050_bq24190_props[] = {
285 	PROPERTY_ENTRY_STRING_ARRAY_LEN("supplied-from", tusb1211_chg_det_psy, 1),
286 	PROPERTY_ENTRY_REF("monitored-battery", &generic_lipo_hv_4v35_battery_node),
287 	PROPERTY_ENTRY_BOOL("omit-battery-class"),
288 	PROPERTY_ENTRY_BOOL("disable-reset"),
289 	{ }
290 };
291 
292 static const struct software_node lenovo_yoga_tab2_830_1050_bq24190_node = {
293 	.properties = lenovo_yoga_tab2_830_1050_bq24190_props,
294 };
295 
296 static const struct x86_gpio_button lenovo_yoga_tab2_830_1050_lid __initconst = {
297 	.button = {
298 		.code = SW_LID,
299 		.active_low = true,
300 		.desc = "lid_sw",
301 		.type = EV_SW,
302 		.wakeup = true,
303 		.debounce_interval = 50,
304 	},
305 	.chip = "INT33FC:02",
306 	.pin = 26,
307 };
308 
309 /* This gets filled by lenovo_yoga_tab2_830_1050_init() */
310 static struct rmi_device_platform_data lenovo_yoga_tab2_830_1050_rmi_pdata = { };
311 
312 static struct x86_i2c_client_info lenovo_yoga_tab2_830_1050_i2c_clients[] __initdata = {
313 	{
314 		/*
315 		 * This must be the first entry because lenovo_yoga_tab2_830_1050_init()
316 		 * may update its swnode. LSM303DA accelerometer + magnetometer.
317 		 */
318 		.board_info = {
319 			.type = "lsm303d",
320 			.addr = 0x1d,
321 			.dev_name = "lsm303d",
322 		},
323 		.adapter_path = "\\_SB_.I2C5",
324 	}, {
325 		/* AL3320A ambient light sensor */
326 		.board_info = {
327 			.type = "al3320a",
328 			.addr = 0x1c,
329 			.dev_name = "al3320a",
330 		},
331 		.adapter_path = "\\_SB_.I2C5",
332 	}, {
333 		/* bq24292i battery charger */
334 		.board_info = {
335 			.type = "bq24190",
336 			.addr = 0x6b,
337 			.dev_name = "bq24292i",
338 			.swnode = &lenovo_yoga_tab2_830_1050_bq24190_node,
339 			.platform_data = &bq24190_pdata,
340 		},
341 		.adapter_path = "\\_SB_.I2C1",
342 		.irq_data = {
343 			.type = X86_ACPI_IRQ_TYPE_GPIOINT,
344 			.chip = "INT33FC:02",
345 			.index = 2,
346 			.trigger = ACPI_EDGE_SENSITIVE,
347 			.polarity = ACPI_ACTIVE_HIGH,
348 			.con_id = "bq24292i_irq",
349 		},
350 	}, {
351 		/* BQ27541 fuel-gauge */
352 		.board_info = {
353 			.type = "bq27541",
354 			.addr = 0x55,
355 			.dev_name = "bq27541",
356 			.swnode = &fg_bq24190_supply_node,
357 		},
358 		.adapter_path = "\\_SB_.I2C1",
359 	}, {
360 		/* Synaptics RMI touchscreen */
361 		.board_info = {
362 			.type = "rmi4_i2c",
363 			.addr = 0x38,
364 			.dev_name = "rmi4_i2c",
365 			.platform_data = &lenovo_yoga_tab2_830_1050_rmi_pdata,
366 		},
367 		.adapter_path = "\\_SB_.I2C6",
368 		.irq_data = {
369 			.type = X86_ACPI_IRQ_TYPE_APIC,
370 			.index = 0x45,
371 			.trigger = ACPI_EDGE_SENSITIVE,
372 			.polarity = ACPI_ACTIVE_HIGH,
373 		},
374 	}, {
375 		/* LP8557 Backlight controller */
376 		.board_info = {
377 			.type = "lp8557",
378 			.addr = 0x2c,
379 			.dev_name = "lp8557",
380 			.platform_data = &lenovo_lp8557_pwm_and_reg_pdata,
381 		},
382 		.adapter_path = "\\_SB_.I2C3",
383 	},
384 };
385 
386 static struct gpiod_lookup_table lenovo_yoga_tab2_830_1050_int3496_gpios = {
387 	.dev_id = "intel-int3496",
388 	.table = {
389 		GPIO_LOOKUP("INT33FC:02", 1, "mux", GPIO_ACTIVE_LOW),
390 		GPIO_LOOKUP("INT33FC:02", 24, "id", GPIO_ACTIVE_HIGH),
391 		{ }
392 	},
393 };
394 
395 #define LENOVO_YOGA_TAB2_830_1050_CODEC_NAME "spi-10WM5102:00"
396 
397 static struct gpiod_lookup_table lenovo_yoga_tab2_830_1050_codec_gpios = {
398 	.dev_id = LENOVO_YOGA_TAB2_830_1050_CODEC_NAME,
399 	.table = {
400 		GPIO_LOOKUP("gpio_crystalcove", 3, "reset", GPIO_ACTIVE_HIGH),
401 		GPIO_LOOKUP("INT33FC:01", 23, "wlf,ldoena", GPIO_ACTIVE_HIGH),
402 		GPIO_LOOKUP("arizona", 2, "wlf,spkvdd-ena", GPIO_ACTIVE_HIGH),
403 		GPIO_LOOKUP("arizona", 4, "wlf,micd-pol", GPIO_ACTIVE_LOW),
404 		{ }
405 	},
406 };
407 
408 static struct gpiod_lookup_table * const lenovo_yoga_tab2_830_1050_gpios[] = {
409 	&lenovo_yoga_tab2_830_1050_int3496_gpios,
410 	&lenovo_yoga_tab2_830_1050_codec_gpios,
411 	NULL
412 };
413 
414 static int __init lenovo_yoga_tab2_830_1050_init(void);
415 static void lenovo_yoga_tab2_830_1050_exit(void);
416 
417 const struct x86_dev_info lenovo_yoga_tab2_830_1050_info __initconst = {
418 	.i2c_client_info = lenovo_yoga_tab2_830_1050_i2c_clients,
419 	.i2c_client_count = ARRAY_SIZE(lenovo_yoga_tab2_830_1050_i2c_clients),
420 	.pdev_info = int3496_pdevs,
421 	.pdev_count = 1,
422 	.gpio_button = &lenovo_yoga_tab2_830_1050_lid,
423 	.gpio_button_count = 1,
424 	.gpiod_lookup_tables = lenovo_yoga_tab2_830_1050_gpios,
425 	.bat_swnode = &generic_lipo_hv_4v35_battery_node,
426 	.modules = bq24190_modules,
427 	.init = lenovo_yoga_tab2_830_1050_init,
428 	.exit = lenovo_yoga_tab2_830_1050_exit,
429 };
430 
431 /*
432  * The Lenovo Yoga Tablet 2 830 and 1050 (8" vs 10") versions use the same
433  * mainboard, but the 830 uses a portrait LCD panel with a landscape touchscreen,
434  * requiring the touchscreen driver to adjust the touch-coords to match the LCD.
435  * And requiring the accelerometer to have a mount-matrix set to correct for
436  * the 90° rotation of the LCD vs the frame.
437  */
438 static const char * const lenovo_yoga_tab2_830_lms303d_mount_matrix[] = {
439 	"0", "1", "0",
440 	"-1", "0", "0",
441 	"0", "0", "1"
442 };
443 
444 static const struct property_entry lenovo_yoga_tab2_830_lms303d_props[] = {
445 	PROPERTY_ENTRY_STRING_ARRAY("mount-matrix", lenovo_yoga_tab2_830_lms303d_mount_matrix),
446 	{ }
447 };
448 
449 static const struct software_node lenovo_yoga_tab2_830_lms303d_node = {
450 	.properties = lenovo_yoga_tab2_830_lms303d_props,
451 };
452 
453 static int __init lenovo_yoga_tab2_830_1050_init_touchscreen(void)
454 {
455 	struct gpio_desc *gpiod;
456 	int ret;
457 
458 	/* Use PMIC GPIO 10 bootstrap pin to differentiate 830 vs 1050 */
459 	ret = x86_android_tablet_get_gpiod("gpio_crystalcove", 10, "yoga_bootstrap",
460 					   false, GPIOD_ASIS, &gpiod);
461 	if (ret)
462 		return ret;
463 
464 	ret = gpiod_get_value_cansleep(gpiod);
465 	if (ret) {
466 		pr_info("detected Lenovo Yoga Tablet 2 1050F/L\n");
467 	} else {
468 		pr_info("detected Lenovo Yoga Tablet 2 830F/L\n");
469 		lenovo_yoga_tab2_830_1050_rmi_pdata.sensor_pdata.axis_align.swap_axes = true;
470 		lenovo_yoga_tab2_830_1050_rmi_pdata.sensor_pdata.axis_align.flip_y = true;
471 		lenovo_yoga_tab2_830_1050_i2c_clients[0].board_info.swnode =
472 			&lenovo_yoga_tab2_830_lms303d_node;
473 	}
474 
475 	return 0;
476 }
477 
478 /* SUS (INT33FC:02) pin 6 needs to be configured as pmu_clk for the audio codec */
479 static const struct pinctrl_map lenovo_yoga_tab2_830_1050_codec_pinctrl_map =
480 	PIN_MAP_MUX_GROUP(LENOVO_YOGA_TAB2_830_1050_CODEC_NAME, "codec_32khz_clk",
481 			  "INT33FC:02", "pmu_clk2_grp", "pmu_clk");
482 
483 static struct pinctrl *lenovo_yoga_tab2_830_1050_codec_pinctrl;
484 static struct sys_off_handler *lenovo_yoga_tab2_830_1050_sys_off_handler;
485 
486 static int __init lenovo_yoga_tab2_830_1050_init_codec(void)
487 {
488 	struct device *codec_dev;
489 	struct pinctrl *pinctrl;
490 	int ret;
491 
492 	codec_dev = bus_find_device_by_name(&spi_bus_type, NULL,
493 					    LENOVO_YOGA_TAB2_830_1050_CODEC_NAME);
494 	if (!codec_dev) {
495 		pr_err("error cannot find %s device\n", LENOVO_YOGA_TAB2_830_1050_CODEC_NAME);
496 		return -ENODEV;
497 	}
498 
499 	ret = pinctrl_register_mappings(&lenovo_yoga_tab2_830_1050_codec_pinctrl_map, 1);
500 	if (ret)
501 		goto err_put_device;
502 
503 	pinctrl = pinctrl_get_select(codec_dev, "codec_32khz_clk");
504 	if (IS_ERR(pinctrl)) {
505 		ret = dev_err_probe(codec_dev, PTR_ERR(pinctrl), "selecting codec_32khz_clk\n");
506 		goto err_unregister_mappings;
507 	}
508 
509 	/* We're done with the codec_dev now */
510 	put_device(codec_dev);
511 
512 	lenovo_yoga_tab2_830_1050_codec_pinctrl = pinctrl;
513 	return 0;
514 
515 err_unregister_mappings:
516 	pinctrl_unregister_mappings(&lenovo_yoga_tab2_830_1050_codec_pinctrl_map);
517 err_put_device:
518 	put_device(codec_dev);
519 	return ret;
520 }
521 
522 /*
523  * These tablet's DSDT does not set acpi_gbl_reduced_hardware, so acpi_power_off
524  * gets used as pm_power_off handler. This causes "poweroff" on these tablets
525  * to hang hard. Requiring pressing the powerbutton for 30 seconds *twice*
526  * followed by a normal 3 second press to recover. Avoid this by doing an EFI
527  * poweroff instead.
528  */
529 static int lenovo_yoga_tab2_830_1050_power_off(struct sys_off_data *data)
530 {
531 	efi.reset_system(EFI_RESET_SHUTDOWN, EFI_SUCCESS, 0, NULL);
532 
533 	return NOTIFY_DONE;
534 }
535 
536 static int __init lenovo_yoga_tab2_830_1050_init(void)
537 {
538 	int ret;
539 
540 	ret = lenovo_yoga_tab2_830_1050_init_touchscreen();
541 	if (ret)
542 		return ret;
543 
544 	ret = lenovo_yoga_tab2_830_1050_init_codec();
545 	if (ret)
546 		return ret;
547 
548 	/* SYS_OFF_PRIO_FIRMWARE + 1 so that it runs before acpi_power_off */
549 	lenovo_yoga_tab2_830_1050_sys_off_handler =
550 		register_sys_off_handler(SYS_OFF_MODE_POWER_OFF, SYS_OFF_PRIO_FIRMWARE + 1,
551 					 lenovo_yoga_tab2_830_1050_power_off, NULL);
552 	if (IS_ERR(lenovo_yoga_tab2_830_1050_sys_off_handler))
553 		return PTR_ERR(lenovo_yoga_tab2_830_1050_sys_off_handler);
554 
555 	return 0;
556 }
557 
558 static void lenovo_yoga_tab2_830_1050_exit(void)
559 {
560 	unregister_sys_off_handler(lenovo_yoga_tab2_830_1050_sys_off_handler);
561 
562 	if (lenovo_yoga_tab2_830_1050_codec_pinctrl) {
563 		pinctrl_put(lenovo_yoga_tab2_830_1050_codec_pinctrl);
564 		pinctrl_unregister_mappings(&lenovo_yoga_tab2_830_1050_codec_pinctrl_map);
565 	}
566 }
567 
568 /* Lenovo Yoga Tab 3 Pro YT3-X90F */
569 
570 /*
571  * There are 2 batteries, with 2 bq27500 fuel-gauges and 2 bq25892 chargers,
572  * "bq25890-charger-1" is instantiated from: drivers/i2c/busses/i2c-cht-wc.c.
573  */
574 static const char * const lenovo_yt3_bq25892_0_suppliers[] = { "cht_wcove_pwrsrc" };
575 static const char * const bq25890_1_psy[] = { "bq25890-charger-1" };
576 
577 static const struct property_entry fg_bq25890_1_supply_props[] = {
578 	PROPERTY_ENTRY_STRING_ARRAY("supplied-from", bq25890_1_psy),
579 	{ }
580 };
581 
582 static const struct software_node fg_bq25890_1_supply_node = {
583 	.properties = fg_bq25890_1_supply_props,
584 };
585 
586 /* bq25892 charger settings for the flat lipo battery behind the screen */
587 static const struct property_entry lenovo_yt3_bq25892_0_props[] = {
588 	PROPERTY_ENTRY_STRING_ARRAY("supplied-from", lenovo_yt3_bq25892_0_suppliers),
589 	PROPERTY_ENTRY_U32("linux,iinlim-percentage", 40),
590 	PROPERTY_ENTRY_BOOL("linux,skip-reset"),
591 	/* Values taken from Android Factory Image */
592 	PROPERTY_ENTRY_U32("ti,charge-current", 2048000),
593 	PROPERTY_ENTRY_U32("ti,battery-regulation-voltage", 4352000),
594 	PROPERTY_ENTRY_U32("ti,termination-current", 128000),
595 	PROPERTY_ENTRY_U32("ti,precharge-current", 128000),
596 	PROPERTY_ENTRY_U32("ti,minimum-sys-voltage", 3700000),
597 	PROPERTY_ENTRY_U32("ti,boost-voltage", 4998000),
598 	PROPERTY_ENTRY_U32("ti,boost-max-current", 500000),
599 	PROPERTY_ENTRY_BOOL("ti,use-ilim-pin"),
600 	{ }
601 };
602 
603 static const struct software_node lenovo_yt3_bq25892_0_node = {
604 	.properties = lenovo_yt3_bq25892_0_props,
605 };
606 
607 static const struct property_entry lenovo_yt3_hideep_ts_props[] = {
608 	PROPERTY_ENTRY_U32("touchscreen-size-x", 1600),
609 	PROPERTY_ENTRY_U32("touchscreen-size-y", 2560),
610 	PROPERTY_ENTRY_U32("touchscreen-max-pressure", 255),
611 	{ }
612 };
613 
614 static const struct software_node lenovo_yt3_hideep_ts_node = {
615 	.properties = lenovo_yt3_hideep_ts_props,
616 };
617 
618 static const struct x86_i2c_client_info lenovo_yt3_i2c_clients[] __initconst = {
619 	{
620 		/* bq27500 fuel-gauge for the flat lipo battery behind the screen */
621 		.board_info = {
622 			.type = "bq27500",
623 			.addr = 0x55,
624 			.dev_name = "bq27500_0",
625 			.swnode = &fg_bq25890_supply_node,
626 		},
627 		.adapter_path = "\\_SB_.PCI0.I2C1",
628 	}, {
629 		/* bq25892 charger for the flat lipo battery behind the screen */
630 		.board_info = {
631 			.type = "bq25892",
632 			.addr = 0x6b,
633 			.dev_name = "bq25892_0",
634 			.swnode = &lenovo_yt3_bq25892_0_node,
635 		},
636 		.adapter_path = "\\_SB_.PCI0.I2C1",
637 		.irq_data = {
638 			.type = X86_ACPI_IRQ_TYPE_GPIOINT,
639 			.chip = "INT33FF:01",
640 			.index = 5,
641 			.trigger = ACPI_EDGE_SENSITIVE,
642 			.polarity = ACPI_ACTIVE_LOW,
643 			.con_id = "bq25892_0_irq",
644 		},
645 	}, {
646 		/* bq27500 fuel-gauge for the round li-ion cells in the hinge */
647 		.board_info = {
648 			.type = "bq27500",
649 			.addr = 0x55,
650 			.dev_name = "bq27500_1",
651 			.swnode = &fg_bq25890_1_supply_node,
652 		},
653 		.adapter_path = "\\_SB_.PCI0.I2C2",
654 	}, {
655 		/* HiDeep IST520E Touchscreen */
656 		.board_info = {
657 			.type = "hideep_ts",
658 			.addr = 0x6c,
659 			.dev_name = "hideep_ts",
660 			.swnode = &lenovo_yt3_hideep_ts_node,
661 		},
662 		.adapter_path = "\\_SB_.PCI0.I2C6",
663 		.irq_data = {
664 			.type = X86_ACPI_IRQ_TYPE_GPIOINT,
665 			.chip = "INT33FF:03",
666 			.index = 77,
667 			.trigger = ACPI_LEVEL_SENSITIVE,
668 			.polarity = ACPI_ACTIVE_LOW,
669 			.con_id = "hideep_ts_irq",
670 		},
671 	}, {
672 		/* LP8557 Backlight controller */
673 		.board_info = {
674 			.type = "lp8557",
675 			.addr = 0x2c,
676 			.dev_name = "lp8557",
677 			.platform_data = &lenovo_lp8557_reg_only_pdata,
678 		},
679 		.adapter_path = "\\_SB_.PCI0.I2C1",
680 	}
681 };
682 
683 /*
684  * The AOSP 3.5 mm Headset: Accessory Specification gives the following values:
685  * Function A Play/Pause:           0 ohm
686  * Function D Voice assistant:    135 ohm
687  * Function B Volume Up           240 ohm
688  * Function C Volume Down         470 ohm
689  * Minimum Mic DC resistance     1000 ohm
690  * Minimum Ear speaker impedance   16 ohm
691  * Note the first max value below must be less then the min. speaker impedance,
692  * to allow CTIA/OMTP detection to work. The other max values are the closest
693  * value from extcon-arizona.c:arizona_micd_levels halfway 2 button resistances.
694  */
695 static const struct arizona_micd_range arizona_micd_aosp_ranges[] = {
696 	{ .max =  11, .key = KEY_PLAYPAUSE },
697 	{ .max = 186, .key = KEY_VOICECOMMAND },
698 	{ .max = 348, .key = KEY_VOLUMEUP },
699 	{ .max = 752, .key = KEY_VOLUMEDOWN },
700 };
701 
702 /* YT3 WM5102 arizona_micd_config comes from Android kernel sources */
703 static struct arizona_micd_config lenovo_yt3_wm5102_micd_config[] = {
704 	{ 0, 1, 0 },
705 	{ ARIZONA_ACCDET_SRC, 2, 1 },
706 };
707 
708 static struct arizona_pdata lenovo_yt3_wm5102_pdata = {
709 	.irq_flags = IRQF_TRIGGER_LOW,
710 	.micd_detect_debounce = 200,
711 	.micd_ranges = arizona_micd_aosp_ranges,
712 	.num_micd_ranges = ARRAY_SIZE(arizona_micd_aosp_ranges),
713 	.hpdet_channel = ARIZONA_ACCDET_MODE_HPL,
714 
715 	/* Below settings come from Android kernel sources */
716 	.micd_bias_start_time = 1,
717 	.micd_rate = 6,
718 	.micd_configs = lenovo_yt3_wm5102_micd_config,
719 	.num_micd_configs = ARRAY_SIZE(lenovo_yt3_wm5102_micd_config),
720 	.micbias = {
721 		[0] = { /* MICBIAS1 */
722 			.mV = 2800,
723 			.ext_cap = 1,
724 			.discharge = 1,
725 			.soft_start = 0,
726 			.bypass = 0,
727 		},
728 		[1] = { /* MICBIAS2 */
729 			.mV = 2800,
730 			.ext_cap = 1,
731 			.discharge = 1,
732 			.soft_start = 0,
733 			.bypass = 0,
734 		},
735 		[2] = { /* MICBIAS2 */
736 			.mV = 2800,
737 			.ext_cap = 1,
738 			.discharge = 1,
739 			.soft_start = 0,
740 			.bypass = 0,
741 		},
742 	},
743 };
744 
745 static const struct x86_spi_dev_info lenovo_yt3_spi_devs[] __initconst = {
746 	{
747 		/* WM5102 codec */
748 		.board_info = {
749 			.modalias = "wm5102",
750 			.platform_data = &lenovo_yt3_wm5102_pdata,
751 			.max_speed_hz = 5000000,
752 		},
753 		.ctrl_path = "\\_SB_.PCI0.SPI1",
754 		.irq_data = {
755 			.type = X86_ACPI_IRQ_TYPE_GPIOINT,
756 			.chip = "INT33FF:00",
757 			.index = 91,
758 			.trigger = ACPI_LEVEL_SENSITIVE,
759 			.polarity = ACPI_ACTIVE_LOW,
760 			.con_id = "wm5102_irq",
761 		},
762 	}
763 };
764 
765 static int __init lenovo_yt3_init(void)
766 {
767 	int ret;
768 
769 	/*
770 	 * The "bq25892_0" charger IC has its /CE (Charge-Enable) and OTG pins
771 	 * connected to GPIOs, rather then having them hardwired to the correct
772 	 * values as is normally done.
773 	 *
774 	 * The bq25890_charger driver controls these through I2C, but this only
775 	 * works if not overridden by the pins. Set these pins here:
776 	 * 1. Set /CE to 1 to allow charging.
777 	 * 2. Set OTG to 0 disable V5 boost output since the 5V boost output of
778 	 *    the main "bq25892_1" charger is used when necessary.
779 	 */
780 
781 	/* /CE pin */
782 	ret = x86_android_tablet_get_gpiod("INT33FF:02", 22, "bq25892_0_ce",
783 					   true, GPIOD_OUT_HIGH, NULL);
784 	if (ret < 0)
785 		return ret;
786 
787 	/* OTG pin */
788 	ret = x86_android_tablet_get_gpiod("INT33FF:03", 19, "bq25892_0_otg",
789 					   false, GPIOD_OUT_LOW, NULL);
790 	if (ret < 0)
791 		return ret;
792 
793 	/* Enable the regulators used by the touchscreen */
794 	intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0x9b, 0x02, 0xff);
795 	intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0xa0, 0x02, 0xff);
796 
797 	return 0;
798 }
799 
800 static struct gpiod_lookup_table lenovo_yt3_hideep_gpios = {
801 	.dev_id = "i2c-hideep_ts",
802 	.table = {
803 		GPIO_LOOKUP("INT33FF:00", 7, "reset", GPIO_ACTIVE_LOW),
804 		{ }
805 	},
806 };
807 
808 static struct gpiod_lookup_table lenovo_yt3_wm5102_gpios = {
809 	.dev_id = "spi1.0",
810 	.table = {
811 		GPIO_LOOKUP("INT33FF:00", 75, "wlf,spkvdd-ena", GPIO_ACTIVE_HIGH),
812 		GPIO_LOOKUP("INT33FF:00", 81, "wlf,ldoena", GPIO_ACTIVE_HIGH),
813 		GPIO_LOOKUP("INT33FF:00", 82, "reset", GPIO_ACTIVE_HIGH),
814 		GPIO_LOOKUP("arizona", 2, "wlf,micd-pol", GPIO_ACTIVE_HIGH),
815 		{ }
816 	},
817 };
818 
819 static struct gpiod_lookup_table * const lenovo_yt3_gpios[] = {
820 	&lenovo_yt3_hideep_gpios,
821 	&lenovo_yt3_wm5102_gpios,
822 	NULL
823 };
824 
825 const struct x86_dev_info lenovo_yt3_info __initconst = {
826 	.i2c_client_info = lenovo_yt3_i2c_clients,
827 	.i2c_client_count = ARRAY_SIZE(lenovo_yt3_i2c_clients),
828 	.spi_dev_info = lenovo_yt3_spi_devs,
829 	.spi_dev_count = ARRAY_SIZE(lenovo_yt3_spi_devs),
830 	.gpiod_lookup_tables = lenovo_yt3_gpios,
831 	.init = lenovo_yt3_init,
832 };
833