Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  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 */
 51static struct lp855x_platform_data lenovo_lp8557_pwm_and_reg_pdata = {
 52	.device_control = 0x86,
 53	.initial_brightness = 128,
 54};
 55
 56static 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
 63static 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
 69static 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 */
 82static 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
 90static const struct software_node lenovo_yb1_x90_hideep_ts_node = {
 91	.properties = lenovo_yb1_x90_hideep_ts_props,
 92};
 93
 94static 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
167static 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 */
178static 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
187static 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
200static 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
209static 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
217static 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
225static 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
232static 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
251const 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 */
265static 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
278const 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 */
284static 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
292static const struct software_node lenovo_yoga_tab2_830_1050_bq24190_node = {
293	.properties = lenovo_yoga_tab2_830_1050_bq24190_props,
294};
295
296static 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() */
310static struct rmi_device_platform_data lenovo_yoga_tab2_830_1050_rmi_pdata = { };
311
312static 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
386static 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
397static 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
408static 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
414static int __init lenovo_yoga_tab2_830_1050_init(void);
415static void lenovo_yoga_tab2_830_1050_exit(void);
416
417const 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 */
438static const char * const lenovo_yoga_tab2_830_lms303d_mount_matrix[] = {
439	"0", "1", "0",
440	"-1", "0", "0",
441	"0", "0", "1"
442};
443
444static 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
449static const struct software_node lenovo_yoga_tab2_830_lms303d_node = {
450	.properties = lenovo_yoga_tab2_830_lms303d_props,
451};
452
453static 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 */
479static 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
483static struct pinctrl *lenovo_yoga_tab2_830_1050_codec_pinctrl;
484static struct sys_off_handler *lenovo_yoga_tab2_830_1050_sys_off_handler;
485
486static 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
515err_unregister_mappings:
516	pinctrl_unregister_mappings(&lenovo_yoga_tab2_830_1050_codec_pinctrl_map);
517err_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 */
529static 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
536static 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
558static 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 */
574static const char * const lenovo_yt3_bq25892_0_suppliers[] = { "cht_wcove_pwrsrc" };
575static const char * const bq25890_1_psy[] = { "bq25890-charger-1" };
576
577static const struct property_entry fg_bq25890_1_supply_props[] = {
578	PROPERTY_ENTRY_STRING_ARRAY("supplied-from", bq25890_1_psy),
579	{ }
580};
581
582static 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 */
587static 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
603static const struct software_node lenovo_yt3_bq25892_0_node = {
604	.properties = lenovo_yt3_bq25892_0_props,
605};
606
607static 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
614static const struct software_node lenovo_yt3_hideep_ts_node = {
615	.properties = lenovo_yt3_hideep_ts_props,
616};
617
618static 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 */
695static 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 */
703static struct arizona_micd_config lenovo_yt3_wm5102_micd_config[] = {
704	{ 0, 1, 0 },
705	{ ARIZONA_ACCDET_SRC, 2, 1 },
706};
707
708static 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
745static 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
765static 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
800static 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
808static 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
819static struct gpiod_lookup_table * const lenovo_yt3_gpios[] = {
820	&lenovo_yt3_hideep_gpios,
821	&lenovo_yt3_wm5102_gpios,
822	NULL
823};
824
825const 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};