]> Git Repo - linux.git/blob - drivers/platform/x86/x86-android-tablets/lenovo.c
net: wan: Add framer framework support
[linux.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 <[email protected]>
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/intel_soc_pmic.h>
16 #include <linux/pinctrl/consumer.h>
17 #include <linux/pinctrl/machine.h>
18 #include <linux/platform_data/lp855x.h>
19 #include <linux/platform_device.h>
20 #include <linux/reboot.h>
21 #include <linux/rmi.h>
22 #include <linux/spi/spi.h>
23
24 #include "shared-psy-info.h"
25 #include "x86-android-tablets.h"
26
27 /*
28  * Various Lenovo models use a TI LP8557 LED backlight controller with its PWM
29  * input connected to a PWM output coming from the LCD panel's controller.
30  * The Android kernels have a hack in the i915 driver to write a non-standard
31  * panel specific DSI register to set the duty-cycle of the LCD's PWM output.
32  *
33  * To avoid having to have a similar hack in the mainline kernel program the
34  * LP8557 to directly set the level and use the lp855x_bl driver for control.
35  */
36 static struct lp855x_platform_data lenovo_lp8557_pdata = {
37         .device_control = 0x86,
38         .initial_brightness = 128,
39 };
40
41 /* Lenovo Yoga Book X90F / X90L's Android factory img has everything hardcoded */
42
43 static const struct property_entry lenovo_yb1_x90_wacom_props[] = {
44         PROPERTY_ENTRY_U32("hid-descr-addr", 0x0001),
45         PROPERTY_ENTRY_U32("post-reset-deassert-delay-ms", 150),
46         { }
47 };
48
49 static const struct software_node lenovo_yb1_x90_wacom_node = {
50         .properties = lenovo_yb1_x90_wacom_props,
51 };
52
53 /*
54  * The HiDeep IST940E touchscreen comes up in I2C-HID mode. The native protocol
55  * reports ABS_MT_PRESSURE and ABS_MT_TOUCH_MAJOR which are not reported in HID
56  * mode, so using native mode is preferred.
57  * It could alternatively be used in HID mode by changing the properties to:
58  *      PROPERTY_ENTRY_U32("hid-descr-addr", 0x0020),
59  *      PROPERTY_ENTRY_U32("post-reset-deassert-delay-ms", 120),
60  * and changing board_info.type to "hid-over-i2c".
61  */
62 static const struct property_entry lenovo_yb1_x90_hideep_ts_props[] = {
63         PROPERTY_ENTRY_U32("touchscreen-size-x", 1200),
64         PROPERTY_ENTRY_U32("touchscreen-size-y", 1920),
65         PROPERTY_ENTRY_U32("touchscreen-max-pressure", 16384),
66         PROPERTY_ENTRY_BOOL("hideep,force-native-protocol"),
67         { }
68 };
69
70 static const struct software_node lenovo_yb1_x90_hideep_ts_node = {
71         .properties = lenovo_yb1_x90_hideep_ts_props,
72 };
73
74 static const struct x86_i2c_client_info lenovo_yb1_x90_i2c_clients[] __initconst = {
75         {
76                 /* BQ27542 fuel-gauge */
77                 .board_info = {
78                         .type = "bq27542",
79                         .addr = 0x55,
80                         .dev_name = "bq27542",
81                         .swnode = &fg_bq25890_supply_node,
82                 },
83                 .adapter_path = "\\_SB_.PCI0.I2C1",
84         }, {
85                 /* Goodix Touchscreen in keyboard half */
86                 .board_info = {
87                         .type = "GDIX1001:00",
88                         .addr = 0x14,
89                         .dev_name = "goodix_ts",
90                 },
91                 .adapter_path = "\\_SB_.PCI0.I2C2",
92                 .irq_data = {
93                         .type = X86_ACPI_IRQ_TYPE_GPIOINT,
94                         .chip = "INT33FF:01",
95                         .index = 56,
96                         .trigger = ACPI_EDGE_SENSITIVE,
97                         .polarity = ACPI_ACTIVE_LOW,
98                         .con_id = "goodix_ts_irq",
99                 },
100         }, {
101                 /* Wacom Digitizer in keyboard half */
102                 .board_info = {
103                         .type = "hid-over-i2c",
104                         .addr = 0x09,
105                         .dev_name = "wacom",
106                         .swnode = &lenovo_yb1_x90_wacom_node,
107                 },
108                 .adapter_path = "\\_SB_.PCI0.I2C4",
109                 .irq_data = {
110                         .type = X86_ACPI_IRQ_TYPE_GPIOINT,
111                         .chip = "INT33FF:01",
112                         .index = 49,
113                         .trigger = ACPI_LEVEL_SENSITIVE,
114                         .polarity = ACPI_ACTIVE_LOW,
115                         .con_id = "wacom_irq",
116                 },
117         }, {
118                 /* LP8557 Backlight controller */
119                 .board_info = {
120                         .type = "lp8557",
121                         .addr = 0x2c,
122                         .dev_name = "lp8557",
123                         .platform_data = &lenovo_lp8557_pdata,
124                 },
125                 .adapter_path = "\\_SB_.PCI0.I2C4",
126         }, {
127                 /* HiDeep IST940E Touchscreen in display half */
128                 .board_info = {
129                         .type = "hideep_ts",
130                         .addr = 0x6c,
131                         .dev_name = "hideep_ts",
132                         .swnode = &lenovo_yb1_x90_hideep_ts_node,
133                 },
134                 .adapter_path = "\\_SB_.PCI0.I2C6",
135                 .irq_data = {
136                         .type = X86_ACPI_IRQ_TYPE_GPIOINT,
137                         .chip = "INT33FF:03",
138                         .index = 77,
139                         .trigger = ACPI_LEVEL_SENSITIVE,
140                         .polarity = ACPI_ACTIVE_LOW,
141                         .con_id = "hideep_ts_irq",
142                 },
143         },
144 };
145
146 static const struct platform_device_info lenovo_yb1_x90_pdevs[] __initconst = {
147         {
148                 .name = "yogabook-touch-kbd-digitizer-switch",
149                 .id = PLATFORM_DEVID_NONE,
150         },
151 };
152
153 /*
154  * DSDT says UART path is "\\_SB.PCIO.URT1" with a letter 'O' instead of
155  * the number '0' add the link manually.
156  */
157 static const struct x86_serdev_info lenovo_yb1_x90_serdevs[] __initconst = {
158         {
159                 .ctrl_hid = "8086228A",
160                 .ctrl_uid = "1",
161                 .ctrl_devname = "serial0",
162                 .serdev_hid = "BCM2E1A",
163         },
164 };
165
166 static const struct x86_gpio_button lenovo_yb1_x90_lid __initconst = {
167         .button = {
168                 .code = SW_LID,
169                 .active_low = true,
170                 .desc = "lid_sw",
171                 .type = EV_SW,
172                 .wakeup = true,
173                 .debounce_interval = 50,
174         },
175         .chip = "INT33FF:02",
176         .pin = 19,
177 };
178
179 static struct gpiod_lookup_table lenovo_yb1_x90_goodix_gpios = {
180         .dev_id = "i2c-goodix_ts",
181         .table = {
182                 GPIO_LOOKUP("INT33FF:01", 53, "reset", GPIO_ACTIVE_HIGH),
183                 GPIO_LOOKUP("INT33FF:01", 56, "irq", GPIO_ACTIVE_HIGH),
184                 { }
185         },
186 };
187
188 static struct gpiod_lookup_table lenovo_yb1_x90_hideep_gpios = {
189         .dev_id = "i2c-hideep_ts",
190         .table = {
191                 GPIO_LOOKUP("INT33FF:00", 7, "reset", GPIO_ACTIVE_LOW),
192                 { }
193         },
194 };
195
196 static struct gpiod_lookup_table lenovo_yb1_x90_wacom_gpios = {
197         .dev_id = "i2c-wacom",
198         .table = {
199                 GPIO_LOOKUP("INT33FF:00", 82, "reset", GPIO_ACTIVE_LOW),
200                 { }
201         },
202 };
203
204 static struct gpiod_lookup_table * const lenovo_yb1_x90_gpios[] = {
205         &lenovo_yb1_x90_hideep_gpios,
206         &lenovo_yb1_x90_goodix_gpios,
207         &lenovo_yb1_x90_wacom_gpios,
208         NULL
209 };
210
211 static int __init lenovo_yb1_x90_init(void)
212 {
213         /* Enable the regulators used by the touchscreens */
214
215         /* Vprog3B 3.0V used by the goodix touchscreen in the keyboard half */
216         intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0x9b, 0x02, 0xff);
217
218         /* Vprog4D 3.0V used by the HiDeep touchscreen in the display half */
219         intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0x9f, 0x02, 0xff);
220
221         /* Vprog5A 1.8V used by the HiDeep touchscreen in the display half */
222         intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0xa0, 0x02, 0xff);
223
224         /* Vprog5B 1.8V used by the goodix touchscreen in the keyboard half */
225         intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0xa1, 0x02, 0xff);
226
227         return 0;
228 }
229
230 const struct x86_dev_info lenovo_yogabook_x90_info __initconst = {
231         .i2c_client_info = lenovo_yb1_x90_i2c_clients,
232         .i2c_client_count = ARRAY_SIZE(lenovo_yb1_x90_i2c_clients),
233         .pdev_info = lenovo_yb1_x90_pdevs,
234         .pdev_count = ARRAY_SIZE(lenovo_yb1_x90_pdevs),
235         .serdev_info = lenovo_yb1_x90_serdevs,
236         .serdev_count = ARRAY_SIZE(lenovo_yb1_x90_serdevs),
237         .gpio_button = &lenovo_yb1_x90_lid,
238         .gpio_button_count = 1,
239         .gpiod_lookup_tables = lenovo_yb1_x90_gpios,
240         .init = lenovo_yb1_x90_init,
241 };
242
243 /* Lenovo Yoga Book X91F/L Windows tablet needs manual instantiation of the fg client */
244 static const struct x86_i2c_client_info lenovo_yogabook_x91_i2c_clients[] __initconst = {
245         {
246                 /* BQ27542 fuel-gauge */
247                 .board_info = {
248                         .type = "bq27542",
249                         .addr = 0x55,
250                         .dev_name = "bq27542",
251                         .swnode = &fg_bq25890_supply_node,
252                 },
253                 .adapter_path = "\\_SB_.PCI0.I2C1",
254         },
255 };
256
257 const struct x86_dev_info lenovo_yogabook_x91_info __initconst = {
258         .i2c_client_info = lenovo_yogabook_x91_i2c_clients,
259         .i2c_client_count = ARRAY_SIZE(lenovo_yogabook_x91_i2c_clients),
260 };
261
262 /* Lenovo Yoga Tablet 2 1050F/L's Android factory img has everything hardcoded */
263 static const struct property_entry lenovo_yoga_tab2_830_1050_bq24190_props[] = {
264         PROPERTY_ENTRY_STRING_ARRAY_LEN("supplied-from", tusb1211_chg_det_psy, 1),
265         PROPERTY_ENTRY_REF("monitored-battery", &generic_lipo_hv_4v35_battery_node),
266         PROPERTY_ENTRY_BOOL("omit-battery-class"),
267         PROPERTY_ENTRY_BOOL("disable-reset"),
268         { }
269 };
270
271 static const struct software_node lenovo_yoga_tab2_830_1050_bq24190_node = {
272         .properties = lenovo_yoga_tab2_830_1050_bq24190_props,
273 };
274
275 static const struct x86_gpio_button lenovo_yoga_tab2_830_1050_lid __initconst = {
276         .button = {
277                 .code = SW_LID,
278                 .active_low = true,
279                 .desc = "lid_sw",
280                 .type = EV_SW,
281                 .wakeup = true,
282                 .debounce_interval = 50,
283         },
284         .chip = "INT33FC:02",
285         .pin = 26,
286 };
287
288 /* This gets filled by lenovo_yoga_tab2_830_1050_init() */
289 static struct rmi_device_platform_data lenovo_yoga_tab2_830_1050_rmi_pdata = { };
290
291 static struct x86_i2c_client_info lenovo_yoga_tab2_830_1050_i2c_clients[] __initdata = {
292         {
293                 /*
294                  * This must be the first entry because lenovo_yoga_tab2_830_1050_init()
295                  * may update its swnode. LSM303DA accelerometer + magnetometer.
296                  */
297                 .board_info = {
298                         .type = "lsm303d",
299                         .addr = 0x1d,
300                         .dev_name = "lsm303d",
301                 },
302                 .adapter_path = "\\_SB_.I2C5",
303         }, {
304                 /* AL3320A ambient light sensor */
305                 .board_info = {
306                         .type = "al3320a",
307                         .addr = 0x1c,
308                         .dev_name = "al3320a",
309                 },
310                 .adapter_path = "\\_SB_.I2C5",
311         }, {
312                 /* bq24292i battery charger */
313                 .board_info = {
314                         .type = "bq24190",
315                         .addr = 0x6b,
316                         .dev_name = "bq24292i",
317                         .swnode = &lenovo_yoga_tab2_830_1050_bq24190_node,
318                         .platform_data = &bq24190_pdata,
319                 },
320                 .adapter_path = "\\_SB_.I2C1",
321                 .irq_data = {
322                         .type = X86_ACPI_IRQ_TYPE_GPIOINT,
323                         .chip = "INT33FC:02",
324                         .index = 2,
325                         .trigger = ACPI_EDGE_SENSITIVE,
326                         .polarity = ACPI_ACTIVE_HIGH,
327                         .con_id = "bq24292i_irq",
328                 },
329         }, {
330                 /* BQ27541 fuel-gauge */
331                 .board_info = {
332                         .type = "bq27541",
333                         .addr = 0x55,
334                         .dev_name = "bq27541",
335                         .swnode = &fg_bq24190_supply_node,
336                 },
337                 .adapter_path = "\\_SB_.I2C1",
338         }, {
339                 /* Synaptics RMI touchscreen */
340                 .board_info = {
341                         .type = "rmi4_i2c",
342                         .addr = 0x38,
343                         .dev_name = "rmi4_i2c",
344                         .platform_data = &lenovo_yoga_tab2_830_1050_rmi_pdata,
345                 },
346                 .adapter_path = "\\_SB_.I2C6",
347                 .irq_data = {
348                         .type = X86_ACPI_IRQ_TYPE_APIC,
349                         .index = 0x45,
350                         .trigger = ACPI_EDGE_SENSITIVE,
351                         .polarity = ACPI_ACTIVE_HIGH,
352                 },
353         }, {
354                 /* LP8557 Backlight controller */
355                 .board_info = {
356                         .type = "lp8557",
357                         .addr = 0x2c,
358                         .dev_name = "lp8557",
359                         .platform_data = &lenovo_lp8557_pdata,
360                 },
361                 .adapter_path = "\\_SB_.I2C3",
362         },
363 };
364
365 static struct gpiod_lookup_table lenovo_yoga_tab2_830_1050_int3496_gpios = {
366         .dev_id = "intel-int3496",
367         .table = {
368                 GPIO_LOOKUP("INT33FC:02", 1, "mux", GPIO_ACTIVE_LOW),
369                 GPIO_LOOKUP("INT33FC:02", 24, "id", GPIO_ACTIVE_HIGH),
370                 { }
371         },
372 };
373
374 #define LENOVO_YOGA_TAB2_830_1050_CODEC_NAME "spi-10WM5102:00"
375
376 static struct gpiod_lookup_table lenovo_yoga_tab2_830_1050_codec_gpios = {
377         .dev_id = LENOVO_YOGA_TAB2_830_1050_CODEC_NAME,
378         .table = {
379                 GPIO_LOOKUP("gpio_crystalcove", 3, "reset", GPIO_ACTIVE_HIGH),
380                 GPIO_LOOKUP("INT33FC:01", 23, "wlf,ldoena", GPIO_ACTIVE_HIGH),
381                 GPIO_LOOKUP("arizona", 2, "wlf,spkvdd-ena", GPIO_ACTIVE_HIGH),
382                 GPIO_LOOKUP("arizona", 4, "wlf,micd-pol", GPIO_ACTIVE_LOW),
383                 { }
384         },
385 };
386
387 static struct gpiod_lookup_table * const lenovo_yoga_tab2_830_1050_gpios[] = {
388         &lenovo_yoga_tab2_830_1050_int3496_gpios,
389         &lenovo_yoga_tab2_830_1050_codec_gpios,
390         NULL
391 };
392
393 static int __init lenovo_yoga_tab2_830_1050_init(void);
394 static void lenovo_yoga_tab2_830_1050_exit(void);
395
396 const struct x86_dev_info lenovo_yoga_tab2_830_1050_info __initconst = {
397         .i2c_client_info = lenovo_yoga_tab2_830_1050_i2c_clients,
398         .i2c_client_count = ARRAY_SIZE(lenovo_yoga_tab2_830_1050_i2c_clients),
399         .pdev_info = int3496_pdevs,
400         .pdev_count = 1,
401         .gpio_button = &lenovo_yoga_tab2_830_1050_lid,
402         .gpio_button_count = 1,
403         .gpiod_lookup_tables = lenovo_yoga_tab2_830_1050_gpios,
404         .bat_swnode = &generic_lipo_hv_4v35_battery_node,
405         .modules = bq24190_modules,
406         .init = lenovo_yoga_tab2_830_1050_init,
407         .exit = lenovo_yoga_tab2_830_1050_exit,
408 };
409
410 /*
411  * The Lenovo Yoga Tablet 2 830 and 1050 (8" vs 10") versions use the same
412  * mainboard, but the 830 uses a portrait LCD panel with a landscape touchscreen,
413  * requiring the touchscreen driver to adjust the touch-coords to match the LCD.
414  * And requiring the accelerometer to have a mount-matrix set to correct for
415  * the 90° rotation of the LCD vs the frame.
416  */
417 static const char * const lenovo_yoga_tab2_830_lms303d_mount_matrix[] = {
418         "0", "1", "0",
419         "-1", "0", "0",
420         "0", "0", "1"
421 };
422
423 static const struct property_entry lenovo_yoga_tab2_830_lms303d_props[] = {
424         PROPERTY_ENTRY_STRING_ARRAY("mount-matrix", lenovo_yoga_tab2_830_lms303d_mount_matrix),
425         { }
426 };
427
428 static const struct software_node lenovo_yoga_tab2_830_lms303d_node = {
429         .properties = lenovo_yoga_tab2_830_lms303d_props,
430 };
431
432 static int __init lenovo_yoga_tab2_830_1050_init_touchscreen(void)
433 {
434         struct gpio_desc *gpiod;
435         int ret;
436
437         /* Use PMIC GPIO 10 bootstrap pin to differentiate 830 vs 1050 */
438         ret = x86_android_tablet_get_gpiod("gpio_crystalcove", 10, "yoga_bootstrap",
439                                            false, GPIOD_ASIS, &gpiod);
440         if (ret)
441                 return ret;
442
443         ret = gpiod_get_value_cansleep(gpiod);
444         if (ret) {
445                 pr_info("detected Lenovo Yoga Tablet 2 1050F/L\n");
446         } else {
447                 pr_info("detected Lenovo Yoga Tablet 2 830F/L\n");
448                 lenovo_yoga_tab2_830_1050_rmi_pdata.sensor_pdata.axis_align.swap_axes = true;
449                 lenovo_yoga_tab2_830_1050_rmi_pdata.sensor_pdata.axis_align.flip_y = true;
450                 lenovo_yoga_tab2_830_1050_i2c_clients[0].board_info.swnode =
451                         &lenovo_yoga_tab2_830_lms303d_node;
452         }
453
454         return 0;
455 }
456
457 /* SUS (INT33FC:02) pin 6 needs to be configured as pmu_clk for the audio codec */
458 static const struct pinctrl_map lenovo_yoga_tab2_830_1050_codec_pinctrl_map =
459         PIN_MAP_MUX_GROUP(LENOVO_YOGA_TAB2_830_1050_CODEC_NAME, "codec_32khz_clk",
460                           "INT33FC:02", "pmu_clk2_grp", "pmu_clk");
461
462 static struct pinctrl *lenovo_yoga_tab2_830_1050_codec_pinctrl;
463 static struct sys_off_handler *lenovo_yoga_tab2_830_1050_sys_off_handler;
464
465 static int __init lenovo_yoga_tab2_830_1050_init_codec(void)
466 {
467         struct device *codec_dev;
468         struct pinctrl *pinctrl;
469         int ret;
470
471         codec_dev = bus_find_device_by_name(&spi_bus_type, NULL,
472                                             LENOVO_YOGA_TAB2_830_1050_CODEC_NAME);
473         if (!codec_dev) {
474                 pr_err("error cannot find %s device\n", LENOVO_YOGA_TAB2_830_1050_CODEC_NAME);
475                 return -ENODEV;
476         }
477
478         ret = pinctrl_register_mappings(&lenovo_yoga_tab2_830_1050_codec_pinctrl_map, 1);
479         if (ret)
480                 goto err_put_device;
481
482         pinctrl = pinctrl_get_select(codec_dev, "codec_32khz_clk");
483         if (IS_ERR(pinctrl)) {
484                 ret = dev_err_probe(codec_dev, PTR_ERR(pinctrl), "selecting codec_32khz_clk\n");
485                 goto err_unregister_mappings;
486         }
487
488         /* We're done with the codec_dev now */
489         put_device(codec_dev);
490
491         lenovo_yoga_tab2_830_1050_codec_pinctrl = pinctrl;
492         return 0;
493
494 err_unregister_mappings:
495         pinctrl_unregister_mappings(&lenovo_yoga_tab2_830_1050_codec_pinctrl_map);
496 err_put_device:
497         put_device(codec_dev);
498         return ret;
499 }
500
501 /*
502  * These tablet's DSDT does not set acpi_gbl_reduced_hardware, so acpi_power_off
503  * gets used as pm_power_off handler. This causes "poweroff" on these tablets
504  * to hang hard. Requiring pressing the powerbutton for 30 seconds *twice*
505  * followed by a normal 3 second press to recover. Avoid this by doing an EFI
506  * poweroff instead.
507  */
508 static int lenovo_yoga_tab2_830_1050_power_off(struct sys_off_data *data)
509 {
510         efi.reset_system(EFI_RESET_SHUTDOWN, EFI_SUCCESS, 0, NULL);
511
512         return NOTIFY_DONE;
513 }
514
515 static int __init lenovo_yoga_tab2_830_1050_init(void)
516 {
517         int ret;
518
519         ret = lenovo_yoga_tab2_830_1050_init_touchscreen();
520         if (ret)
521                 return ret;
522
523         ret = lenovo_yoga_tab2_830_1050_init_codec();
524         if (ret)
525                 return ret;
526
527         /* SYS_OFF_PRIO_FIRMWARE + 1 so that it runs before acpi_power_off */
528         lenovo_yoga_tab2_830_1050_sys_off_handler =
529                 register_sys_off_handler(SYS_OFF_MODE_POWER_OFF, SYS_OFF_PRIO_FIRMWARE + 1,
530                                          lenovo_yoga_tab2_830_1050_power_off, NULL);
531         if (IS_ERR(lenovo_yoga_tab2_830_1050_sys_off_handler))
532                 return PTR_ERR(lenovo_yoga_tab2_830_1050_sys_off_handler);
533
534         return 0;
535 }
536
537 static void lenovo_yoga_tab2_830_1050_exit(void)
538 {
539         unregister_sys_off_handler(lenovo_yoga_tab2_830_1050_sys_off_handler);
540
541         if (lenovo_yoga_tab2_830_1050_codec_pinctrl) {
542                 pinctrl_put(lenovo_yoga_tab2_830_1050_codec_pinctrl);
543                 pinctrl_unregister_mappings(&lenovo_yoga_tab2_830_1050_codec_pinctrl_map);
544         }
545 }
546
547 /* Lenovo Yoga Tab 3 Pro YT3-X90F */
548
549 /*
550  * There are 2 batteries, with 2 bq27500 fuel-gauges and 2 bq25892 chargers,
551  * "bq25890-charger-1" is instantiated from: drivers/i2c/busses/i2c-cht-wc.c.
552  */
553 static const char * const lenovo_yt3_bq25892_0_suppliers[] = { "cht_wcove_pwrsrc" };
554 static const char * const bq25890_1_psy[] = { "bq25890-charger-1" };
555
556 static const struct property_entry fg_bq25890_1_supply_props[] = {
557         PROPERTY_ENTRY_STRING_ARRAY("supplied-from", bq25890_1_psy),
558         { }
559 };
560
561 static const struct software_node fg_bq25890_1_supply_node = {
562         .properties = fg_bq25890_1_supply_props,
563 };
564
565 /* bq25892 charger settings for the flat lipo battery behind the screen */
566 static const struct property_entry lenovo_yt3_bq25892_0_props[] = {
567         PROPERTY_ENTRY_STRING_ARRAY("supplied-from", lenovo_yt3_bq25892_0_suppliers),
568         PROPERTY_ENTRY_U32("linux,iinlim-percentage", 40),
569         PROPERTY_ENTRY_BOOL("linux,skip-reset"),
570         /* Values taken from Android Factory Image */
571         PROPERTY_ENTRY_U32("ti,charge-current", 2048000),
572         PROPERTY_ENTRY_U32("ti,battery-regulation-voltage", 4352000),
573         PROPERTY_ENTRY_U32("ti,termination-current", 128000),
574         PROPERTY_ENTRY_U32("ti,precharge-current", 128000),
575         PROPERTY_ENTRY_U32("ti,minimum-sys-voltage", 3700000),
576         PROPERTY_ENTRY_U32("ti,boost-voltage", 4998000),
577         PROPERTY_ENTRY_U32("ti,boost-max-current", 500000),
578         PROPERTY_ENTRY_BOOL("ti,use-ilim-pin"),
579         { }
580 };
581
582 static const struct software_node lenovo_yt3_bq25892_0_node = {
583         .properties = lenovo_yt3_bq25892_0_props,
584 };
585
586 static const struct property_entry lenovo_yt3_hideep_ts_props[] = {
587         PROPERTY_ENTRY_U32("touchscreen-size-x", 1600),
588         PROPERTY_ENTRY_U32("touchscreen-size-y", 2560),
589         PROPERTY_ENTRY_U32("touchscreen-max-pressure", 255),
590         { }
591 };
592
593 static const struct software_node lenovo_yt3_hideep_ts_node = {
594         .properties = lenovo_yt3_hideep_ts_props,
595 };
596
597 static const struct x86_i2c_client_info lenovo_yt3_i2c_clients[] __initconst = {
598         {
599                 /* bq27500 fuel-gauge for the flat lipo battery behind the screen */
600                 .board_info = {
601                         .type = "bq27500",
602                         .addr = 0x55,
603                         .dev_name = "bq27500_0",
604                         .swnode = &fg_bq25890_supply_node,
605                 },
606                 .adapter_path = "\\_SB_.PCI0.I2C1",
607         }, {
608                 /* bq25892 charger for the flat lipo battery behind the screen */
609                 .board_info = {
610                         .type = "bq25892",
611                         .addr = 0x6b,
612                         .dev_name = "bq25892_0",
613                         .swnode = &lenovo_yt3_bq25892_0_node,
614                 },
615                 .adapter_path = "\\_SB_.PCI0.I2C1",
616                 .irq_data = {
617                         .type = X86_ACPI_IRQ_TYPE_GPIOINT,
618                         .chip = "INT33FF:01",
619                         .index = 5,
620                         .trigger = ACPI_EDGE_SENSITIVE,
621                         .polarity = ACPI_ACTIVE_LOW,
622                         .con_id = "bq25892_0_irq",
623                 },
624         }, {
625                 /* bq27500 fuel-gauge for the round li-ion cells in the hinge */
626                 .board_info = {
627                         .type = "bq27500",
628                         .addr = 0x55,
629                         .dev_name = "bq27500_1",
630                         .swnode = &fg_bq25890_1_supply_node,
631                 },
632                 .adapter_path = "\\_SB_.PCI0.I2C2",
633         }, {
634                 /* HiDeep IST520E Touchscreen */
635                 .board_info = {
636                         .type = "hideep_ts",
637                         .addr = 0x6c,
638                         .dev_name = "hideep_ts",
639                         .swnode = &lenovo_yt3_hideep_ts_node,
640                 },
641                 .adapter_path = "\\_SB_.PCI0.I2C6",
642                 .irq_data = {
643                         .type = X86_ACPI_IRQ_TYPE_GPIOINT,
644                         .chip = "INT33FF:03",
645                         .index = 77,
646                         .trigger = ACPI_LEVEL_SENSITIVE,
647                         .polarity = ACPI_ACTIVE_LOW,
648                         .con_id = "hideep_ts_irq",
649                 },
650         }, {
651                 /* LP8557 Backlight controller */
652                 .board_info = {
653                         .type = "lp8557",
654                         .addr = 0x2c,
655                         .dev_name = "lp8557",
656                         .platform_data = &lenovo_lp8557_pdata,
657                 },
658                 .adapter_path = "\\_SB_.PCI0.I2C1",
659         }
660 };
661
662 static int __init lenovo_yt3_init(void)
663 {
664         int ret;
665
666         /*
667          * The "bq25892_0" charger IC has its /CE (Charge-Enable) and OTG pins
668          * connected to GPIOs, rather then having them hardwired to the correct
669          * values as is normally done.
670          *
671          * The bq25890_charger driver controls these through I2C, but this only
672          * works if not overridden by the pins. Set these pins here:
673          * 1. Set /CE to 1 to allow charging.
674          * 2. Set OTG to 0 disable V5 boost output since the 5V boost output of
675          *    the main "bq25892_1" charger is used when necessary.
676          */
677
678         /* /CE pin */
679         ret = x86_android_tablet_get_gpiod("INT33FF:02", 22, "bq25892_0_ce",
680                                            true, GPIOD_OUT_HIGH, NULL);
681         if (ret < 0)
682                 return ret;
683
684         /* OTG pin */
685         ret = x86_android_tablet_get_gpiod("INT33FF:03", 19, "bq25892_0_otg",
686                                            false, GPIOD_OUT_LOW, NULL);
687         if (ret < 0)
688                 return ret;
689
690         /* Enable the regulators used by the touchscreen */
691         intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0x9b, 0x02, 0xff);
692         intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0xa0, 0x02, 0xff);
693
694         return 0;
695 }
696
697 static struct gpiod_lookup_table lenovo_yt3_hideep_gpios = {
698         .dev_id = "i2c-hideep_ts",
699         .table = {
700                 GPIO_LOOKUP("INT33FF:00", 7, "reset", GPIO_ACTIVE_LOW),
701                 { }
702         },
703 };
704
705 static struct gpiod_lookup_table * const lenovo_yt3_gpios[] = {
706         &lenovo_yt3_hideep_gpios,
707         NULL
708 };
709
710 const struct x86_dev_info lenovo_yt3_info __initconst = {
711         .i2c_client_info = lenovo_yt3_i2c_clients,
712         .i2c_client_count = ARRAY_SIZE(lenovo_yt3_i2c_clients),
713         .gpiod_lookup_tables = lenovo_yt3_gpios,
714         .init = lenovo_yt3_init,
715 };
This page took 0.076433 seconds and 4 git commands to generate.