cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

drm_panel_orientation_quirks.c (12896B)


      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/module.h>
     13#include <drm/drm_connector.h>
     14#include <drm/drm_utils.h>
     15
     16#ifdef CONFIG_DMI
     17
     18/*
     19 * Some x86 clamshell design devices use portrait tablet screens and a display
     20 * engine which cannot rotate in hardware, so we need to rotate the fbcon to
     21 * compensate. Unfortunately these (cheap) devices also typically have quite
     22 * generic DMI data, so we match on a combination of DMI data, screen resolution
     23 * 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 asus_t100ha = {
     34	.width = 800,
     35	.height = 1280,
     36	.orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP,
     37};
     38
     39static const struct drm_dmi_panel_orientation_data gpd_micropc = {
     40	.width = 720,
     41	.height = 1280,
     42	.bios_dates = (const char * const []){ "04/26/2019",
     43		NULL },
     44	.orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
     45};
     46
     47static const struct drm_dmi_panel_orientation_data gpd_pocket = {
     48	.width = 1200,
     49	.height = 1920,
     50	.bios_dates = (const char * const []){ "05/26/2017", "06/28/2017",
     51		"07/05/2017", "08/07/2017", NULL },
     52	.orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
     53};
     54
     55static const struct drm_dmi_panel_orientation_data gpd_pocket2 = {
     56	.width = 1200,
     57	.height = 1920,
     58	.bios_dates = (const char * const []){ "06/28/2018", "08/28/2018",
     59		"12/07/2018", NULL },
     60	.orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
     61};
     62
     63static const struct drm_dmi_panel_orientation_data gpd_win = {
     64	.width = 720,
     65	.height = 1280,
     66	.bios_dates = (const char * const []){
     67		"10/25/2016", "11/18/2016", "12/23/2016", "12/26/2016",
     68		"02/21/2017", "03/20/2017", "05/25/2017", NULL },
     69	.orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
     70};
     71
     72static const struct drm_dmi_panel_orientation_data gpd_win2 = {
     73	.width = 720,
     74	.height = 1280,
     75	.bios_dates = (const char * const []){
     76		"12/07/2017", "05/24/2018", "06/29/2018", NULL },
     77	.orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
     78};
     79
     80static const struct drm_dmi_panel_orientation_data itworks_tw891 = {
     81	.width = 800,
     82	.height = 1280,
     83	.bios_dates = (const char * const []){ "10/16/2015", NULL },
     84	.orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
     85};
     86
     87static const struct drm_dmi_panel_orientation_data onegx1_pro = {
     88	.width = 1200,
     89	.height = 1920,
     90	.bios_dates = (const char * const []){ "12/17/2020", NULL },
     91	.orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
     92};
     93
     94static const struct drm_dmi_panel_orientation_data lcd720x1280_rightside_up = {
     95	.width = 720,
     96	.height = 1280,
     97	.orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
     98};
     99
    100static const struct drm_dmi_panel_orientation_data lcd800x1280_rightside_up = {
    101	.width = 800,
    102	.height = 1280,
    103	.orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
    104};
    105
    106static const struct drm_dmi_panel_orientation_data lcd1200x1920_rightside_up = {
    107	.width = 1200,
    108	.height = 1920,
    109	.orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
    110};
    111
    112static const struct drm_dmi_panel_orientation_data lcd1280x1920_rightside_up = {
    113	.width = 1280,
    114	.height = 1920,
    115	.orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
    116};
    117
    118static const struct drm_dmi_panel_orientation_data lcd1600x2560_leftside_up = {
    119	.width = 1600,
    120	.height = 2560,
    121	.orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP,
    122};
    123
    124static const struct dmi_system_id orientation_data[] = {
    125	{	/* Acer One 10 (S1003) */
    126		.matches = {
    127		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Acer"),
    128		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "One S1003"),
    129		},
    130		.driver_data = (void *)&lcd800x1280_rightside_up,
    131	}, {	/* Asus T100HA */
    132		.matches = {
    133		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
    134		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100HAN"),
    135		},
    136		.driver_data = (void *)&asus_t100ha,
    137	}, {	/* Asus T101HA */
    138		.matches = {
    139		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
    140		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T101HA"),
    141		},
    142		.driver_data = (void *)&lcd800x1280_rightside_up,
    143	}, {	/* Asus T103HAF */
    144		.matches = {
    145		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
    146		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T103HAF"),
    147		},
    148		.driver_data = (void *)&lcd800x1280_rightside_up,
    149	}, {	/* AYA NEO 2021 */
    150		.matches = {
    151		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "AYADEVICE"),
    152		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "AYA NEO 2021"),
    153		},
    154		.driver_data = (void *)&lcd800x1280_rightside_up,
    155	}, {	/* AYA NEO NEXT */
    156		.matches = {
    157		  DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AYANEO"),
    158		  DMI_MATCH(DMI_BOARD_NAME, "NEXT"),
    159		},
    160		.driver_data = (void *)&lcd800x1280_rightside_up,
    161	}, {	/* Chuwi HiBook (CWI514) */
    162		.matches = {
    163			DMI_MATCH(DMI_BOARD_VENDOR, "Hampoo"),
    164			DMI_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"),
    165			/* Above matches are too generic, add bios-date match */
    166			DMI_MATCH(DMI_BIOS_DATE, "05/07/2016"),
    167		},
    168		.driver_data = (void *)&lcd1200x1920_rightside_up,
    169	}, {	/* Chuwi Hi10 Pro (CWI529) */
    170		.matches = {
    171		  DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Hampoo"),
    172		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Hi10 pro tablet"),
    173		},
    174		.driver_data = (void *)&lcd1200x1920_rightside_up,
    175	}, {	/* GPD MicroPC (generic strings, also match on bios date) */
    176		.matches = {
    177		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Default string"),
    178		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Default string"),
    179		  DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Default string"),
    180		  DMI_EXACT_MATCH(DMI_BOARD_NAME, "Default string"),
    181		},
    182		.driver_data = (void *)&gpd_micropc,
    183	}, {	/* GPD MicroPC (later BIOS versions with proper DMI strings) */
    184		.matches = {
    185		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "GPD"),
    186		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "MicroPC"),
    187		},
    188		.driver_data = (void *)&lcd720x1280_rightside_up,
    189	}, {	/* GPD Win Max */
    190		.matches = {
    191		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "GPD"),
    192		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "G1619-01"),
    193		},
    194		.driver_data = (void *)&lcd800x1280_rightside_up,
    195	}, {	/*
    196		 * GPD Pocket, note that the the DMI data is less generic then
    197		 * it seems, devices with a board-vendor of "AMI Corporation"
    198		 * are quite rare, as are devices which have both board- *and*
    199		 * product-id set to "Default String"
    200		 */
    201		.matches = {
    202		  DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
    203		  DMI_EXACT_MATCH(DMI_BOARD_NAME, "Default string"),
    204		  DMI_EXACT_MATCH(DMI_BOARD_SERIAL, "Default string"),
    205		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Default string"),
    206		},
    207		.driver_data = (void *)&gpd_pocket,
    208	}, {	/* GPD Pocket 2 (generic strings, also match on bios date) */
    209		.matches = {
    210		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Default string"),
    211		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Default string"),
    212		  DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Default string"),
    213		  DMI_EXACT_MATCH(DMI_BOARD_NAME, "Default string"),
    214		},
    215		.driver_data = (void *)&gpd_pocket2,
    216	}, {	/* GPD Win (same note on DMI match as GPD Pocket) */
    217		.matches = {
    218		  DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
    219		  DMI_EXACT_MATCH(DMI_BOARD_NAME, "Default string"),
    220		  DMI_EXACT_MATCH(DMI_BOARD_SERIAL, "Default string"),
    221		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Default string"),
    222		},
    223		.driver_data = (void *)&gpd_win,
    224	}, {	/* GPD Win 2 (too generic strings, also match on bios date) */
    225		.matches = {
    226		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Default string"),
    227		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Default string"),
    228		  DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Default string"),
    229		  DMI_EXACT_MATCH(DMI_BOARD_NAME, "Default string"),
    230		},
    231		.driver_data = (void *)&gpd_win2,
    232	}, {	/* GPD Win 3 */
    233		.matches = {
    234		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "GPD"),
    235		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "G1618-03")
    236		},
    237		.driver_data = (void *)&lcd720x1280_rightside_up,
    238	}, {	/* I.T.Works TW891 */
    239		.matches = {
    240		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "To be filled by O.E.M."),
    241		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "TW891"),
    242		  DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "To be filled by O.E.M."),
    243		  DMI_EXACT_MATCH(DMI_BOARD_NAME, "TW891"),
    244		},
    245		.driver_data = (void *)&itworks_tw891,
    246	}, {	/* KD Kurio Smart C15200 2-in-1 */
    247		.matches = {
    248		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "KD Interactive"),
    249		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Kurio Smart"),
    250		  DMI_EXACT_MATCH(DMI_BOARD_NAME, "KDM960BCP"),
    251		},
    252		.driver_data = (void *)&lcd800x1280_rightside_up,
    253	}, {	/*
    254		 * Lenovo Ideapad Miix 310 laptop, only some production batches
    255		 * have a portrait screen, the resolution checks makes the quirk
    256		 * apply only to those batches.
    257		 */
    258		.matches = {
    259		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
    260		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "80SG"),
    261		  DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "MIIX 310-10ICR"),
    262		},
    263		.driver_data = (void *)&lcd800x1280_rightside_up,
    264	}, {	/* Lenovo Ideapad Miix 320 */
    265		.matches = {
    266		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
    267		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "80XF"),
    268		  DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 320-10ICR"),
    269		},
    270		.driver_data = (void *)&lcd800x1280_rightside_up,
    271	}, {	/* Lenovo Ideapad D330-10IGM (HD) */
    272		.matches = {
    273		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
    274		  DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad D330-10IGM"),
    275		},
    276		.driver_data = (void *)&lcd800x1280_rightside_up,
    277	}, {	/* Lenovo Ideapad D330-10IGM (FHD) */
    278		.matches = {
    279		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
    280		  DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad D330-10IGM"),
    281		},
    282		.driver_data = (void *)&lcd1200x1920_rightside_up,
    283	}, {	/* Lenovo Yoga Book X90F / X91F / X91L */
    284		.matches = {
    285		  /* Non exact match to match all versions */
    286		  DMI_MATCH(DMI_PRODUCT_NAME, "Lenovo YB1-X9"),
    287		},
    288		.driver_data = (void *)&lcd1200x1920_rightside_up,
    289	}, {	/* OneGX1 Pro */
    290		.matches = {
    291		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "SYSTEM_MANUFACTURER"),
    292		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "SYSTEM_PRODUCT_NAME"),
    293		  DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Default string"),
    294		},
    295		.driver_data = (void *)&onegx1_pro,
    296	}, {	/* OneXPlayer */
    297		.matches = {
    298		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ONE-NETBOOK TECHNOLOGY CO., LTD."),
    299		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ONE XPLAYER"),
    300		},
    301		.driver_data = (void *)&lcd1600x2560_leftside_up,
    302	}, {	/* Samsung GalaxyBook 10.6 */
    303		.matches = {
    304		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
    305		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Galaxy Book 10.6"),
    306		},
    307		.driver_data = (void *)&lcd1280x1920_rightside_up,
    308	}, {	/* Valve Steam Deck */
    309		.matches = {
    310		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Valve"),
    311		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Jupiter"),
    312		  DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "1"),
    313		},
    314		.driver_data = (void *)&lcd800x1280_rightside_up,
    315	}, {	/* VIOS LTH17 */
    316		.matches = {
    317		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "VIOS"),
    318		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "LTH17"),
    319		},
    320		.driver_data = (void *)&lcd800x1280_rightside_up,
    321	},
    322	{}
    323};
    324
    325/**
    326 * drm_get_panel_orientation_quirk - Check for panel orientation quirks
    327 * @width: width in pixels of the panel
    328 * @height: height in pixels of the panel
    329 *
    330 * This function checks for platform specific (e.g. DMI based) quirks
    331 * providing info on panel_orientation for systems where this cannot be
    332 * probed from the hard-/firm-ware. To avoid false-positive this function
    333 * takes the panel resolution as argument and checks that against the
    334 * resolution expected by the quirk-table entry.
    335 *
    336 * Note this function is also used outside of the drm-subsys, by for example
    337 * the efifb code. Because of this this function gets compiled into its own
    338 * kernel-module when built as a module.
    339 *
    340 * Returns:
    341 * A DRM_MODE_PANEL_ORIENTATION_* value if there is a quirk for this system,
    342 * or DRM_MODE_PANEL_ORIENTATION_UNKNOWN if there is no quirk.
    343 */
    344int drm_get_panel_orientation_quirk(int width, int height)
    345{
    346	const struct dmi_system_id *match;
    347	const struct drm_dmi_panel_orientation_data *data;
    348	const char *bios_date;
    349	int i;
    350
    351	for (match = dmi_first_match(orientation_data);
    352	     match;
    353	     match = dmi_first_match(match + 1)) {
    354		data = match->driver_data;
    355
    356		if (data->width != width ||
    357		    data->height != height)
    358			continue;
    359
    360		if (!data->bios_dates)
    361			return data->orientation;
    362
    363		bios_date = dmi_get_system_info(DMI_BIOS_DATE);
    364		if (!bios_date)
    365			continue;
    366
    367		i = match_string(data->bios_dates, -1, bios_date);
    368		if (i >= 0)
    369			return data->orientation;
    370	}
    371
    372	return DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
    373}
    374EXPORT_SYMBOL(drm_get_panel_orientation_quirk);
    375
    376#else
    377
    378/* There are no quirks for non x86 devices yet */
    379int drm_get_panel_orientation_quirk(int width, int height)
    380{
    381	return DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
    382}
    383EXPORT_SYMBOL(drm_get_panel_orientation_quirk);
    384
    385#endif
    386
    387MODULE_LICENSE("Dual MIT/GPL");