Merge tag 'qcom-drivers-for-6.9-2' of https://git.kernel.org/pub/scm/linux/kernel...
[linux-block.git] / drivers / platform / x86 / x86-android-tablets / lenovo.c
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 };