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 27 struct drm_dmi_panel_orientation_data { 28 int width; 29 int height; 30 const char * const *bios_dates; 31 int orientation; 32 }; 33 34 static 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 42 static 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 50 static 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 58 static 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 66 static 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 75 static 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 83 static 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 90 static 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 97 static 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 103 static 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 109 static 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 115 static 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 121 static 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 127 static 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 133 static 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 139 static 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 145 static 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 151 static 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 157 static 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 163 static 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 */ 558 int 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 } 588 EXPORT_SYMBOL(drm_get_panel_orientation_quirk); 589 590 #else 591 592 /* There are no quirks for non x86 devices yet */ 593 int drm_get_panel_orientation_quirk(int width, int height) 594 { 595 return DRM_MODE_PANEL_ORIENTATION_UNKNOWN; 596 } 597 EXPORT_SYMBOL(drm_get_panel_orientation_quirk); 598 599 #endif 600 601 MODULE_DESCRIPTION("Quirks for non-normal panel orientation"); 602 MODULE_LICENSE("Dual MIT/GPL"); 603