1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * DMI based code to deal with broken DSDTs on X86 tablets which ship with |
4 | * Android as (part of) the factory image. 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 | #include <linux/acpi.h> |
12 | #include <linux/gpio/machine.h> |
13 | #include <linux/input.h> |
14 | #include <linux/platform_device.h> |
15 | |
16 | #include "shared-psy-info.h" |
17 | #include "x86-android-tablets.h" |
18 | |
19 | /* Acer Iconia One 7 B1-750 has an Android factory img with everything hardcoded */ |
20 | static const char * const acer_b1_750_mount_matrix[] = { |
21 | "-1" , "0" , "0" , |
22 | "0" , "1" , "0" , |
23 | "0" , "0" , "1" |
24 | }; |
25 | |
26 | static const struct property_entry acer_b1_750_bma250e_props[] = { |
27 | PROPERTY_ENTRY_STRING_ARRAY("mount-matrix" , acer_b1_750_mount_matrix), |
28 | { } |
29 | }; |
30 | |
31 | static const struct software_node acer_b1_750_bma250e_node = { |
32 | .properties = acer_b1_750_bma250e_props, |
33 | }; |
34 | |
35 | static const struct x86_i2c_client_info acer_b1_750_i2c_clients[] __initconst = { |
36 | { |
37 | /* Novatek NVT-ts touchscreen */ |
38 | .board_info = { |
39 | .type = "NVT-ts" , |
40 | .addr = 0x34, |
41 | .dev_name = "NVT-ts" , |
42 | }, |
43 | .adapter_path = "\\_SB_.I2C4" , |
44 | .irq_data = { |
45 | .type = X86_ACPI_IRQ_TYPE_GPIOINT, |
46 | .chip = "INT33FC:02" , |
47 | .index = 3, |
48 | .trigger = ACPI_EDGE_SENSITIVE, |
49 | .polarity = ACPI_ACTIVE_LOW, |
50 | .con_id = "NVT-ts_irq" , |
51 | }, |
52 | }, { |
53 | /* BMA250E accelerometer */ |
54 | .board_info = { |
55 | .type = "bma250e" , |
56 | .addr = 0x18, |
57 | .swnode = &acer_b1_750_bma250e_node, |
58 | }, |
59 | .adapter_path = "\\_SB_.I2C3" , |
60 | .irq_data = { |
61 | .type = X86_ACPI_IRQ_TYPE_GPIOINT, |
62 | .chip = "INT33FC:02" , |
63 | .index = 25, |
64 | .trigger = ACPI_LEVEL_SENSITIVE, |
65 | .polarity = ACPI_ACTIVE_HIGH, |
66 | .con_id = "bma250e_irq" , |
67 | }, |
68 | }, |
69 | }; |
70 | |
71 | static struct gpiod_lookup_table acer_b1_750_nvt_ts_gpios = { |
72 | .dev_id = "i2c-NVT-ts" , |
73 | .table = { |
74 | GPIO_LOOKUP("INT33FC:01" , 26, "reset" , GPIO_ACTIVE_LOW), |
75 | { } |
76 | }, |
77 | }; |
78 | |
79 | static struct gpiod_lookup_table * const acer_b1_750_gpios[] = { |
80 | &acer_b1_750_nvt_ts_gpios, |
81 | &int3496_reference_gpios, |
82 | NULL |
83 | }; |
84 | |
85 | const struct x86_dev_info acer_b1_750_info __initconst = { |
86 | .i2c_client_info = acer_b1_750_i2c_clients, |
87 | .i2c_client_count = ARRAY_SIZE(acer_b1_750_i2c_clients), |
88 | .pdev_info = int3496_pdevs, |
89 | .pdev_count = 1, |
90 | .gpiod_lookup_tables = acer_b1_750_gpios, |
91 | }; |
92 | |
93 | /* |
94 | * Advantech MICA-071 |
95 | * This is a standard Windows tablet, but it has an extra "quick launch" button |
96 | * which is not described in the ACPI tables in anyway. |
97 | * Use the x86-android-tablets infra to create a gpio-button device for this. |
98 | */ |
99 | static const struct x86_gpio_button advantech_mica_071_button __initconst = { |
100 | .button = { |
101 | .code = KEY_PROG1, |
102 | .active_low = true, |
103 | .desc = "prog1_key" , |
104 | .type = EV_KEY, |
105 | .wakeup = false, |
106 | .debounce_interval = 50, |
107 | }, |
108 | .chip = "INT33FC:00" , |
109 | .pin = 2, |
110 | }; |
111 | |
112 | const struct x86_dev_info advantech_mica_071_info __initconst = { |
113 | .gpio_button = &advantech_mica_071_button, |
114 | .gpio_button_count = 1, |
115 | }; |
116 | |
117 | /* |
118 | * When booted with the BIOS set to Android mode the Chuwi Hi8 (CWI509) DSDT |
119 | * contains a whole bunch of bogus ACPI I2C devices and is missing entries |
120 | * for the touchscreen and the accelerometer. |
121 | */ |
122 | static const struct property_entry chuwi_hi8_gsl1680_props[] = { |
123 | PROPERTY_ENTRY_U32("touchscreen-size-x" , 1665), |
124 | PROPERTY_ENTRY_U32("touchscreen-size-y" , 1140), |
125 | PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y" ), |
126 | PROPERTY_ENTRY_BOOL("silead,home-button" ), |
127 | PROPERTY_ENTRY_STRING("firmware-name" , "gsl1680-chuwi-hi8.fw" ), |
128 | { } |
129 | }; |
130 | |
131 | static const struct software_node chuwi_hi8_gsl1680_node = { |
132 | .properties = chuwi_hi8_gsl1680_props, |
133 | }; |
134 | |
135 | static const char * const chuwi_hi8_mount_matrix[] = { |
136 | "1" , "0" , "0" , |
137 | "0" , "-1" , "0" , |
138 | "0" , "0" , "1" |
139 | }; |
140 | |
141 | static const struct property_entry chuwi_hi8_bma250e_props[] = { |
142 | PROPERTY_ENTRY_STRING_ARRAY("mount-matrix" , chuwi_hi8_mount_matrix), |
143 | { } |
144 | }; |
145 | |
146 | static const struct software_node chuwi_hi8_bma250e_node = { |
147 | .properties = chuwi_hi8_bma250e_props, |
148 | }; |
149 | |
150 | static const struct x86_i2c_client_info chuwi_hi8_i2c_clients[] __initconst = { |
151 | { |
152 | /* Silead touchscreen */ |
153 | .board_info = { |
154 | .type = "gsl1680" , |
155 | .addr = 0x40, |
156 | .swnode = &chuwi_hi8_gsl1680_node, |
157 | }, |
158 | .adapter_path = "\\_SB_.I2C4" , |
159 | .irq_data = { |
160 | .type = X86_ACPI_IRQ_TYPE_APIC, |
161 | .index = 0x44, |
162 | .trigger = ACPI_EDGE_SENSITIVE, |
163 | .polarity = ACPI_ACTIVE_HIGH, |
164 | }, |
165 | }, { |
166 | /* BMA250E accelerometer */ |
167 | .board_info = { |
168 | .type = "bma250e" , |
169 | .addr = 0x18, |
170 | .swnode = &chuwi_hi8_bma250e_node, |
171 | }, |
172 | .adapter_path = "\\_SB_.I2C3" , |
173 | .irq_data = { |
174 | .type = X86_ACPI_IRQ_TYPE_GPIOINT, |
175 | .chip = "INT33FC:02" , |
176 | .index = 23, |
177 | .trigger = ACPI_LEVEL_SENSITIVE, |
178 | .polarity = ACPI_ACTIVE_HIGH, |
179 | .con_id = "bma250e_irq" , |
180 | }, |
181 | }, |
182 | }; |
183 | |
184 | static int __init chuwi_hi8_init(void) |
185 | { |
186 | /* |
187 | * Avoid the acpi_unregister_gsi() call in x86_acpi_irq_helper_get() |
188 | * breaking the touchscreen + logging various errors when the Windows |
189 | * BIOS is used. |
190 | */ |
191 | if (acpi_dev_present(hid: "MSSL0001" , NULL, hrv: 1)) |
192 | return -ENODEV; |
193 | |
194 | return 0; |
195 | } |
196 | |
197 | const struct x86_dev_info chuwi_hi8_info __initconst = { |
198 | .i2c_client_info = chuwi_hi8_i2c_clients, |
199 | .i2c_client_count = ARRAY_SIZE(chuwi_hi8_i2c_clients), |
200 | .init = chuwi_hi8_init, |
201 | }; |
202 | |
203 | /* |
204 | * Cyberbook T116 Android version |
205 | * This comes in both Windows and Android versions and even on Android |
206 | * the DSDT is mostly sane. This tablet has 2 extra general purpose buttons |
207 | * in the button row with the power + volume-buttons labeled P and F. |
208 | * Use the x86-android-tablets infra to create a gpio-button device for these. |
209 | */ |
210 | static const struct x86_gpio_button cyberbook_t116_buttons[] __initconst = { |
211 | { |
212 | .button = { |
213 | .code = KEY_PROG1, |
214 | .active_low = true, |
215 | .desc = "prog1_key" , |
216 | .type = EV_KEY, |
217 | .wakeup = false, |
218 | .debounce_interval = 50, |
219 | }, |
220 | .chip = "INT33FF:00" , |
221 | .pin = 30, |
222 | }, |
223 | { |
224 | .button = { |
225 | .code = KEY_PROG2, |
226 | .active_low = true, |
227 | .desc = "prog2_key" , |
228 | .type = EV_KEY, |
229 | .wakeup = false, |
230 | .debounce_interval = 50, |
231 | }, |
232 | .chip = "INT33FF:03" , |
233 | .pin = 48, |
234 | }, |
235 | }; |
236 | |
237 | const struct x86_dev_info cyberbook_t116_info __initconst = { |
238 | .gpio_button = cyberbook_t116_buttons, |
239 | .gpio_button_count = ARRAY_SIZE(cyberbook_t116_buttons), |
240 | }; |
241 | |
242 | #define 0x68 |
243 | #define CZC_EC_ANDROID_KEYS 0x63 |
244 | |
245 | static int __init czc_p10t_init(void) |
246 | { |
247 | /* |
248 | * The device boots up in "Windows 7" mode, when the home button sends a |
249 | * Windows specific key sequence (Left Meta + D) and the second button |
250 | * sends an unknown one while also toggling the Radio Kill Switch. |
251 | * This is a surprising behavior when the second button is labeled "Back". |
252 | * |
253 | * The vendor-supplied Android-x86 build switches the device to a "Android" |
254 | * mode by writing value 0x63 to the I/O port 0x68. This just seems to just |
255 | * set bit 6 on address 0x96 in the EC region; switching the bit directly |
256 | * seems to achieve the same result. It uses a "p10t_switcher" to do the |
257 | * job. It doesn't seem to be able to do anything else, and no other use |
258 | * of the port 0x68 is known. |
259 | * |
260 | * In the Android mode, the home button sends just a single scancode, |
261 | * which can be handled in Linux userspace more reasonably and the back |
262 | * button only sends a scancode without toggling the kill switch. |
263 | * The scancode can then be mapped either to Back or RF Kill functionality |
264 | * in userspace, depending on how the button is labeled on that particular |
265 | * model. |
266 | */ |
267 | outb(CZC_EC_ANDROID_KEYS, CZC_EC_EXTRA_PORT); |
268 | return 0; |
269 | } |
270 | |
271 | const struct x86_dev_info czc_p10t __initconst = { |
272 | .init = czc_p10t_init, |
273 | }; |
274 | |
275 | /* Medion Lifetab S10346 tablets have an Android factory img with everything hardcoded */ |
276 | static const char * const medion_lifetab_s10346_accel_mount_matrix[] = { |
277 | "0" , "1" , "0" , |
278 | "1" , "0" , "0" , |
279 | "0" , "0" , "1" |
280 | }; |
281 | |
282 | static const struct property_entry medion_lifetab_s10346_accel_props[] = { |
283 | PROPERTY_ENTRY_STRING_ARRAY("mount-matrix" , medion_lifetab_s10346_accel_mount_matrix), |
284 | { } |
285 | }; |
286 | |
287 | static const struct software_node medion_lifetab_s10346_accel_node = { |
288 | .properties = medion_lifetab_s10346_accel_props, |
289 | }; |
290 | |
291 | /* Note the LCD panel is mounted upside down, this is correctly indicated in the VBT */ |
292 | static const struct property_entry medion_lifetab_s10346_touchscreen_props[] = { |
293 | PROPERTY_ENTRY_BOOL("touchscreen-inverted-x" ), |
294 | PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y" ), |
295 | { } |
296 | }; |
297 | |
298 | static const struct software_node medion_lifetab_s10346_touchscreen_node = { |
299 | .properties = medion_lifetab_s10346_touchscreen_props, |
300 | }; |
301 | |
302 | static const struct x86_i2c_client_info medion_lifetab_s10346_i2c_clients[] __initconst = { |
303 | { |
304 | /* kxtj21009 accel */ |
305 | .board_info = { |
306 | .type = "kxtj21009" , |
307 | .addr = 0x0f, |
308 | .dev_name = "kxtj21009" , |
309 | .swnode = &medion_lifetab_s10346_accel_node, |
310 | }, |
311 | .adapter_path = "\\_SB_.I2C3" , |
312 | .irq_data = { |
313 | .type = X86_ACPI_IRQ_TYPE_GPIOINT, |
314 | .chip = "INT33FC:02" , |
315 | .index = 23, |
316 | .trigger = ACPI_EDGE_SENSITIVE, |
317 | .polarity = ACPI_ACTIVE_HIGH, |
318 | .con_id = "kxtj21009_irq" , |
319 | }, |
320 | }, { |
321 | /* goodix touchscreen */ |
322 | .board_info = { |
323 | .type = "GDIX1001:00" , |
324 | .addr = 0x14, |
325 | .dev_name = "goodix_ts" , |
326 | .swnode = &medion_lifetab_s10346_touchscreen_node, |
327 | }, |
328 | .adapter_path = "\\_SB_.I2C4" , |
329 | .irq_data = { |
330 | .type = X86_ACPI_IRQ_TYPE_APIC, |
331 | .index = 0x44, |
332 | .trigger = ACPI_EDGE_SENSITIVE, |
333 | .polarity = ACPI_ACTIVE_LOW, |
334 | }, |
335 | }, |
336 | }; |
337 | |
338 | static struct gpiod_lookup_table medion_lifetab_s10346_goodix_gpios = { |
339 | .dev_id = "i2c-goodix_ts" , |
340 | .table = { |
341 | GPIO_LOOKUP("INT33FC:01" , 26, "reset" , GPIO_ACTIVE_HIGH), |
342 | GPIO_LOOKUP("INT33FC:02" , 3, "irq" , GPIO_ACTIVE_HIGH), |
343 | { } |
344 | }, |
345 | }; |
346 | |
347 | static struct gpiod_lookup_table * const medion_lifetab_s10346_gpios[] = { |
348 | &medion_lifetab_s10346_goodix_gpios, |
349 | NULL |
350 | }; |
351 | |
352 | const struct x86_dev_info medion_lifetab_s10346_info __initconst = { |
353 | .i2c_client_info = medion_lifetab_s10346_i2c_clients, |
354 | .i2c_client_count = ARRAY_SIZE(medion_lifetab_s10346_i2c_clients), |
355 | .gpiod_lookup_tables = medion_lifetab_s10346_gpios, |
356 | }; |
357 | |
358 | /* Nextbook Ares 8 (BYT) tablets have an Android factory img with everything hardcoded */ |
359 | static const char * const nextbook_ares8_accel_mount_matrix[] = { |
360 | "0" , "-1" , "0" , |
361 | "-1" , "0" , "0" , |
362 | "0" , "0" , "1" |
363 | }; |
364 | |
365 | static const struct property_entry nextbook_ares8_accel_props[] = { |
366 | PROPERTY_ENTRY_STRING_ARRAY("mount-matrix" , nextbook_ares8_accel_mount_matrix), |
367 | { } |
368 | }; |
369 | |
370 | static const struct software_node nextbook_ares8_accel_node = { |
371 | .properties = nextbook_ares8_accel_props, |
372 | }; |
373 | |
374 | static const struct property_entry nextbook_ares8_touchscreen_props[] = { |
375 | PROPERTY_ENTRY_U32("touchscreen-size-x" , 800), |
376 | PROPERTY_ENTRY_U32("touchscreen-size-y" , 1280), |
377 | { } |
378 | }; |
379 | |
380 | static const struct software_node nextbook_ares8_touchscreen_node = { |
381 | .properties = nextbook_ares8_touchscreen_props, |
382 | }; |
383 | |
384 | static const struct x86_i2c_client_info nextbook_ares8_i2c_clients[] __initconst = { |
385 | { |
386 | /* Freescale MMA8653FC accel */ |
387 | .board_info = { |
388 | .type = "mma8653" , |
389 | .addr = 0x1d, |
390 | .dev_name = "mma8653" , |
391 | .swnode = &nextbook_ares8_accel_node, |
392 | }, |
393 | .adapter_path = "\\_SB_.I2C3" , |
394 | }, { |
395 | /* FT5416DQ9 touchscreen controller */ |
396 | .board_info = { |
397 | .type = "edt-ft5x06" , |
398 | .addr = 0x38, |
399 | .dev_name = "ft5416" , |
400 | .swnode = &nextbook_ares8_touchscreen_node, |
401 | }, |
402 | .adapter_path = "\\_SB_.I2C4" , |
403 | .irq_data = { |
404 | .type = X86_ACPI_IRQ_TYPE_GPIOINT, |
405 | .chip = "INT33FC:02" , |
406 | .index = 3, |
407 | .trigger = ACPI_EDGE_SENSITIVE, |
408 | .polarity = ACPI_ACTIVE_LOW, |
409 | .con_id = "ft5416_irq" , |
410 | }, |
411 | }, |
412 | }; |
413 | |
414 | static struct gpiod_lookup_table * const nextbook_ares8_gpios[] = { |
415 | &int3496_reference_gpios, |
416 | NULL |
417 | }; |
418 | |
419 | const struct x86_dev_info nextbook_ares8_info __initconst = { |
420 | .i2c_client_info = nextbook_ares8_i2c_clients, |
421 | .i2c_client_count = ARRAY_SIZE(nextbook_ares8_i2c_clients), |
422 | .pdev_info = int3496_pdevs, |
423 | .pdev_count = 1, |
424 | .gpiod_lookup_tables = nextbook_ares8_gpios, |
425 | }; |
426 | |
427 | /* Nextbook Ares 8A (CHT) tablets have an Android factory img with everything hardcoded */ |
428 | static const char * const nextbook_ares8a_accel_mount_matrix[] = { |
429 | "1" , "0" , "0" , |
430 | "0" , "-1" , "0" , |
431 | "0" , "0" , "1" |
432 | }; |
433 | |
434 | static const struct property_entry nextbook_ares8a_accel_props[] = { |
435 | PROPERTY_ENTRY_STRING_ARRAY("mount-matrix" , nextbook_ares8a_accel_mount_matrix), |
436 | { } |
437 | }; |
438 | |
439 | static const struct software_node nextbook_ares8a_accel_node = { |
440 | .properties = nextbook_ares8a_accel_props, |
441 | }; |
442 | |
443 | static const struct x86_i2c_client_info nextbook_ares8a_i2c_clients[] __initconst = { |
444 | { |
445 | /* Freescale MMA8653FC accel */ |
446 | .board_info = { |
447 | .type = "mma8653" , |
448 | .addr = 0x1d, |
449 | .dev_name = "mma8653" , |
450 | .swnode = &nextbook_ares8a_accel_node, |
451 | }, |
452 | .adapter_path = "\\_SB_.PCI0.I2C3" , |
453 | }, { |
454 | /* FT5416DQ9 touchscreen controller */ |
455 | .board_info = { |
456 | .type = "edt-ft5x06" , |
457 | .addr = 0x38, |
458 | .dev_name = "ft5416" , |
459 | .swnode = &nextbook_ares8_touchscreen_node, |
460 | }, |
461 | .adapter_path = "\\_SB_.PCI0.I2C6" , |
462 | .irq_data = { |
463 | .type = X86_ACPI_IRQ_TYPE_GPIOINT, |
464 | .chip = "INT33FF:01" , |
465 | .index = 17, |
466 | .trigger = ACPI_EDGE_SENSITIVE, |
467 | .polarity = ACPI_ACTIVE_LOW, |
468 | .con_id = "ft5416_irq" , |
469 | }, |
470 | }, |
471 | }; |
472 | |
473 | static struct gpiod_lookup_table nextbook_ares8a_ft5416_gpios = { |
474 | .dev_id = "i2c-ft5416" , |
475 | .table = { |
476 | GPIO_LOOKUP("INT33FF:01" , 25, "reset" , GPIO_ACTIVE_LOW), |
477 | { } |
478 | }, |
479 | }; |
480 | |
481 | static struct gpiod_lookup_table * const nextbook_ares8a_gpios[] = { |
482 | &nextbook_ares8a_ft5416_gpios, |
483 | NULL |
484 | }; |
485 | |
486 | const struct x86_dev_info nextbook_ares8a_info __initconst = { |
487 | .i2c_client_info = nextbook_ares8a_i2c_clients, |
488 | .i2c_client_count = ARRAY_SIZE(nextbook_ares8a_i2c_clients), |
489 | .gpiod_lookup_tables = nextbook_ares8a_gpios, |
490 | }; |
491 | |
492 | /* |
493 | * Peaq C1010 |
494 | * This is a standard Windows tablet, but it has a special Dolby button. |
495 | * This button has a WMI interface, but that is broken. Instead of trying to |
496 | * use the broken WMI interface, instantiate a gpio_keys device for this. |
497 | */ |
498 | static const struct x86_gpio_button peaq_c1010_button __initconst = { |
499 | .button = { |
500 | .code = KEY_SOUND, |
501 | .active_low = true, |
502 | .desc = "dolby_key" , |
503 | .type = EV_KEY, |
504 | .wakeup = false, |
505 | .debounce_interval = 50, |
506 | }, |
507 | .chip = "INT33FC:00" , |
508 | .pin = 3, |
509 | }; |
510 | |
511 | const struct x86_dev_info peaq_c1010_info __initconst = { |
512 | .gpio_button = &peaq_c1010_button, |
513 | .gpio_button_count = 1, |
514 | }; |
515 | |
516 | /* |
517 | * Whitelabel (sold as various brands) TM800A550L tablets. |
518 | * These tablet's DSDT contains a whole bunch of bogus ACPI I2C devices |
519 | * (removed through acpi_quirk_skip_i2c_client_enumeration()) and |
520 | * the touchscreen fwnode has the wrong GPIOs. |
521 | */ |
522 | static const char * const whitelabel_tm800a550l_accel_mount_matrix[] = { |
523 | "-1" , "0" , "0" , |
524 | "0" , "1" , "0" , |
525 | "0" , "0" , "1" |
526 | }; |
527 | |
528 | static const struct property_entry whitelabel_tm800a550l_accel_props[] = { |
529 | PROPERTY_ENTRY_STRING_ARRAY("mount-matrix" , whitelabel_tm800a550l_accel_mount_matrix), |
530 | { } |
531 | }; |
532 | |
533 | static const struct software_node whitelabel_tm800a550l_accel_node = { |
534 | .properties = whitelabel_tm800a550l_accel_props, |
535 | }; |
536 | |
537 | static const struct property_entry whitelabel_tm800a550l_goodix_props[] = { |
538 | PROPERTY_ENTRY_STRING("firmware-name" , "gt912-tm800a550l.fw" ), |
539 | PROPERTY_ENTRY_STRING("goodix,config-name" , "gt912-tm800a550l.cfg" ), |
540 | PROPERTY_ENTRY_U32("goodix,main-clk" , 54), |
541 | { } |
542 | }; |
543 | |
544 | static const struct software_node whitelabel_tm800a550l_goodix_node = { |
545 | .properties = whitelabel_tm800a550l_goodix_props, |
546 | }; |
547 | |
548 | static const struct x86_i2c_client_info whitelabel_tm800a550l_i2c_clients[] __initconst = { |
549 | { |
550 | /* goodix touchscreen */ |
551 | .board_info = { |
552 | .type = "GDIX1001:00" , |
553 | .addr = 0x14, |
554 | .dev_name = "goodix_ts" , |
555 | .swnode = &whitelabel_tm800a550l_goodix_node, |
556 | }, |
557 | .adapter_path = "\\_SB_.I2C2" , |
558 | .irq_data = { |
559 | .type = X86_ACPI_IRQ_TYPE_APIC, |
560 | .index = 0x44, |
561 | .trigger = ACPI_EDGE_SENSITIVE, |
562 | .polarity = ACPI_ACTIVE_HIGH, |
563 | }, |
564 | }, { |
565 | /* kxcj91008 accel */ |
566 | .board_info = { |
567 | .type = "kxcj91008" , |
568 | .addr = 0x0f, |
569 | .dev_name = "kxcj91008" , |
570 | .swnode = &whitelabel_tm800a550l_accel_node, |
571 | }, |
572 | .adapter_path = "\\_SB_.I2C3" , |
573 | }, |
574 | }; |
575 | |
576 | static struct gpiod_lookup_table whitelabel_tm800a550l_goodix_gpios = { |
577 | .dev_id = "i2c-goodix_ts" , |
578 | .table = { |
579 | GPIO_LOOKUP("INT33FC:01" , 26, "reset" , GPIO_ACTIVE_HIGH), |
580 | GPIO_LOOKUP("INT33FC:02" , 3, "irq" , GPIO_ACTIVE_HIGH), |
581 | { } |
582 | }, |
583 | }; |
584 | |
585 | static struct gpiod_lookup_table * const whitelabel_tm800a550l_gpios[] = { |
586 | &whitelabel_tm800a550l_goodix_gpios, |
587 | NULL |
588 | }; |
589 | |
590 | const struct x86_dev_info whitelabel_tm800a550l_info __initconst = { |
591 | .i2c_client_info = whitelabel_tm800a550l_i2c_clients, |
592 | .i2c_client_count = ARRAY_SIZE(whitelabel_tm800a550l_i2c_clients), |
593 | .gpiod_lookup_tables = whitelabel_tm800a550l_gpios, |
594 | }; |
595 | |
596 | /* |
597 | * If the EFI bootloader is not Xiaomi's own signed Android loader, then the |
598 | * Xiaomi Mi Pad 2 X86 tablet sets OSID in the DSDT to 1 (Windows), causing |
599 | * a bunch of devices to be hidden. |
600 | * |
601 | * This takes care of instantiating the hidden devices manually. |
602 | */ |
603 | static const struct x86_i2c_client_info xiaomi_mipad2_i2c_clients[] __initconst = { |
604 | { |
605 | /* BQ27520 fuel-gauge */ |
606 | .board_info = { |
607 | .type = "bq27520" , |
608 | .addr = 0x55, |
609 | .dev_name = "bq27520" , |
610 | .swnode = &fg_bq25890_supply_node, |
611 | }, |
612 | .adapter_path = "\\_SB_.PCI0.I2C1" , |
613 | }, { |
614 | /* KTD2026 RGB notification LED controller */ |
615 | .board_info = { |
616 | .type = "ktd2026" , |
617 | .addr = 0x30, |
618 | .dev_name = "ktd2026" , |
619 | }, |
620 | .adapter_path = "\\_SB_.PCI0.I2C3" , |
621 | }, |
622 | }; |
623 | |
624 | const struct x86_dev_info xiaomi_mipad2_info __initconst = { |
625 | .i2c_client_info = xiaomi_mipad2_i2c_clients, |
626 | .i2c_client_count = ARRAY_SIZE(xiaomi_mipad2_i2c_clients), |
627 | }; |
628 | |