File Index
Files and directories
Sign in
FILE

drm_panel_orientation_quirks.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/drm_panel_orientation_quirks.c C
  1/* SPDX-License-Identifier: MIT */
  2/*
  3 * drm_panel_orientation_quirks.c -- Quirks for non-normal panel orientation
  4 *
  5 * Copyright (C) 2017 Hans de Goede <hdegoede@redhat.com>
  6 *
  7 * Note the quirks in this file are shared with fbdev/efifb and as such
  8 * must not depend on other drm code.
  9 */
 10
 11#include <linux/dmi.h>
 12#include <linux/export.h>
 13#include <linux/module.h>
 14#include <drm/drm_connector.h>
 15#include <drm/drm_utils.h>
 16
 17#ifdef CONFIG_DMI
 18
 19/*
 20 * Some x86 clamshell design devices use portrait tablet screens and a display
 21 * engine which cannot rotate in hardware, so we need to rotate the fbcon to
 22 * compensate. Unfortunately these (cheap) devices also typically have quite
 23 * generic DMI data, so we match on a combination of DMI data, screen resolution
 24 * and a list of known BIOS dates to avoid false positives.
 25 */
 26
 27struct drm_dmi_panel_orientation_data {
 28	int width;
 29	int height;
 30	const char * const *bios_dates;
 31	int orientation;
 32};
 33
 34static const struct drm_dmi_panel_orientation_data gpd_micropc = {
 35	.width = 720,
 36	.height = 1280,
 37	.bios_dates = (const char * const []){ "04/26/2019",
 38		NULL },
 39	.orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
 40};
 41
 42static const struct drm_dmi_panel_orientation_data gpd_onemix2s = {
 43	.width = 1200,
 44	.height = 1920,
 45	.bios_dates = (const char * const []){ "05/21/2018", "10/26/2018",
 46		"03/04/2019", NULL },
 47	.orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
 48};
 49
 50static const struct drm_dmi_panel_orientation_data gpd_pocket = {
 51	.width = 1200,
 52	.height = 1920,
 53	.bios_dates = (const char * const []){ "05/26/2017", "06/28/2017",
 54		"07/05/2017", "08/07/2017", NULL },
 55	.orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
 56};
 57
 58static const struct drm_dmi_panel_orientation_data gpd_pocket2 = {
 59	.width = 1200,
 60	.height = 1920,
 61	.bios_dates = (const char * const []){ "06/28/2018", "08/28/2018",
 62		"12/07/2018", NULL },
 63	.orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
 64};
 65
 66static const struct drm_dmi_panel_orientation_data gpd_win = {
 67	.width = 720,
 68	.height = 1280,
 69	.bios_dates = (const char * const []){
 70		"10/25/2016", "11/18/2016", "12/23/2016", "12/26/2016",
 71		"02/21/2017", "03/20/2017", "05/25/2017", NULL },
 72	.orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
 73};
 74
 75static const struct drm_dmi_panel_orientation_data gpd_win2 = {
 76	.width = 720,
 77	.height = 1280,
 78	.bios_dates = (const char * const []){
 79		"12/07/2017", "05/24/2018", "06/29/2018", NULL },
 80	.orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
 81};
 82
 83static const struct drm_dmi_panel_orientation_data itworks_tw891 = {
 84	.width = 800,
 85	.height = 1280,
 86	.bios_dates = (const char * const []){ "10/16/2015", NULL },
 87	.orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
 88};
 89
 90static const struct drm_dmi_panel_orientation_data onegx1_pro = {
 91	.width = 1200,
 92	.height = 1920,
 93	.bios_dates = (const char * const []){ "12/17/2020", NULL },
 94	.orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
 95};
 96
 97static const struct drm_dmi_panel_orientation_data lcd640x960_leftside_up = {
 98	.width = 640,
 99	.height = 960,
100	.orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP,
101};
102
103static const struct drm_dmi_panel_orientation_data lcd720x1280_rightside_up = {
104	.width = 720,
105	.height = 1280,
106	.orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
107};
108
109static const struct drm_dmi_panel_orientation_data lcd800x1280_leftside_up = {
110	.width = 800,
111	.height = 1280,
112	.orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP,
113};
114
115static const struct drm_dmi_panel_orientation_data lcd800x1280_rightside_up = {
116	.width = 800,
117	.height = 1280,
118	.orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
119};
120
121static const struct drm_dmi_panel_orientation_data lcd1080x1920_leftside_up = {
122	.width = 1080,
123	.height = 1920,
124	.orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP,
125};
126
127static const struct drm_dmi_panel_orientation_data lcd1080x1920_rightside_up = {
128	.width = 1080,
129	.height = 1920,
130	.orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
131};
132
133static const struct drm_dmi_panel_orientation_data lcd1200x1920_leftside_up = {
134	.width = 1200,
135	.height = 1920,
136	.orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP,
137};
138
139static const struct drm_dmi_panel_orientation_data lcd1200x1920_rightside_up = {
140	.width = 1200,
141	.height = 1920,
142	.orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
143};
144
145static const struct drm_dmi_panel_orientation_data lcd1280x1920_rightside_up = {
146	.width = 1280,
147	.height = 1920,
148	.orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
149};
150
151static const struct drm_dmi_panel_orientation_data lcd1600x2560_leftside_up = {
152	.width = 1600,
153	.height = 2560,
154	.orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP,
155};
156
157static const struct drm_dmi_panel_orientation_data lcd1600x2560_rightside_up = {
158	.width = 1600,
159	.height = 2560,
160	.orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
161};
162
163static const struct dmi_system_id orientation_data[] = {
164	{	/* Acer One 10 (S1003) */
165		.matches = {
166		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Acer"),
167		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "One S1003"),
168		},
169		.driver_data = (void *)&lcd800x1280_rightside_up,
170	}, {	/* Acer Switch V 10 (SW5-017) */
171		.matches = {
172		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Acer"),
173		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "SW5-017"),
174		},
175		.driver_data = (void *)&lcd800x1280_rightside_up,
176	}, {	/* Anbernic Win600 */
177		.matches = {
178		  DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Anbernic"),
179		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Win600"),
180		},
181		.driver_data = (void *)&lcd720x1280_rightside_up,
182	}, {	/* Asus T100HA */
183		.matches = {
184		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
185		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100HAN"),
186		},
187		.driver_data = (void *)&lcd800x1280_leftside_up,
188	}, {	/* Asus T101HA */
189		.matches = {
190		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
191		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T101HA"),
192		},
193		.driver_data = (void *)&lcd800x1280_rightside_up,
194	}, {	/* Asus T103HAF */
195		.matches = {
196		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
197		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T103HAF"),
198		},
199		.driver_data = (void *)&lcd800x1280_rightside_up,
200	}, {	/* AYA NEO AYANEO 2/2S */
201		.matches = {
202		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "AYANEO"),
203		  DMI_MATCH(DMI_PRODUCT_NAME, "AYANEO 2"),
204		},
205		.driver_data = (void *)&lcd1200x1920_rightside_up,
206	}, {	/* AYA NEO 2021 */
207		.matches = {
208		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "AYADEVICE"),
209		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "AYA NEO 2021"),
210		},
211		.driver_data = (void *)&lcd800x1280_rightside_up,
212	}, {	/* AYA NEO AIR */
213		.matches = {
214		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "AYANEO"),
215		  DMI_MATCH(DMI_PRODUCT_NAME, "AIR"),
216		},
217		.driver_data = (void *)&lcd1080x1920_leftside_up,
218	}, {    /* AYA NEO Flip DS Bottom Screen */
219		.matches = {
220		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "AYANEO"),
221		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "FLIP DS"),
222		},
223		.driver_data = (void *)&lcd640x960_leftside_up,
224	}, {    /* AYA NEO Flip KB/DS Top Screen */
225		.matches = {
226		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "AYANEO"),
227		  DMI_MATCH(DMI_PRODUCT_NAME, "FLIP"),
228		},
229		.driver_data = (void *)&lcd1080x1920_leftside_up,
230	}, {	/* AYA NEO Founder */
231		.matches = {
232		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "AYA NEO"),
233		  DMI_MATCH(DMI_PRODUCT_NAME, "AYA NEO Founder"),
234		},
235		.driver_data = (void *)&lcd800x1280_rightside_up,
236	}, {	/* AYA NEO GEEK */
237		.matches = {
238		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "AYANEO"),
239		  DMI_MATCH(DMI_PRODUCT_NAME, "GEEK"),
240		},
241		.driver_data = (void *)&lcd800x1280_rightside_up,
242	}, {	/* AYA NEO NEXT */
243		.matches = {
244		  DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AYANEO"),
245		  DMI_MATCH(DMI_BOARD_NAME, "NEXT"),
246		},
247		.driver_data = (void *)&lcd800x1280_rightside_up,
248	}, {	/* AYA NEO KUN */
249		.matches = {
250		  DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AYANEO"),
251		  DMI_MATCH(DMI_BOARD_NAME, "KUN"),
252		},
253		.driver_data = (void *)&lcd1600x2560_rightside_up,
254	}, {	/* AYA NEO SLIDE */
255		.matches = {
256		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "AYANEO"),
257		  DMI_MATCH(DMI_PRODUCT_NAME, "SLIDE"),
258		},
259		.driver_data = (void *)&lcd1080x1920_leftside_up,
260	}, {    /* AYN Loki Max */
261		.matches = {
262			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ayn"),
263			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Loki Max"),
264		},
265		.driver_data = (void *)&lcd1080x1920_leftside_up,
266	}, {	/* AYN Loki Zero */
267		.matches = {
268			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ayn"),
269			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Loki Zero"),
270		},
271		.driver_data = (void *)&lcd1080x1920_leftside_up,
272	}, {	/* Chuwi HiBook (CWI514) */
273		.matches = {
274			DMI_MATCH(DMI_BOARD_VENDOR, "Hampoo"),
275			DMI_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"),
276			/* Above matches are too generic, add bios-date match */
277			DMI_MATCH(DMI_BIOS_DATE, "05/07/2016"),
278		},
279		.driver_data = (void *)&lcd1200x1920_rightside_up,
280	}, {	/* Chuwi Hi10 Pro (CWI529) */
281		.matches = {
282		  DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Hampoo"),
283		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Hi10 pro tablet"),
284		},
285		.driver_data = (void *)&lcd1200x1920_rightside_up,
286	}, {	/* Dynabook K50 */
287		.matches = {
288		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Dynabook Inc."),
289		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "dynabook K50/FR"),
290		},
291		.driver_data = (void *)&lcd800x1280_leftside_up,
292	}, {	/* GPD MicroPC (generic strings, also match on bios date) */
293		.matches = {
294		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Default string"),
295		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Default string"),
296		  DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Default string"),
297		  DMI_EXACT_MATCH(DMI_BOARD_NAME, "Default string"),
298		},
299		.driver_data = (void *)&gpd_micropc,
300	}, {	/* GPD MicroPC (later BIOS versions with proper DMI strings) */
301		.matches = {
302		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "GPD"),
303		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "MicroPC"),
304		},
305		.driver_data = (void *)&lcd720x1280_rightside_up,
306	}, {	/* GPD Win Max */
307		.matches = {
308		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "GPD"),
309		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "G1619-01"),
310		},
311		.driver_data = (void *)&lcd800x1280_rightside_up,
312	}, {	/*
313		 * GPD Pocket, note that the DMI data is less generic then
314		 * it seems, devices with a board-vendor of "AMI Corporation"
315		 * are quite rare, as are devices which have both board- *and*
316		 * product-id set to "Default String"
317		 */
318		.matches = {
319		  DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
320		  DMI_EXACT_MATCH(DMI_BOARD_NAME, "Default string"),
321		  DMI_EXACT_MATCH(DMI_BOARD_SERIAL, "Default string"),
322		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Default string"),
323		},
324		.driver_data = (void *)&gpd_pocket,
325	}, {	/* GPD Pocket 2 (generic strings, also match on bios date) */
326		.matches = {
327		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Default string"),
328		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Default string"),
329		  DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Default string"),
330		  DMI_EXACT_MATCH(DMI_BOARD_NAME, "Default string"),
331		},
332		.driver_data = (void *)&gpd_pocket2,
333	}, {	/* GPD Win (same note on DMI match as GPD Pocket) */
334		.matches = {
335		  DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
336		  DMI_EXACT_MATCH(DMI_BOARD_NAME, "Default string"),
337		  DMI_EXACT_MATCH(DMI_BOARD_SERIAL, "Default string"),
338		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Default string"),
339		},
340		.driver_data = (void *)&gpd_win,
341	}, {	/* GPD Win 2 (too generic strings, also match on bios date) */
342		.matches = {
343		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Default string"),
344		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Default string"),
345		  DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Default string"),
346		  DMI_EXACT_MATCH(DMI_BOARD_NAME, "Default string"),
347		},
348		.driver_data = (void *)&gpd_win2,
349	}, {	/* GPD Win 2 (correct DMI strings) */
350		.matches = {
351		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "GPD"),
352		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "WIN2")
353		},
354		.driver_data = (void *)&lcd720x1280_rightside_up,
355	}, {	/* GPD Win 3 */
356		.matches = {
357		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "GPD"),
358		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "G1618-03")
359		},
360		.driver_data = (void *)&lcd720x1280_rightside_up,
361	}, {	/* GPD Win Mini */
362		.matches = {
363		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "GPD"),
364		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "G1617-01")
365		},
366		.driver_data = (void *)&lcd1080x1920_rightside_up,
367	}, {	/* I.T.Works TW891 */
368		.matches = {
369		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "To be filled by O.E.M."),
370		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "TW891"),
371		  DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "To be filled by O.E.M."),
372		  DMI_EXACT_MATCH(DMI_BOARD_NAME, "TW891"),
373		},
374		.driver_data = (void *)&itworks_tw891,
375	}, {	/* KD Kurio Smart C15200 2-in-1 */
376		.matches = {
377		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "KD Interactive"),
378		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Kurio Smart"),
379		  DMI_EXACT_MATCH(DMI_BOARD_NAME, "KDM960BCP"),
380		},
381		.driver_data = (void *)&lcd800x1280_rightside_up,
382	}, {	/*
383		 * Lenovo Ideapad Miix 310 laptop, only some production batches
384		 * have a portrait screen, the resolution checks makes the quirk
385		 * apply only to those batches.
386		 */
387		.matches = {
388		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
389		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "80SG"),
390		  DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "MIIX 310-10ICR"),
391		},
392		.driver_data = (void *)&lcd800x1280_rightside_up,
393	}, {	/* Lenovo Ideapad Miix 320 */
394		.matches = {
395		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
396		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "80XF"),
397		  DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 320-10ICR"),
398		},
399		.driver_data = (void *)&lcd800x1280_rightside_up,
400	}, {	/* Lenovo Ideapad D330-10IGM (HD) */
401		.matches = {
402		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
403		  DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad D330-10IGM"),
404		},
405		.driver_data = (void *)&lcd800x1280_rightside_up,
406	}, {	/* Lenovo Ideapad D330-10IGM (FHD) */
407		.matches = {
408		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
409		  DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad D330-10IGM"),
410		},
411		.driver_data = (void *)&lcd1200x1920_rightside_up,
412	}, {	/* Lenovo Ideapad D330-10IGL (HD) */
413		.matches = {
414		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
415		  DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad D330-10IGL"),
416		},
417		.driver_data = (void *)&lcd800x1280_rightside_up,
418	}, {	/* Lenovo IdeaPad Duet 3 10IGL5 */
419		.matches = {
420		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
421		  DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "IdeaPad Duet 3 10IGL5"),
422		},
423		.driver_data = (void *)&lcd1200x1920_rightside_up,
424	}, {	/* Lenovo Legion Go 8APU1 */
425		.matches = {
426		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
427		  DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Legion Go 8APU1"),
428		},
429		.driver_data = (void *)&lcd1600x2560_leftside_up,
430	}, {	/* Lenovo Yoga Book X90F / X90L */
431		.matches = {
432		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
433		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "CHERRYVIEW D1 PLATFORM"),
434		  DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "YETI-11"),
435		},
436		.driver_data = (void *)&lcd1200x1920_rightside_up,
437	}, {	/* Lenovo Yoga Book X91F / X91L */
438		.matches = {
439		  /* Non exact match to match F + L versions */
440		  DMI_MATCH(DMI_PRODUCT_NAME, "Lenovo YB1-X91"),
441		},
442		.driver_data = (void *)&lcd1200x1920_rightside_up,
443	}, {	/* Lenovo Yoga Tablet 2 830F / 830L */
444		.matches = {
445		 /*
446		  * Note this also matches the Lenovo Yoga Tablet 2 1050F/L
447		  * since that uses the same mainboard. The resolution match
448		  * will limit this to only matching on the 830F/L. Neither has
449		  * any external video outputs so those are not a concern.
450		  */
451		 DMI_MATCH(DMI_SYS_VENDOR, "Intel Corp."),
452		 DMI_MATCH(DMI_PRODUCT_NAME, "VALLEYVIEW C0 PLATFORM"),
453		 DMI_MATCH(DMI_BOARD_NAME, "BYT-T FFD8"),
454		 /* Partial match on beginning of BIOS version */
455		 DMI_MATCH(DMI_BIOS_VERSION, "BLADE_21"),
456		},
457		.driver_data = (void *)&lcd1200x1920_rightside_up,
458	}, {	/* Lenovo Yoga Tab 3 X90F */
459		.matches = {
460		 DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
461		 DMI_MATCH(DMI_PRODUCT_VERSION, "Blade3-10A-001"),
462		},
463		.driver_data = (void *)&lcd1600x2560_rightside_up,
464	}, {	/* Nanote UMPC-01 */
465		.matches = {
466		 DMI_MATCH(DMI_SYS_VENDOR, "RWC CO.,LTD"),
467		 DMI_MATCH(DMI_PRODUCT_NAME, "UMPC-01"),
468		},
469		.driver_data = (void *)&lcd1200x1920_rightside_up,
470	}, {	/* OneGX1 Pro */
471		.matches = {
472		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "SYSTEM_MANUFACTURER"),
473		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "SYSTEM_PRODUCT_NAME"),
474		  DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Default string"),
475		},
476		.driver_data = (void *)&onegx1_pro,
477	}, {	/* OneXPlayer */
478		.matches = {
479		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ONE-NETBOOK TECHNOLOGY CO., LTD."),
480		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ONE XPLAYER"),
481		},
482		.driver_data = (void *)&lcd1600x2560_leftside_up,
483	}, {	/* OneXPlayer Mini (Intel) */
484		.matches = {
485		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ONE-NETBOOK TECHNOLOGY CO., LTD."),
486		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ONE XPLAYER"),
487		},
488		.driver_data = (void *)&lcd1200x1920_leftside_up,
489	}, {	/* OrangePi Neo */
490		.matches = {
491		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "OrangePi"),
492		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "NEO-01"),
493		},
494		.driver_data = (void *)&lcd1200x1920_rightside_up,
495	}, {	/* Samsung GalaxyBook 10.6 */
496		.matches = {
497		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
498		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Galaxy Book 10.6"),
499		},
500		.driver_data = (void *)&lcd1280x1920_rightside_up,
501	}, {	/* Valve Steam Deck (Jupiter) */
502		.matches = {
503		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Valve"),
504		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Jupiter"),
505		  DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "1"),
506		},
507		.driver_data = (void *)&lcd800x1280_rightside_up,
508	}, {	/* Valve Steam Deck (Galileo) */
509		.matches = {
510		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Valve"),
511		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Galileo"),
512		  DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "1"),
513		},
514		.driver_data = (void *)&lcd800x1280_rightside_up,
515	}, {	/* VIOS LTH17 */
516		.matches = {
517		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "VIOS"),
518		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "LTH17"),
519		},
520		.driver_data = (void *)&lcd800x1280_rightside_up,
521	}, {	/* ZOTAC Gaming Zone */
522		.matches = {
523		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ZOTAC"),
524		  DMI_EXACT_MATCH(DMI_BOARD_NAME, "G0A1W"),
525		},
526		.driver_data = (void *)&lcd1080x1920_leftside_up,
527	}, {	/* One Mix 2S (generic strings, also match on bios date) */
528		.matches = {
529		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Default string"),
530		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Default string"),
531		  DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Default string"),
532		  DMI_EXACT_MATCH(DMI_BOARD_NAME, "Default string"),
533		},
534		.driver_data = (void *)&gpd_onemix2s,
535	},
536	{}
537};
538
539/**
540 * drm_get_panel_orientation_quirk - Check for panel orientation quirks
541 * @width: width in pixels of the panel
542 * @height: height in pixels of the panel
543 *
544 * This function checks for platform specific (e.g. DMI based) quirks
545 * providing info on panel_orientation for systems where this cannot be
546 * probed from the hard-/firm-ware. To avoid false-positive this function
547 * takes the panel resolution as argument and checks that against the
548 * resolution expected by the quirk-table entry.
549 *
550 * Note this function is also used outside of the drm-subsys, by for example
551 * the efifb code. Because of this this function gets compiled into its own
552 * kernel-module when built as a module.
553 *
554 * Returns:
555 * A DRM_MODE_PANEL_ORIENTATION_* value if there is a quirk for this system,
556 * or DRM_MODE_PANEL_ORIENTATION_UNKNOWN if there is no quirk.
557 */
558int drm_get_panel_orientation_quirk(int width, int height)
559{
560	const struct dmi_system_id *match;
561	const struct drm_dmi_panel_orientation_data *data;
562	const char *bios_date;
563	int i;
564
565	for (match = dmi_first_match(orientation_data);
566	     match;
567	     match = dmi_first_match(match + 1)) {
568		data = match->driver_data;
569
570		if (data->width != width ||
571		    data->height != height)
572			continue;
573
574		if (!data->bios_dates)
575			return data->orientation;
576
577		bios_date = dmi_get_system_info(DMI_BIOS_DATE);
578		if (!bios_date)
579			continue;
580
581		i = match_string(data->bios_dates, -1, bios_date);
582		if (i >= 0)
583			return data->orientation;
584	}
585
586	return DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
587}
588EXPORT_SYMBOL(drm_get_panel_orientation_quirk);
589
590#else
591
592/* There are no quirks for non x86 devices yet */
593int drm_get_panel_orientation_quirk(int width, int height)
594{
595	return DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
596}
597EXPORT_SYMBOL(drm_get_panel_orientation_quirk);
598
599#endif
600
601MODULE_DESCRIPTION("Quirks for non-normal panel orientation");
602MODULE_LICENSE("Dual MIT/GPL");
~/ Read-only file preview.