LCOV - code coverage report
Current view: top level - drivers/gpu/drm - drm_panel_orientation_quirks.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 20 0.0 %
Date: 2022-04-01 14:17:54 Functions: 0 1 0.0 %
Branches: 0 12 0.0 %

           Branch data     Line data    Source code
       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                 :            : 
      26                 :            : struct drm_dmi_panel_orientation_data {
      27                 :            :         int width;
      28                 :            :         int height;
      29                 :            :         const char * const *bios_dates;
      30                 :            :         int orientation;
      31                 :            : };
      32                 :            : 
      33                 :            : static const struct drm_dmi_panel_orientation_data acer_s1003 = {
      34                 :            :         .width = 800,
      35                 :            :         .height = 1280,
      36                 :            :         .orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
      37                 :            : };
      38                 :            : 
      39                 :            : static const struct drm_dmi_panel_orientation_data asus_t100ha = {
      40                 :            :         .width = 800,
      41                 :            :         .height = 1280,
      42                 :            :         .orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP,
      43                 :            : };
      44                 :            : 
      45                 :            : static const struct drm_dmi_panel_orientation_data gpd_micropc = {
      46                 :            :         .width = 720,
      47                 :            :         .height = 1280,
      48                 :            :         .bios_dates = (const char * const []){ "04/26/2019",
      49                 :            :                 NULL },
      50                 :            :         .orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
      51                 :            : };
      52                 :            : 
      53                 :            : static const struct drm_dmi_panel_orientation_data gpd_pocket = {
      54                 :            :         .width = 1200,
      55                 :            :         .height = 1920,
      56                 :            :         .bios_dates = (const char * const []){ "05/26/2017", "06/28/2017",
      57                 :            :                 "07/05/2017", "08/07/2017", NULL },
      58                 :            :         .orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
      59                 :            : };
      60                 :            : 
      61                 :            : static const struct drm_dmi_panel_orientation_data gpd_pocket2 = {
      62                 :            :         .width = 1200,
      63                 :            :         .height = 1920,
      64                 :            :         .bios_dates = (const char * const []){ "06/28/2018", "08/28/2018",
      65                 :            :                 "12/07/2018", NULL },
      66                 :            :         .orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
      67                 :            : };
      68                 :            : 
      69                 :            : static const struct drm_dmi_panel_orientation_data gpd_win = {
      70                 :            :         .width = 720,
      71                 :            :         .height = 1280,
      72                 :            :         .bios_dates = (const char * const []){
      73                 :            :                 "10/25/2016", "11/18/2016", "12/23/2016", "12/26/2016",
      74                 :            :                 "02/21/2017", "03/20/2017", "05/25/2017", NULL },
      75                 :            :         .orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
      76                 :            : };
      77                 :            : 
      78                 :            : static const struct drm_dmi_panel_orientation_data gpd_win2 = {
      79                 :            :         .width = 720,
      80                 :            :         .height = 1280,
      81                 :            :         .bios_dates = (const char * const []){
      82                 :            :                 "12/07/2017", "05/24/2018", "06/29/2018", NULL },
      83                 :            :         .orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
      84                 :            : };
      85                 :            : 
      86                 :            : static const struct drm_dmi_panel_orientation_data itworks_tw891 = {
      87                 :            :         .width = 800,
      88                 :            :         .height = 1280,
      89                 :            :         .bios_dates = (const char * const []){ "10/16/2015", NULL },
      90                 :            :         .orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
      91                 :            : };
      92                 :            : 
      93                 :            : static const struct drm_dmi_panel_orientation_data lcd720x1280_rightside_up = {
      94                 :            :         .width = 720,
      95                 :            :         .height = 1280,
      96                 :            :         .orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
      97                 :            : };
      98                 :            : 
      99                 :            : static const struct drm_dmi_panel_orientation_data lcd800x1280_rightside_up = {
     100                 :            :         .width = 800,
     101                 :            :         .height = 1280,
     102                 :            :         .orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
     103                 :            : };
     104                 :            : 
     105                 :            : static const struct drm_dmi_panel_orientation_data lcd1200x1920_rightside_up = {
     106                 :            :         .width = 1200,
     107                 :            :         .height = 1920,
     108                 :            :         .orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
     109                 :            : };
     110                 :            : 
     111                 :            : static const struct dmi_system_id orientation_data[] = {
     112                 :            :         {       /* Acer One 10 (S1003) */
     113                 :            :                 .matches = {
     114                 :            :                   DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Acer"),
     115                 :            :                   DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "One S1003"),
     116                 :            :                 },
     117                 :            :                 .driver_data = (void *)&acer_s1003,
     118                 :            :         }, {    /* Asus T100HA */
     119                 :            :                 .matches = {
     120                 :            :                   DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
     121                 :            :                   DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100HAN"),
     122                 :            :                 },
     123                 :            :                 .driver_data = (void *)&asus_t100ha,
     124                 :            :         }, {    /* GPD MicroPC (generic strings, also match on bios date) */
     125                 :            :                 .matches = {
     126                 :            :                   DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Default string"),
     127                 :            :                   DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Default string"),
     128                 :            :                   DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Default string"),
     129                 :            :                   DMI_EXACT_MATCH(DMI_BOARD_NAME, "Default string"),
     130                 :            :                 },
     131                 :            :                 .driver_data = (void *)&gpd_micropc,
     132                 :            :         }, {    /* GPD MicroPC (later BIOS versions with proper DMI strings) */
     133                 :            :                 .matches = {
     134                 :            :                   DMI_EXACT_MATCH(DMI_SYS_VENDOR, "GPD"),
     135                 :            :                   DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "MicroPC"),
     136                 :            :                 },
     137                 :            :                 .driver_data = (void *)&lcd720x1280_rightside_up,
     138                 :            :         }, {    /*
     139                 :            :                  * GPD Pocket, note that the the DMI data is less generic then
     140                 :            :                  * it seems, devices with a board-vendor of "AMI Corporation"
     141                 :            :                  * are quite rare, as are devices which have both board- *and*
     142                 :            :                  * product-id set to "Default String"
     143                 :            :                  */
     144                 :            :                 .matches = {
     145                 :            :                   DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
     146                 :            :                   DMI_EXACT_MATCH(DMI_BOARD_NAME, "Default string"),
     147                 :            :                   DMI_EXACT_MATCH(DMI_BOARD_SERIAL, "Default string"),
     148                 :            :                   DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Default string"),
     149                 :            :                 },
     150                 :            :                 .driver_data = (void *)&gpd_pocket,
     151                 :            :         }, {    /* GPD Pocket 2 (generic strings, also match on bios date) */
     152                 :            :                 .matches = {
     153                 :            :                   DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Default string"),
     154                 :            :                   DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Default string"),
     155                 :            :                   DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Default string"),
     156                 :            :                   DMI_EXACT_MATCH(DMI_BOARD_NAME, "Default string"),
     157                 :            :                 },
     158                 :            :                 .driver_data = (void *)&gpd_pocket2,
     159                 :            :         }, {    /* GPD Win (same note on DMI match as GPD Pocket) */
     160                 :            :                 .matches = {
     161                 :            :                   DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
     162                 :            :                   DMI_EXACT_MATCH(DMI_BOARD_NAME, "Default string"),
     163                 :            :                   DMI_EXACT_MATCH(DMI_BOARD_SERIAL, "Default string"),
     164                 :            :                   DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Default string"),
     165                 :            :                 },
     166                 :            :                 .driver_data = (void *)&gpd_win,
     167                 :            :         }, {    /* GPD Win 2 (too generic strings, also match on bios date) */
     168                 :            :                 .matches = {
     169                 :            :                   DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Default string"),
     170                 :            :                   DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Default string"),
     171                 :            :                   DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Default string"),
     172                 :            :                   DMI_EXACT_MATCH(DMI_BOARD_NAME, "Default string"),
     173                 :            :                 },
     174                 :            :                 .driver_data = (void *)&gpd_win2,
     175                 :            :         }, {    /* I.T.Works TW891 */
     176                 :            :                 .matches = {
     177                 :            :                   DMI_EXACT_MATCH(DMI_SYS_VENDOR, "To be filled by O.E.M."),
     178                 :            :                   DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "TW891"),
     179                 :            :                   DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "To be filled by O.E.M."),
     180                 :            :                   DMI_EXACT_MATCH(DMI_BOARD_NAME, "TW891"),
     181                 :            :                 },
     182                 :            :                 .driver_data = (void *)&itworks_tw891,
     183                 :            :         }, {    /*
     184                 :            :                  * Lenovo Ideapad Miix 310 laptop, only some production batches
     185                 :            :                  * have a portrait screen, the resolution checks makes the quirk
     186                 :            :                  * apply only to those batches.
     187                 :            :                  */
     188                 :            :                 .matches = {
     189                 :            :                   DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
     190                 :            :                   DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "80SG"),
     191                 :            :                   DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "MIIX 310-10ICR"),
     192                 :            :                 },
     193                 :            :                 .driver_data = (void *)&lcd800x1280_rightside_up,
     194                 :            :         }, {    /* Lenovo Ideapad Miix 320 */
     195                 :            :                 .matches = {
     196                 :            :                   DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
     197                 :            :                   DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "80XF"),
     198                 :            :                   DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 320-10ICR"),
     199                 :            :                 },
     200                 :            :                 .driver_data = (void *)&lcd800x1280_rightside_up,
     201                 :            :         }, {    /* Lenovo Ideapad D330 */
     202                 :            :                 .matches = {
     203                 :            :                   DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
     204                 :            :                   DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "81H3"),
     205                 :            :                   DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad D330-10IGM"),
     206                 :            :                 },
     207                 :            :                 .driver_data = (void *)&lcd1200x1920_rightside_up,
     208                 :            :         }, {    /* VIOS LTH17 */
     209                 :            :                 .matches = {
     210                 :            :                   DMI_EXACT_MATCH(DMI_SYS_VENDOR, "VIOS"),
     211                 :            :                   DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "LTH17"),
     212                 :            :                 },
     213                 :            :                 .driver_data = (void *)&lcd800x1280_rightside_up,
     214                 :            :         },
     215                 :            :         {}
     216                 :            : };
     217                 :            : 
     218                 :            : /**
     219                 :            :  * drm_get_panel_orientation_quirk - Check for panel orientation quirks
     220                 :            :  * @width: width in pixels of the panel
     221                 :            :  * @height: height in pixels of the panel
     222                 :            :  *
     223                 :            :  * This function checks for platform specific (e.g. DMI based) quirks
     224                 :            :  * providing info on panel_orientation for systems where this cannot be
     225                 :            :  * probed from the hard-/firm-ware. To avoid false-positive this function
     226                 :            :  * takes the panel resolution as argument and checks that against the
     227                 :            :  * resolution expected by the quirk-table entry.
     228                 :            :  *
     229                 :            :  * Note this function is also used outside of the drm-subsys, by for example
     230                 :            :  * the efifb code. Because of this this function gets compiled into its own
     231                 :            :  * kernel-module when built as a module.
     232                 :            :  *
     233                 :            :  * Returns:
     234                 :            :  * A DRM_MODE_PANEL_ORIENTATION_* value if there is a quirk for this system,
     235                 :            :  * or DRM_MODE_PANEL_ORIENTATION_UNKNOWN if there is no quirk.
     236                 :            :  */
     237                 :          0 : int drm_get_panel_orientation_quirk(int width, int height)
     238                 :            : {
     239                 :          0 :         const struct dmi_system_id *match;
     240                 :          0 :         const struct drm_dmi_panel_orientation_data *data;
     241                 :          0 :         const char *bios_date;
     242                 :          0 :         int i;
     243                 :            : 
     244                 :          0 :         for (match = dmi_first_match(orientation_data);
     245         [ #  # ]:          0 :              match;
     246                 :          0 :              match = dmi_first_match(match + 1)) {
     247                 :          0 :                 data = match->driver_data;
     248                 :            : 
     249         [ #  # ]:          0 :                 if (data->width != width ||
     250         [ #  # ]:          0 :                     data->height != height)
     251                 :          0 :                         continue;
     252                 :            : 
     253         [ #  # ]:          0 :                 if (!data->bios_dates)
     254                 :          0 :                         return data->orientation;
     255                 :            : 
     256                 :          0 :                 bios_date = dmi_get_system_info(DMI_BIOS_DATE);
     257         [ #  # ]:          0 :                 if (!bios_date)
     258                 :          0 :                         continue;
     259                 :            : 
     260                 :          0 :                 i = match_string(data->bios_dates, -1, bios_date);
     261         [ #  # ]:          0 :                 if (i >= 0)
     262                 :          0 :                         return data->orientation;
     263                 :            :         }
     264                 :            : 
     265                 :            :         return DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
     266                 :            : }
     267                 :            : EXPORT_SYMBOL(drm_get_panel_orientation_quirk);
     268                 :            : 
     269                 :            : #else
     270                 :            : 
     271                 :            : /* There are no quirks for non x86 devices yet */
     272                 :            : int drm_get_panel_orientation_quirk(int width, int height)
     273                 :            : {
     274                 :            :         return DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
     275                 :            : }
     276                 :            : EXPORT_SYMBOL(drm_get_panel_orientation_quirk);
     277                 :            : 
     278                 :            : #endif
     279                 :            : 
     280                 :            : MODULE_LICENSE("Dual MIT/GPL");

Generated by: LCOV version 1.14