1 /*
2  * Touchscreen driver DMI based configuration code
3  *
4  * Copyright (c) 2017 Red Hat Inc.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * Red Hat authors:
12  * Hans de Goede <hdegoede@redhat.com>
13  */
14 
15 #include <linux/acpi.h>
16 #include <linux/device.h>
17 #include <linux/dmi.h>
18 #include <linux/i2c.h>
19 #include <linux/notifier.h>
20 #include <linux/property.h>
21 #include <linux/string.h>
22 
23 struct ts_dmi_data {
24 	const char *acpi_name;
25 	const struct property_entry *properties;
26 };
27 
28 /* NOTE: Please keep all entries sorted alphabetically */
29 
30 static const struct property_entry chuwi_hi8_props[] = {
31 	PROPERTY_ENTRY_U32("touchscreen-size-x", 1665),
32 	PROPERTY_ENTRY_U32("touchscreen-size-y", 1140),
33 	PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
34 	PROPERTY_ENTRY_BOOL("silead,home-button"),
35 	PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-chuwi-hi8.fw"),
36 	{ }
37 };
38 
39 static const struct ts_dmi_data chuwi_hi8_data = {
40 	.acpi_name      = "MSSL0001:00",
41 	.properties     = chuwi_hi8_props,
42 };
43 
44 static const struct property_entry chuwi_hi8_pro_props[] = {
45 	PROPERTY_ENTRY_U32("touchscreen-size-x", 1728),
46 	PROPERTY_ENTRY_U32("touchscreen-size-y", 1148),
47 	PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
48 	PROPERTY_ENTRY_STRING("firmware-name", "gsl3680-chuwi-hi8-pro.fw"),
49 	PROPERTY_ENTRY_BOOL("silead,home-button"),
50 	{ }
51 };
52 
53 static const struct ts_dmi_data chuwi_hi8_pro_data = {
54 	.acpi_name	= "MSSL1680:00",
55 	.properties	= chuwi_hi8_pro_props,
56 };
57 
58 static const struct property_entry chuwi_vi8_props[] = {
59 	PROPERTY_ENTRY_U32("touchscreen-size-x", 1724),
60 	PROPERTY_ENTRY_U32("touchscreen-size-y", 1140),
61 	PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
62 	PROPERTY_ENTRY_STRING("firmware-name", "gsl3676-chuwi-vi8.fw"),
63 	PROPERTY_ENTRY_U32("silead,max-fingers", 10),
64 	PROPERTY_ENTRY_BOOL("silead,home-button"),
65 	{ }
66 };
67 
68 static const struct ts_dmi_data chuwi_vi8_data = {
69 	.acpi_name      = "MSSL1680:00",
70 	.properties     = chuwi_vi8_props,
71 };
72 
73 static const struct property_entry chuwi_vi10_props[] = {
74 	PROPERTY_ENTRY_U32("touchscreen-min-x", 0),
75 	PROPERTY_ENTRY_U32("touchscreen-min-y", 4),
76 	PROPERTY_ENTRY_U32("touchscreen-size-x", 1858),
77 	PROPERTY_ENTRY_U32("touchscreen-size-y", 1280),
78 	PROPERTY_ENTRY_STRING("firmware-name", "gsl3680-chuwi-vi10.fw"),
79 	PROPERTY_ENTRY_U32("silead,max-fingers", 10),
80 	PROPERTY_ENTRY_BOOL("silead,home-button"),
81 	{ }
82 };
83 
84 static const struct ts_dmi_data chuwi_vi10_data = {
85 	.acpi_name      = "MSSL0002:00",
86 	.properties     = chuwi_vi10_props,
87 };
88 
89 static const struct property_entry connect_tablet9_props[] = {
90 	PROPERTY_ENTRY_U32("touchscreen-min-x", 9),
91 	PROPERTY_ENTRY_U32("touchscreen-min-y", 8),
92 	PROPERTY_ENTRY_U32("touchscreen-size-x", 1664),
93 	PROPERTY_ENTRY_U32("touchscreen-size-y", 878),
94 	PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
95 	PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
96 	PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-connect-tablet9.fw"),
97 	PROPERTY_ENTRY_U32("silead,max-fingers", 10),
98 	{ }
99 };
100 
101 static const struct ts_dmi_data connect_tablet9_data = {
102 	.acpi_name      = "MSSL1680:00",
103 	.properties     = connect_tablet9_props,
104 };
105 
106 static const struct property_entry cube_iwork8_air_props[] = {
107 	PROPERTY_ENTRY_U32("touchscreen-size-x", 1660),
108 	PROPERTY_ENTRY_U32("touchscreen-size-y", 900),
109 	PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
110 	PROPERTY_ENTRY_STRING("firmware-name", "gsl3670-cube-iwork8-air.fw"),
111 	PROPERTY_ENTRY_U32("silead,max-fingers", 10),
112 	{ }
113 };
114 
115 static const struct ts_dmi_data cube_iwork8_air_data = {
116 	.acpi_name	= "MSSL1680:00",
117 	.properties	= cube_iwork8_air_props,
118 };
119 
120 static const struct property_entry cube_knote_i1101_props[] = {
121 	PROPERTY_ENTRY_U32("touchscreen-min-x", 20),
122 	PROPERTY_ENTRY_U32("touchscreen-min-y",  22),
123 	PROPERTY_ENTRY_U32("touchscreen-size-x", 1961),
124 	PROPERTY_ENTRY_U32("touchscreen-size-y", 1513),
125 	PROPERTY_ENTRY_STRING("firmware-name", "gsl3692-cube-knote-i1101.fw"),
126 	PROPERTY_ENTRY_U32("silead,max-fingers", 10),
127 	PROPERTY_ENTRY_BOOL("silead,home-button"),
128 	{ }
129 };
130 
131 static const struct ts_dmi_data cube_knote_i1101_data = {
132 	.acpi_name	= "MSSL1680:00",
133 	.properties	= cube_knote_i1101_props,
134 };
135 
136 static const struct property_entry dexp_ursus_7w_props[] = {
137 	PROPERTY_ENTRY_U32("touchscreen-size-x", 890),
138 	PROPERTY_ENTRY_U32("touchscreen-size-y", 630),
139 	PROPERTY_ENTRY_STRING("firmware-name", "gsl1686-dexp-ursus-7w.fw"),
140 	PROPERTY_ENTRY_U32("silead,max-fingers", 10),
141 	PROPERTY_ENTRY_BOOL("silead,home-button"),
142 	{ }
143 };
144 
145 static const struct ts_dmi_data dexp_ursus_7w_data = {
146 	.acpi_name	= "MSSL1680:00",
147 	.properties	= dexp_ursus_7w_props,
148 };
149 
150 static const struct property_entry digma_citi_e200_props[] = {
151 	PROPERTY_ENTRY_U32("touchscreen-size-x", 1980),
152 	PROPERTY_ENTRY_U32("touchscreen-size-y", 1500),
153 	PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
154 	PROPERTY_ENTRY_STRING("firmware-name",
155 			      "gsl1686-digma_citi_e200.fw"),
156 	PROPERTY_ENTRY_U32("silead,max-fingers", 10),
157 	PROPERTY_ENTRY_BOOL("silead,home-button"),
158 	{ }
159 };
160 
161 static const struct ts_dmi_data digma_citi_e200_data = {
162 	.acpi_name	= "MSSL1680:00",
163 	.properties	= digma_citi_e200_props,
164 };
165 
166 static const struct property_entry gp_electronic_t701_props[] = {
167 	PROPERTY_ENTRY_U32("touchscreen-size-x", 960),
168 	PROPERTY_ENTRY_U32("touchscreen-size-y", 640),
169 	PROPERTY_ENTRY_BOOL("touchscreen-inverted-x"),
170 	PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
171 	PROPERTY_ENTRY_STRING("firmware-name",
172 			      "gsl1680-gp-electronic-t701.fw"),
173 	{ }
174 };
175 
176 static const struct ts_dmi_data gp_electronic_t701_data = {
177 	.acpi_name	= "MSSL1680:00",
178 	.properties	= gp_electronic_t701_props,
179 };
180 
181 static const struct property_entry itworks_tw891_props[] = {
182 	PROPERTY_ENTRY_U32("touchscreen-size-x", 1600),
183 	PROPERTY_ENTRY_U32("touchscreen-size-y", 890),
184 	PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
185 	PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
186 	PROPERTY_ENTRY_STRING("firmware-name", "gsl3670-itworks-tw891.fw"),
187 	{ }
188 };
189 
190 static const struct ts_dmi_data itworks_tw891_data = {
191 	.acpi_name	= "MSSL1680:00",
192 	.properties	= itworks_tw891_props,
193 };
194 
195 static const struct property_entry jumper_ezpad_6_pro_props[] = {
196 	PROPERTY_ENTRY_U32("touchscreen-size-x", 1980),
197 	PROPERTY_ENTRY_U32("touchscreen-size-y", 1500),
198 	PROPERTY_ENTRY_STRING("firmware-name", "gsl3692-jumper-ezpad-6-pro.fw"),
199 	PROPERTY_ENTRY_U32("silead,max-fingers", 10),
200 	PROPERTY_ENTRY_BOOL("silead,home-button"),
201 	{ }
202 };
203 
204 static const struct ts_dmi_data jumper_ezpad_6_pro_data = {
205 	.acpi_name	= "MSSL1680:00",
206 	.properties	= jumper_ezpad_6_pro_props,
207 };
208 
209 static const struct property_entry jumper_ezpad_mini3_props[] = {
210 	PROPERTY_ENTRY_U32("touchscreen-size-x", 1700),
211 	PROPERTY_ENTRY_U32("touchscreen-size-y", 1150),
212 	PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
213 	PROPERTY_ENTRY_STRING("firmware-name", "gsl3676-jumper-ezpad-mini3.fw"),
214 	PROPERTY_ENTRY_U32("silead,max-fingers", 10),
215 	{ }
216 };
217 
218 static const struct ts_dmi_data jumper_ezpad_mini3_data = {
219 	.acpi_name	= "MSSL1680:00",
220 	.properties	= jumper_ezpad_mini3_props,
221 };
222 
223 static const struct property_entry onda_obook_20_plus_props[] = {
224 	PROPERTY_ENTRY_U32("touchscreen-size-x", 1728),
225 	PROPERTY_ENTRY_U32("touchscreen-size-y", 1148),
226 	PROPERTY_ENTRY_BOOL("touchscreen-inverted-x"),
227 	PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
228 	PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
229 	PROPERTY_ENTRY_STRING("firmware-name", "gsl3676-onda-obook-20-plus.fw"),
230 	PROPERTY_ENTRY_U32("silead,max-fingers", 10),
231 	PROPERTY_ENTRY_BOOL("silead,home-button"),
232 	{ }
233 };
234 
235 static const struct ts_dmi_data onda_obook_20_plus_data = {
236 	.acpi_name	= "MSSL1680:00",
237 	.properties	= onda_obook_20_plus_props,
238 };
239 
240 static const struct property_entry onda_v820w_32g_props[] = {
241 	PROPERTY_ENTRY_U32("touchscreen-size-x", 1665),
242 	PROPERTY_ENTRY_U32("touchscreen-size-y", 1140),
243 	PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
244 	PROPERTY_ENTRY_STRING("firmware-name",
245 			      "gsl1680-onda-v820w-32g.fw"),
246 	PROPERTY_ENTRY_U32("silead,max-fingers", 10),
247 	PROPERTY_ENTRY_BOOL("silead,home-button"),
248 	{ }
249 };
250 
251 static const struct ts_dmi_data onda_v820w_32g_data = {
252 	.acpi_name	= "MSSL1680:00",
253 	.properties	= onda_v820w_32g_props,
254 };
255 
256 static const struct property_entry onda_v891w_v1_props[] = {
257 	PROPERTY_ENTRY_U32("touchscreen-min-x", 46),
258 	PROPERTY_ENTRY_U32("touchscreen-min-y",  8),
259 	PROPERTY_ENTRY_U32("touchscreen-size-x", 1676),
260 	PROPERTY_ENTRY_U32("touchscreen-size-y", 1130),
261 	PROPERTY_ENTRY_STRING("firmware-name",
262 			      "gsl3680-onda-v891w-v1.fw"),
263 	PROPERTY_ENTRY_U32("silead,max-fingers", 10),
264 	PROPERTY_ENTRY_BOOL("silead,home-button"),
265 	{ }
266 };
267 
268 static const struct ts_dmi_data onda_v891w_v1_data = {
269 	.acpi_name	= "MSSL1680:00",
270 	.properties	= onda_v891w_v1_props,
271 };
272 
273 static const struct property_entry onda_v891w_v3_props[] = {
274 	PROPERTY_ENTRY_U32("touchscreen-min-x", 35),
275 	PROPERTY_ENTRY_U32("touchscreen-min-y", 15),
276 	PROPERTY_ENTRY_U32("touchscreen-size-x", 1625),
277 	PROPERTY_ENTRY_U32("touchscreen-size-y", 1135),
278 	PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
279 	PROPERTY_ENTRY_STRING("firmware-name",
280 			      "gsl3676-onda-v891w-v3.fw"),
281 	PROPERTY_ENTRY_U32("silead,max-fingers", 10),
282 	PROPERTY_ENTRY_BOOL("silead,home-button"),
283 	{ }
284 };
285 
286 static const struct ts_dmi_data onda_v891w_v3_data = {
287 	.acpi_name	= "MSSL1680:00",
288 	.properties	= onda_v891w_v3_props,
289 };
290 
291 static const struct property_entry pipo_w2s_props[] = {
292 	PROPERTY_ENTRY_U32("touchscreen-size-x", 1660),
293 	PROPERTY_ENTRY_U32("touchscreen-size-y", 880),
294 	PROPERTY_ENTRY_BOOL("touchscreen-inverted-x"),
295 	PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
296 	PROPERTY_ENTRY_STRING("firmware-name",
297 			      "gsl1680-pipo-w2s.fw"),
298 	{ }
299 };
300 
301 static const struct ts_dmi_data pipo_w2s_data = {
302 	.acpi_name	= "MSSL1680:00",
303 	.properties	= pipo_w2s_props,
304 };
305 
306 static const struct property_entry pov_mobii_wintab_p800w_v20_props[] = {
307 	PROPERTY_ENTRY_U32("touchscreen-min-x", 32),
308 	PROPERTY_ENTRY_U32("touchscreen-min-y", 16),
309 	PROPERTY_ENTRY_U32("touchscreen-size-x", 1692),
310 	PROPERTY_ENTRY_U32("touchscreen-size-y", 1146),
311 	PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
312 	PROPERTY_ENTRY_STRING("firmware-name",
313 			      "gsl3680-pov-mobii-wintab-p800w-v20.fw"),
314 	PROPERTY_ENTRY_U32("silead,max-fingers", 10),
315 	PROPERTY_ENTRY_BOOL("silead,home-button"),
316 	{ }
317 };
318 
319 static const struct ts_dmi_data pov_mobii_wintab_p800w_v20_data = {
320 	.acpi_name	= "MSSL1680:00",
321 	.properties	= pov_mobii_wintab_p800w_v20_props,
322 };
323 
324 static const struct property_entry pov_mobii_wintab_p800w_v21_props[] = {
325 	PROPERTY_ENTRY_U32("touchscreen-size-x", 1800),
326 	PROPERTY_ENTRY_U32("touchscreen-size-y", 1150),
327 	PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
328 	PROPERTY_ENTRY_STRING("firmware-name",
329 			      "gsl3692-pov-mobii-wintab-p800w.fw"),
330 	PROPERTY_ENTRY_BOOL("silead,home-button"),
331 	{ }
332 };
333 
334 static const struct ts_dmi_data pov_mobii_wintab_p800w_v21_data = {
335 	.acpi_name	= "MSSL1680:00",
336 	.properties	= pov_mobii_wintab_p800w_v21_props,
337 };
338 
339 static const struct property_entry teclast_x3_plus_props[] = {
340 	PROPERTY_ENTRY_U32("touchscreen-size-x", 1980),
341 	PROPERTY_ENTRY_U32("touchscreen-size-y", 1500),
342 	PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-teclast-x3-plus.fw"),
343 	PROPERTY_ENTRY_U32("silead,max-fingers", 10),
344 	PROPERTY_ENTRY_BOOL("silead,home-button"),
345 	{ }
346 };
347 
348 static const struct ts_dmi_data teclast_x3_plus_data = {
349 	.acpi_name	= "MSSL1680:00",
350 	.properties	= teclast_x3_plus_props,
351 };
352 
353 static const struct property_entry teclast_x98plus2_props[] = {
354 	PROPERTY_ENTRY_U32("touchscreen-size-x", 2048),
355 	PROPERTY_ENTRY_U32("touchscreen-size-y", 1280),
356 	PROPERTY_ENTRY_BOOL("touchscreen-inverted-x"),
357 	PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
358 	PROPERTY_ENTRY_STRING("firmware-name",
359 			      "gsl1686-teclast_x98plus2.fw"),
360 	PROPERTY_ENTRY_U32("silead,max-fingers", 10),
361 	{ }
362 };
363 
364 static const struct ts_dmi_data teclast_x98plus2_data = {
365 	.acpi_name	= "MSSL1680:00",
366 	.properties	= teclast_x98plus2_props,
367 };
368 
369 static const struct property_entry trekstor_primebook_c13_props[] = {
370 	PROPERTY_ENTRY_U32("touchscreen-size-x", 2624),
371 	PROPERTY_ENTRY_U32("touchscreen-size-y", 1920),
372 	PROPERTY_ENTRY_STRING("firmware-name",
373 			      "gsl1680-trekstor-primebook-c13.fw"),
374 	PROPERTY_ENTRY_U32("silead,max-fingers", 10),
375 	PROPERTY_ENTRY_BOOL("silead,home-button"),
376 	{ }
377 };
378 
379 static const struct ts_dmi_data trekstor_primebook_c13_data = {
380 	.acpi_name	= "MSSL1680:00",
381 	.properties	= trekstor_primebook_c13_props,
382 };
383 
384 static const struct property_entry trekstor_surftab_twin_10_1_props[] = {
385 	PROPERTY_ENTRY_U32("touchscreen-size-x", 1900),
386 	PROPERTY_ENTRY_U32("touchscreen-size-y", 1280),
387 	PROPERTY_ENTRY_U32("touchscreen-inverted-y", 1),
388 	PROPERTY_ENTRY_STRING("firmware-name",
389 			      "gsl3670-surftab-twin-10-1-st10432-8.fw"),
390 	PROPERTY_ENTRY_U32("silead,max-fingers", 10),
391 	{ }
392 };
393 
394 static const struct ts_dmi_data trekstor_surftab_twin_10_1_data = {
395 	.acpi_name	= "MSSL1680:00",
396 	.properties	= trekstor_surftab_twin_10_1_props,
397 };
398 
399 static const struct property_entry trekstor_surftab_wintron70_props[] = {
400 	PROPERTY_ENTRY_U32("touchscreen-size-x", 884),
401 	PROPERTY_ENTRY_U32("touchscreen-size-y", 632),
402 	PROPERTY_ENTRY_STRING("firmware-name",
403 			      "gsl1686-surftab-wintron70-st70416-6.fw"),
404 	PROPERTY_ENTRY_U32("silead,max-fingers", 10),
405 	PROPERTY_ENTRY_BOOL("silead,home-button"),
406 	{ }
407 };
408 
409 static const struct ts_dmi_data trekstor_surftab_wintron70_data = {
410 	.acpi_name	= "MSSL1680:00",
411 	.properties	= trekstor_surftab_wintron70_props,
412 };
413 
414 /* NOTE: Please keep this table sorted alphabetically */
415 static const struct dmi_system_id touchscreen_dmi_table[] = {
416 	{
417 		/* Chuwi Hi8 */
418 		.driver_data = (void *)&chuwi_hi8_data,
419 		.matches = {
420 			DMI_MATCH(DMI_SYS_VENDOR, "ilife"),
421 			DMI_MATCH(DMI_PRODUCT_NAME, "S806"),
422 		},
423 	},
424 	{
425 		/* Chuwi Hi8 (H1D_S806_206) */
426 		.driver_data = (void *)&chuwi_hi8_data,
427 		.matches = {
428 			DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
429 			DMI_MATCH(DMI_PRODUCT_NAME, "BayTrail"),
430 			DMI_MATCH(DMI_BIOS_VERSION, "H1D_S806_206"),
431 		},
432 	},
433 	{
434 		/* Chuwi Hi8 Pro (CWI513) */
435 		.driver_data = (void *)&chuwi_hi8_pro_data,
436 		.matches = {
437 			DMI_MATCH(DMI_SYS_VENDOR, "Hampoo"),
438 			DMI_MATCH(DMI_PRODUCT_NAME, "X1D3_C806N"),
439 		},
440 	},
441 	{
442 		/* Chuwi Vi8 (CWI506) */
443 		.driver_data = (void *)&chuwi_vi8_data,
444 		.matches = {
445 			DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
446 			DMI_MATCH(DMI_PRODUCT_NAME, "i86"),
447 			DMI_MATCH(DMI_BIOS_VERSION, "CHUWI.D86JLBNR"),
448 		},
449 	},
450 	{
451 		/* Chuwi Vi10 (CWI505) */
452 		.driver_data = (void *)&chuwi_vi10_data,
453 		.matches = {
454 			DMI_MATCH(DMI_BOARD_VENDOR, "Hampoo"),
455 			DMI_MATCH(DMI_BOARD_NAME, "BYT-PF02"),
456 			DMI_MATCH(DMI_SYS_VENDOR, "ilife"),
457 			DMI_MATCH(DMI_PRODUCT_NAME, "S165"),
458 		},
459 	},
460 	{
461 		/* Connect Tablet 9 */
462 		.driver_data = (void *)&connect_tablet9_data,
463 		.matches = {
464 			DMI_MATCH(DMI_SYS_VENDOR, "Connect"),
465 			DMI_MATCH(DMI_PRODUCT_NAME, "Tablet 9"),
466 		},
467 	},
468 	{
469 		/* CUBE iwork8 Air */
470 		.driver_data = (void *)&cube_iwork8_air_data,
471 		.matches = {
472 			DMI_MATCH(DMI_SYS_VENDOR, "cube"),
473 			DMI_MATCH(DMI_PRODUCT_NAME, "i1-TF"),
474 			DMI_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"),
475 		},
476 	},
477 	{
478 		/* Cube KNote i1101 */
479 		.driver_data = (void *)&cube_knote_i1101_data,
480 		.matches = {
481 			DMI_MATCH(DMI_BOARD_VENDOR, "Hampoo"),
482 			DMI_MATCH(DMI_BOARD_NAME, "L1W6_I1101"),
483 			DMI_MATCH(DMI_SYS_VENDOR, "ALLDOCUBE"),
484 			DMI_MATCH(DMI_PRODUCT_NAME, "i1101"),
485 		},
486 	},
487 	{
488 		/* DEXP Ursus 7W */
489 		.driver_data = (void *)&dexp_ursus_7w_data,
490 		.matches = {
491 			DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
492 			DMI_MATCH(DMI_PRODUCT_NAME, "7W"),
493 		},
494 	},
495 	{
496 		/* Digma Citi E200 */
497 		.driver_data = (void *)&digma_citi_e200_data,
498 		.matches = {
499 			DMI_MATCH(DMI_SYS_VENDOR, "Digma"),
500 			DMI_MATCH(DMI_PRODUCT_NAME, "CITI E200"),
501 			DMI_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"),
502 		},
503 	},
504 	{
505 		/* GP-electronic T701 */
506 		.driver_data = (void *)&gp_electronic_t701_data,
507 		.matches = {
508 			DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
509 			DMI_MATCH(DMI_PRODUCT_NAME, "T701"),
510 			DMI_MATCH(DMI_BIOS_VERSION, "BYT70A.YNCHENG.WIN.007"),
511 		},
512 	},
513 	{
514 		/* I.T.Works TW701 (same hardware as the Trekstor ST70416-6) */
515 		.driver_data = (void *)&trekstor_surftab_wintron70_data,
516 		.matches = {
517 			DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
518 			DMI_MATCH(DMI_PRODUCT_NAME, "i71c"),
519 			DMI_MATCH(DMI_BIOS_VERSION, "itWORKS.G.WI71C.JGBMRB"),
520 		},
521 	},
522 	{
523 		/* I.T.Works TW891 */
524 		.driver_data = (void *)&itworks_tw891_data,
525 		.matches = {
526 			DMI_MATCH(DMI_SYS_VENDOR, "To be filled by O.E.M."),
527 			DMI_MATCH(DMI_PRODUCT_NAME, "TW891"),
528 		},
529 	},
530 	{
531 		/* Jumper EZpad 6 Pro */
532 		.driver_data = (void *)&jumper_ezpad_6_pro_data,
533 		.matches = {
534 			DMI_MATCH(DMI_SYS_VENDOR, "Jumper"),
535 			DMI_MATCH(DMI_PRODUCT_NAME, "EZpad"),
536 			DMI_MATCH(DMI_BIOS_VERSION, "5.12"),
537 			/* Above matches are too generic, add bios-date match */
538 			DMI_MATCH(DMI_BIOS_DATE, "08/18/2017"),
539 		},
540 	},
541 	{
542 		/* Jumper EZpad mini3 */
543 		.driver_data = (void *)&jumper_ezpad_mini3_data,
544 		.matches = {
545 			DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
546 			/* jumperx.T87.KFBNEEA02 with the version-nr dropped */
547 			DMI_MATCH(DMI_BIOS_VERSION, "jumperx.T87.KFBNEEA"),
548 		},
549 	},
550 	{
551 		/* Onda oBook 20 Plus */
552 		.driver_data = (void *)&onda_obook_20_plus_data,
553 		.matches = {
554 			DMI_MATCH(DMI_SYS_VENDOR, "ONDA"),
555 			DMI_MATCH(DMI_PRODUCT_NAME, "OBOOK 20 PLUS"),
556 		},
557 	},
558 	{
559 		/* ONDA V820w DualOS */
560 		.driver_data = (void *)&onda_v820w_32g_data,
561 		.matches = {
562 			DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "ONDA"),
563 			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "V820w DualOS")
564 		},
565 	},
566 	{
567 		/* ONDA V891w revision P891WBEBV1B00 aka v1 */
568 		.driver_data = (void *)&onda_v891w_v1_data,
569 		.matches = {
570 			DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "ONDA"),
571 			DMI_EXACT_MATCH(DMI_BOARD_NAME, "ONDA Tablet"),
572 			DMI_EXACT_MATCH(DMI_BOARD_VERSION, "V001"),
573 			/* Exact match, different versions need different fw */
574 			DMI_EXACT_MATCH(DMI_BIOS_VERSION, "ONDA.W89EBBN08"),
575 		},
576 	},
577 	{
578 		/* ONDA V891w Dual OS P891DCF2V1A01274 64GB */
579 		.driver_data = (void *)&onda_v891w_v3_data,
580 		.matches = {
581 			DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
582 			DMI_MATCH(DMI_PRODUCT_NAME, "ONDA Tablet"),
583 			DMI_MATCH(DMI_BIOS_VERSION, "ONDA.D890HBBNR0A"),
584 		},
585 	},
586 	{
587 		/* Pipo W2S */
588 		.driver_data = (void *)&pipo_w2s_data,
589 		.matches = {
590 			DMI_MATCH(DMI_SYS_VENDOR, "PIPO"),
591 			DMI_MATCH(DMI_PRODUCT_NAME, "W2S"),
592 		},
593 	},
594 	{
595 		/* Ployer Momo7w (same hardware as the Trekstor ST70416-6) */
596 		.driver_data = (void *)&trekstor_surftab_wintron70_data,
597 		.matches = {
598 			DMI_MATCH(DMI_SYS_VENDOR, "Shenzhen PLOYER"),
599 			DMI_MATCH(DMI_PRODUCT_NAME, "MOMO7W"),
600 			/* Exact match, different versions need different fw */
601 			DMI_MATCH(DMI_BIOS_VERSION, "MOMO.G.WI71C.MABMRBA02"),
602 		},
603 	},
604 	{
605 		/* Point of View mobii wintab p800w (v2.0) */
606 		.driver_data = (void *)&pov_mobii_wintab_p800w_v20_data,
607 		.matches = {
608 			DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
609 			DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
610 			DMI_MATCH(DMI_BIOS_VERSION, "3BAIR1014"),
611 			/* Above matches are too generic, add bios-date match */
612 			DMI_MATCH(DMI_BIOS_DATE, "10/24/2014"),
613 		},
614 	},
615 	{
616 		/* Point of View mobii wintab p800w (v2.1) */
617 		.driver_data = (void *)&pov_mobii_wintab_p800w_v21_data,
618 		.matches = {
619 			DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
620 			DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
621 			DMI_MATCH(DMI_BIOS_VERSION, "3BAIR1013"),
622 			/* Above matches are too generic, add bios-date match */
623 			DMI_MATCH(DMI_BIOS_DATE, "08/22/2014"),
624 		},
625 	},
626 	{
627 		/* Teclast X3 Plus */
628 		.driver_data = (void *)&teclast_x3_plus_data,
629 		.matches = {
630 			DMI_MATCH(DMI_SYS_VENDOR, "TECLAST"),
631 			DMI_MATCH(DMI_PRODUCT_NAME, "X3 Plus"),
632 			DMI_MATCH(DMI_BOARD_NAME, "X3 Plus"),
633 		},
634 	},
635 	{
636 		/* Teclast X98 Plus II */
637 		.driver_data = (void *)&teclast_x98plus2_data,
638 		.matches = {
639 			DMI_MATCH(DMI_SYS_VENDOR, "TECLAST"),
640 			DMI_MATCH(DMI_PRODUCT_NAME, "X98 Plus II"),
641 		},
642 	},
643 	{
644 		/* Trekstor Primebook C13 */
645 		.driver_data = (void *)&trekstor_primebook_c13_data,
646 		.matches = {
647 			DMI_MATCH(DMI_SYS_VENDOR, "TREKSTOR"),
648 			DMI_MATCH(DMI_PRODUCT_NAME, "Primebook C13"),
649 		},
650 	},
651 	{
652 		/* TrekStor SurfTab twin 10.1 ST10432-8 */
653 		.driver_data = (void *)&trekstor_surftab_twin_10_1_data,
654 		.matches = {
655 			DMI_MATCH(DMI_SYS_VENDOR, "TrekStor"),
656 			DMI_MATCH(DMI_PRODUCT_NAME, "SurfTab twin 10.1"),
657 		},
658 	},
659 	{
660 		/* Trekstor Surftab Wintron 7.0 ST70416-6 */
661 		.driver_data = (void *)&trekstor_surftab_wintron70_data,
662 		.matches = {
663 			DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
664 			DMI_MATCH(DMI_PRODUCT_NAME, "ST70416-6"),
665 			/* Exact match, different versions need different fw */
666 			DMI_MATCH(DMI_BIOS_VERSION, "TREK.G.WI71C.JGBMRBA04"),
667 		},
668 	},
669 	{
670 		/* Trekstor Surftab Wintron 7.0 ST70416-6, newer BIOS */
671 		.driver_data = (void *)&trekstor_surftab_wintron70_data,
672 		.matches = {
673 			DMI_MATCH(DMI_SYS_VENDOR, "TrekStor"),
674 			DMI_MATCH(DMI_PRODUCT_NAME,
675 					     "SurfTab wintron 7.0 ST70416-6"),
676 			/* Exact match, different versions need different fw */
677 			DMI_MATCH(DMI_BIOS_VERSION, "TREK.G.WI71C.JGBMRBA05"),
678 		},
679 	},
680 	{
681 		/* Yours Y8W81, same case and touchscreen as Chuwi Vi8 */
682 		.driver_data = (void *)&chuwi_vi8_data,
683 		.matches = {
684 			DMI_MATCH(DMI_SYS_VENDOR, "YOURS"),
685 			DMI_MATCH(DMI_PRODUCT_NAME, "Y8W81"),
686 		},
687 	},
688 	{ },
689 };
690 
691 static const struct ts_dmi_data *ts_data;
692 
ts_dmi_add_props(struct i2c_client * client)693 static void ts_dmi_add_props(struct i2c_client *client)
694 {
695 	struct device *dev = &client->dev;
696 	int error;
697 
698 	if (has_acpi_companion(dev) &&
699 	    !strncmp(ts_data->acpi_name, client->name, I2C_NAME_SIZE)) {
700 		error = device_add_properties(dev, ts_data->properties);
701 		if (error)
702 			dev_err(dev, "failed to add properties: %d\n", error);
703 	}
704 }
705 
ts_dmi_notifier_call(struct notifier_block * nb,unsigned long action,void * data)706 static int ts_dmi_notifier_call(struct notifier_block *nb,
707 				       unsigned long action, void *data)
708 {
709 	struct device *dev = data;
710 	struct i2c_client *client;
711 
712 	switch (action) {
713 	case BUS_NOTIFY_ADD_DEVICE:
714 		client = i2c_verify_client(dev);
715 		if (client)
716 			ts_dmi_add_props(client);
717 		break;
718 
719 	default:
720 		break;
721 	}
722 
723 	return 0;
724 }
725 
726 static struct notifier_block ts_dmi_notifier = {
727 	.notifier_call = ts_dmi_notifier_call,
728 };
729 
ts_dmi_init(void)730 static int __init ts_dmi_init(void)
731 {
732 	const struct dmi_system_id *dmi_id;
733 	int error;
734 
735 	dmi_id = dmi_first_match(touchscreen_dmi_table);
736 	if (!dmi_id)
737 		return 0; /* Not an error */
738 
739 	ts_data = dmi_id->driver_data;
740 
741 	error = bus_register_notifier(&i2c_bus_type, &ts_dmi_notifier);
742 	if (error)
743 		pr_err("%s: failed to register i2c bus notifier: %d\n",
744 			__func__, error);
745 
746 	return error;
747 }
748 
749 /*
750  * We are registering out notifier after i2c core is initialized and i2c bus
751  * itself is ready (which happens at postcore initcall level), but before
752  * ACPI starts enumerating devices (at subsys initcall level).
753  */
754 arch_initcall(ts_dmi_init);
755