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