LCOV - code coverage report
Current view: top level - drivers/gpu/drm - drm_modes.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 693 0.0 %
Date: 2022-04-01 13:59:58 Functions: 0 38 0.0 %
Branches: 0 436 0.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright © 1997-2003 by The XFree86 Project, Inc.
       3                 :            :  * Copyright © 2007 Dave Airlie
       4                 :            :  * Copyright © 2007-2008 Intel Corporation
       5                 :            :  *   Jesse Barnes <jesse.barnes@intel.com>
       6                 :            :  * Copyright 2005-2006 Luc Verhaegen
       7                 :            :  * Copyright (c) 2001, Andy Ritger  aritger@nvidia.com
       8                 :            :  *
       9                 :            :  * Permission is hereby granted, free of charge, to any person obtaining a
      10                 :            :  * copy of this software and associated documentation files (the "Software"),
      11                 :            :  * to deal in the Software without restriction, including without limitation
      12                 :            :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      13                 :            :  * and/or sell copies of the Software, and to permit persons to whom the
      14                 :            :  * Software is furnished to do so, subject to the following conditions:
      15                 :            :  *
      16                 :            :  * The above copyright notice and this permission notice shall be included in
      17                 :            :  * all copies or substantial portions of the Software.
      18                 :            :  *
      19                 :            :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      20                 :            :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      21                 :            :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      22                 :            :  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
      23                 :            :  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
      24                 :            :  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
      25                 :            :  * OTHER DEALINGS IN THE SOFTWARE.
      26                 :            :  *
      27                 :            :  * Except as contained in this notice, the name of the copyright holder(s)
      28                 :            :  * and author(s) shall not be used in advertising or otherwise to promote
      29                 :            :  * the sale, use or other dealings in this Software without prior written
      30                 :            :  * authorization from the copyright holder(s) and author(s).
      31                 :            :  */
      32                 :            : 
      33                 :            : #include <linux/ctype.h>
      34                 :            : #include <linux/list.h>
      35                 :            : #include <linux/list_sort.h>
      36                 :            : #include <linux/export.h>
      37                 :            : 
      38                 :            : #include <video/of_videomode.h>
      39                 :            : #include <video/videomode.h>
      40                 :            : 
      41                 :            : #include <drm/drm_crtc.h>
      42                 :            : #include <drm/drm_device.h>
      43                 :            : #include <drm/drm_modes.h>
      44                 :            : #include <drm/drm_print.h>
      45                 :            : 
      46                 :            : #include "drm_crtc_internal.h"
      47                 :            : 
      48                 :            : /**
      49                 :            :  * drm_mode_debug_printmodeline - print a mode to dmesg
      50                 :            :  * @mode: mode to print
      51                 :            :  *
      52                 :            :  * Describe @mode using DRM_DEBUG.
      53                 :            :  */
      54                 :          0 : void drm_mode_debug_printmodeline(const struct drm_display_mode *mode)
      55                 :            : {
      56                 :          0 :         DRM_DEBUG_KMS("Modeline " DRM_MODE_FMT "\n", DRM_MODE_ARG(mode));
      57                 :          0 : }
      58                 :            : EXPORT_SYMBOL(drm_mode_debug_printmodeline);
      59                 :            : 
      60                 :            : /**
      61                 :            :  * drm_mode_create - create a new display mode
      62                 :            :  * @dev: DRM device
      63                 :            :  *
      64                 :            :  * Create a new, cleared drm_display_mode with kzalloc, allocate an ID for it
      65                 :            :  * and return it.
      66                 :            :  *
      67                 :            :  * Returns:
      68                 :            :  * Pointer to new mode on success, NULL on error.
      69                 :            :  */
      70                 :          0 : struct drm_display_mode *drm_mode_create(struct drm_device *dev)
      71                 :            : {
      72                 :          0 :         struct drm_display_mode *nmode;
      73                 :            : 
      74                 :          0 :         nmode = kzalloc(sizeof(struct drm_display_mode), GFP_KERNEL);
      75   [ #  #  #  #  :          0 :         if (!nmode)
             #  #  #  # ]
      76                 :          0 :                 return NULL;
      77                 :            : 
      78                 :            :         return nmode;
      79                 :            : }
      80                 :            : EXPORT_SYMBOL(drm_mode_create);
      81                 :            : 
      82                 :            : /**
      83                 :            :  * drm_mode_destroy - remove a mode
      84                 :            :  * @dev: DRM device
      85                 :            :  * @mode: mode to remove
      86                 :            :  *
      87                 :            :  * Release @mode's unique ID, then free it @mode structure itself using kfree.
      88                 :            :  */
      89                 :          0 : void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode)
      90                 :            : {
      91         [ #  # ]:          0 :         if (!mode)
      92                 :            :                 return;
      93                 :            : 
      94                 :          0 :         kfree(mode);
      95                 :            : }
      96                 :            : EXPORT_SYMBOL(drm_mode_destroy);
      97                 :            : 
      98                 :            : /**
      99                 :            :  * drm_mode_probed_add - add a mode to a connector's probed_mode list
     100                 :            :  * @connector: connector the new mode
     101                 :            :  * @mode: mode data
     102                 :            :  *
     103                 :            :  * Add @mode to @connector's probed_mode list for later use. This list should
     104                 :            :  * then in a second step get filtered and all the modes actually supported by
     105                 :            :  * the hardware moved to the @connector's modes list.
     106                 :            :  */
     107                 :          0 : void drm_mode_probed_add(struct drm_connector *connector,
     108                 :            :                          struct drm_display_mode *mode)
     109                 :            : {
     110         [ #  # ]:          0 :         WARN_ON(!mutex_is_locked(&connector->dev->mode_config.mutex));
     111                 :            : 
     112                 :          0 :         list_add_tail(&mode->head, &connector->probed_modes);
     113                 :          0 : }
     114                 :            : EXPORT_SYMBOL(drm_mode_probed_add);
     115                 :            : 
     116                 :            : /**
     117                 :            :  * drm_cvt_mode -create a modeline based on the CVT algorithm
     118                 :            :  * @dev: drm device
     119                 :            :  * @hdisplay: hdisplay size
     120                 :            :  * @vdisplay: vdisplay size
     121                 :            :  * @vrefresh: vrefresh rate
     122                 :            :  * @reduced: whether to use reduced blanking
     123                 :            :  * @interlaced: whether to compute an interlaced mode
     124                 :            :  * @margins: whether to add margins (borders)
     125                 :            :  *
     126                 :            :  * This function is called to generate the modeline based on CVT algorithm
     127                 :            :  * according to the hdisplay, vdisplay, vrefresh.
     128                 :            :  * It is based from the VESA(TM) Coordinated Video Timing Generator by
     129                 :            :  * Graham Loveridge April 9, 2003 available at
     130                 :            :  * http://www.elo.utfsm.cl/~elo212/docs/CVTd6r1.xls 
     131                 :            :  *
     132                 :            :  * And it is copied from xf86CVTmode in xserver/hw/xfree86/modes/xf86cvt.c.
     133                 :            :  * What I have done is to translate it by using integer calculation.
     134                 :            :  *
     135                 :            :  * Returns:
     136                 :            :  * The modeline based on the CVT algorithm stored in a drm_display_mode object.
     137                 :            :  * The display mode object is allocated with drm_mode_create(). Returns NULL
     138                 :            :  * when no mode could be allocated.
     139                 :            :  */
     140                 :          0 : struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, int hdisplay,
     141                 :            :                                       int vdisplay, int vrefresh,
     142                 :            :                                       bool reduced, bool interlaced, bool margins)
     143                 :            : {
     144                 :            : #define HV_FACTOR                       1000
     145                 :            :         /* 1) top/bottom margin size (% of height) - default: 1.8, */
     146                 :            : #define CVT_MARGIN_PERCENTAGE           18
     147                 :            :         /* 2) character cell horizontal granularity (pixels) - default 8 */
     148                 :            : #define CVT_H_GRANULARITY               8
     149                 :            :         /* 3) Minimum vertical porch (lines) - default 3 */
     150                 :            : #define CVT_MIN_V_PORCH                 3
     151                 :            :         /* 4) Minimum number of vertical back porch lines - default 6 */
     152                 :            : #define CVT_MIN_V_BPORCH                6
     153                 :            :         /* Pixel Clock step (kHz) */
     154                 :            : #define CVT_CLOCK_STEP                  250
     155                 :          0 :         struct drm_display_mode *drm_mode;
     156                 :          0 :         unsigned int vfieldrate, hperiod;
     157                 :          0 :         int hdisplay_rnd, hmargin, vdisplay_rnd, vmargin, vsync;
     158                 :          0 :         int interlace;
     159                 :          0 :         u64 tmp;
     160                 :            : 
     161         [ #  # ]:          0 :         if (!hdisplay || !vdisplay)
     162                 :            :                 return NULL;
     163                 :            : 
     164                 :            :         /* allocate the drm_display_mode structure. If failure, we will
     165                 :            :          * return directly
     166                 :            :          */
     167                 :          0 :         drm_mode = drm_mode_create(dev);
     168                 :          0 :         if (!drm_mode)
     169                 :            :                 return NULL;
     170                 :            : 
     171                 :            :         /* the CVT default refresh rate is 60Hz */
     172         [ #  # ]:          0 :         if (!vrefresh)
     173                 :          0 :                 vrefresh = 60;
     174                 :            : 
     175                 :            :         /* the required field fresh rate */
     176         [ #  # ]:          0 :         if (interlaced)
     177                 :          0 :                 vfieldrate = vrefresh * 2;
     178                 :            :         else
     179                 :          0 :                 vfieldrate = vrefresh;
     180                 :            : 
     181                 :            :         /* horizontal pixels */
     182                 :          0 :         hdisplay_rnd = hdisplay - (hdisplay % CVT_H_GRANULARITY);
     183                 :            : 
     184                 :            :         /* determine the left&right borders */
     185                 :          0 :         hmargin = 0;
     186         [ #  # ]:          0 :         if (margins) {
     187                 :          0 :                 hmargin = hdisplay_rnd * CVT_MARGIN_PERCENTAGE / 1000;
     188                 :          0 :                 hmargin -= hmargin % CVT_H_GRANULARITY;
     189                 :            :         }
     190                 :            :         /* find the total active pixels */
     191                 :          0 :         drm_mode->hdisplay = hdisplay_rnd + 2 * hmargin;
     192                 :            : 
     193                 :            :         /* find the number of lines per field */
     194         [ #  # ]:          0 :         if (interlaced)
     195                 :          0 :                 vdisplay_rnd = vdisplay / 2;
     196                 :            :         else
     197                 :            :                 vdisplay_rnd = vdisplay;
     198                 :            : 
     199                 :            :         /* find the top & bottom borders */
     200                 :          0 :         vmargin = 0;
     201         [ #  # ]:          0 :         if (margins)
     202                 :          0 :                 vmargin = vdisplay_rnd * CVT_MARGIN_PERCENTAGE / 1000;
     203                 :            : 
     204                 :          0 :         drm_mode->vdisplay = vdisplay + 2 * vmargin;
     205                 :            : 
     206                 :            :         /* Interlaced */
     207         [ #  # ]:          0 :         if (interlaced)
     208                 :            :                 interlace = 1;
     209                 :            :         else
     210                 :          0 :                 interlace = 0;
     211                 :            : 
     212                 :            :         /* Determine VSync Width from aspect ratio */
     213   [ #  #  #  # ]:          0 :         if (!(vdisplay % 3) && ((vdisplay * 4 / 3) == hdisplay))
     214                 :            :                 vsync = 4;
     215   [ #  #  #  # ]:          0 :         else if (!(vdisplay % 9) && ((vdisplay * 16 / 9) == hdisplay))
     216                 :            :                 vsync = 5;
     217   [ #  #  #  # ]:          0 :         else if (!(vdisplay % 10) && ((vdisplay * 16 / 10) == hdisplay))
     218                 :            :                 vsync = 6;
     219   [ #  #  #  # ]:          0 :         else if (!(vdisplay % 4) && ((vdisplay * 5 / 4) == hdisplay))
     220                 :            :                 vsync = 7;
     221   [ #  #  #  # ]:          0 :         else if (!(vdisplay % 9) && ((vdisplay * 15 / 9) == hdisplay))
     222                 :            :                 vsync = 7;
     223                 :            :         else /* custom */
     224                 :          0 :                 vsync = 10;
     225                 :            : 
     226         [ #  # ]:          0 :         if (!reduced) {
     227                 :            :                 /* simplify the GTF calculation */
     228                 :            :                 /* 4) Minimum time of vertical sync + back porch interval (µs)
     229                 :            :                  * default 550.0
     230                 :            :                  */
     231                 :          0 :                 int tmp1, tmp2;
     232                 :            : #define CVT_MIN_VSYNC_BP        550
     233                 :            :                 /* 3) Nominal HSync width (% of line period) - default 8 */
     234                 :            : #define CVT_HSYNC_PERCENTAGE    8
     235                 :          0 :                 unsigned int hblank_percentage;
     236                 :          0 :                 int vsyncandback_porch, __maybe_unused vback_porch, hblank;
     237                 :            : 
     238                 :            :                 /* estimated the horizontal period */
     239                 :          0 :                 tmp1 = HV_FACTOR * 1000000  -
     240                 :          0 :                                 CVT_MIN_VSYNC_BP * HV_FACTOR * vfieldrate;
     241                 :          0 :                 tmp2 = (vdisplay_rnd + 2 * vmargin + CVT_MIN_V_PORCH) * 2 +
     242                 :            :                                 interlace;
     243                 :          0 :                 hperiod = tmp1 * 2 / (tmp2 * vfieldrate);
     244                 :            : 
     245                 :          0 :                 tmp1 = CVT_MIN_VSYNC_BP * HV_FACTOR / hperiod + 1;
     246                 :            :                 /* 9. Find number of lines in sync + backporch */
     247                 :          0 :                 if (tmp1 < (vsync + CVT_MIN_V_PORCH))
     248                 :            :                         vsyncandback_porch = vsync + CVT_MIN_V_PORCH;
     249                 :            :                 else
     250                 :            :                         vsyncandback_porch = tmp1;
     251                 :            :                 /* 10. Find number of lines in back porch */
     252                 :          0 :                 vback_porch = vsyncandback_porch - vsync;
     253                 :          0 :                 drm_mode->vtotal = vdisplay_rnd + 2 * vmargin +
     254                 :          0 :                                 vsyncandback_porch + CVT_MIN_V_PORCH;
     255                 :            :                 /* 5) Definition of Horizontal blanking time limitation */
     256                 :            :                 /* Gradient (%/kHz) - default 600 */
     257                 :            : #define CVT_M_FACTOR    600
     258                 :            :                 /* Offset (%) - default 40 */
     259                 :            : #define CVT_C_FACTOR    40
     260                 :            :                 /* Blanking time scaling factor - default 128 */
     261                 :            : #define CVT_K_FACTOR    128
     262                 :            :                 /* Scaling factor weighting - default 20 */
     263                 :            : #define CVT_J_FACTOR    20
     264                 :            : #define CVT_M_PRIME     (CVT_M_FACTOR * CVT_K_FACTOR / 256)
     265                 :            : #define CVT_C_PRIME     ((CVT_C_FACTOR - CVT_J_FACTOR) * CVT_K_FACTOR / 256 + \
     266                 :            :                          CVT_J_FACTOR)
     267                 :            :                 /* 12. Find ideal blanking duty cycle from formula */
     268                 :          0 :                 hblank_percentage = CVT_C_PRIME * HV_FACTOR - CVT_M_PRIME *
     269                 :          0 :                                         hperiod / 1000;
     270                 :            :                 /* 13. Blanking time */
     271                 :          0 :                 if (hblank_percentage < 20 * HV_FACTOR)
     272                 :            :                         hblank_percentage = 20 * HV_FACTOR;
     273                 :          0 :                 hblank = drm_mode->hdisplay * hblank_percentage /
     274                 :          0 :                          (100 * HV_FACTOR - hblank_percentage);
     275                 :          0 :                 hblank -= hblank % (2 * CVT_H_GRANULARITY);
     276                 :            :                 /* 14. find the total pixels per line */
     277                 :          0 :                 drm_mode->htotal = drm_mode->hdisplay + hblank;
     278                 :          0 :                 drm_mode->hsync_end = drm_mode->hdisplay + hblank / 2;
     279                 :          0 :                 drm_mode->hsync_start = drm_mode->hsync_end -
     280                 :          0 :                         (drm_mode->htotal * CVT_HSYNC_PERCENTAGE) / 100;
     281                 :          0 :                 drm_mode->hsync_start += CVT_H_GRANULARITY -
     282                 :          0 :                         drm_mode->hsync_start % CVT_H_GRANULARITY;
     283                 :            :                 /* fill the Vsync values */
     284                 :          0 :                 drm_mode->vsync_start = drm_mode->vdisplay + CVT_MIN_V_PORCH;
     285                 :          0 :                 drm_mode->vsync_end = drm_mode->vsync_start + vsync;
     286                 :            :         } else {
     287                 :            :                 /* Reduced blanking */
     288                 :            :                 /* Minimum vertical blanking interval time (µs)- default 460 */
     289                 :            : #define CVT_RB_MIN_VBLANK       460
     290                 :            :                 /* Fixed number of clocks for horizontal sync */
     291                 :            : #define CVT_RB_H_SYNC           32
     292                 :            :                 /* Fixed number of clocks for horizontal blanking */
     293                 :            : #define CVT_RB_H_BLANK          160
     294                 :            :                 /* Fixed number of lines for vertical front porch - default 3*/
     295                 :            : #define CVT_RB_VFPORCH          3
     296                 :          0 :                 int vbilines;
     297                 :          0 :                 int tmp1, tmp2;
     298                 :            :                 /* 8. Estimate Horizontal period. */
     299                 :          0 :                 tmp1 = HV_FACTOR * 1000000 -
     300                 :          0 :                         CVT_RB_MIN_VBLANK * HV_FACTOR * vfieldrate;
     301                 :          0 :                 tmp2 = vdisplay_rnd + 2 * vmargin;
     302                 :          0 :                 hperiod = tmp1 / (tmp2 * vfieldrate);
     303                 :            :                 /* 9. Find number of lines in vertical blanking */
     304                 :          0 :                 vbilines = CVT_RB_MIN_VBLANK * HV_FACTOR / hperiod + 1;
     305                 :            :                 /* 10. Check if vertical blanking is sufficient */
     306                 :          0 :                 if (vbilines < (CVT_RB_VFPORCH + vsync + CVT_MIN_V_BPORCH))
     307                 :            :                         vbilines = CVT_RB_VFPORCH + vsync + CVT_MIN_V_BPORCH;
     308                 :            :                 /* 11. Find total number of lines in vertical field */
     309                 :          0 :                 drm_mode->vtotal = vdisplay_rnd + 2 * vmargin + vbilines;
     310                 :            :                 /* 12. Find total number of pixels in a line */
     311                 :          0 :                 drm_mode->htotal = drm_mode->hdisplay + CVT_RB_H_BLANK;
     312                 :            :                 /* Fill in HSync values */
     313                 :          0 :                 drm_mode->hsync_end = drm_mode->hdisplay + CVT_RB_H_BLANK / 2;
     314                 :          0 :                 drm_mode->hsync_start = drm_mode->hsync_end - CVT_RB_H_SYNC;
     315                 :            :                 /* Fill in VSync values */
     316                 :          0 :                 drm_mode->vsync_start = drm_mode->vdisplay + CVT_RB_VFPORCH;
     317                 :          0 :                 drm_mode->vsync_end = drm_mode->vsync_start + vsync;
     318                 :            :         }
     319                 :            :         /* 15/13. Find pixel clock frequency (kHz for xf86) */
     320                 :          0 :         tmp = drm_mode->htotal; /* perform intermediate calcs in u64 */
     321                 :          0 :         tmp *= HV_FACTOR * 1000;
     322                 :          0 :         do_div(tmp, hperiod);
     323                 :          0 :         tmp -= drm_mode->clock % CVT_CLOCK_STEP;
     324                 :          0 :         drm_mode->clock = tmp;
     325                 :            :         /* 18/16. Find actual vertical frame frequency */
     326                 :            :         /* ignore - just set the mode flag for interlaced */
     327         [ #  # ]:          0 :         if (interlaced) {
     328                 :          0 :                 drm_mode->vtotal *= 2;
     329                 :          0 :                 drm_mode->flags |= DRM_MODE_FLAG_INTERLACE;
     330                 :            :         }
     331                 :            :         /* Fill the mode line name */
     332                 :          0 :         drm_mode_set_name(drm_mode);
     333         [ #  # ]:          0 :         if (reduced)
     334                 :          0 :                 drm_mode->flags |= (DRM_MODE_FLAG_PHSYNC |
     335                 :            :                                         DRM_MODE_FLAG_NVSYNC);
     336                 :            :         else
     337                 :          0 :                 drm_mode->flags |= (DRM_MODE_FLAG_PVSYNC |
     338                 :            :                                         DRM_MODE_FLAG_NHSYNC);
     339                 :            : 
     340                 :            :         return drm_mode;
     341                 :            : }
     342                 :            : EXPORT_SYMBOL(drm_cvt_mode);
     343                 :            : 
     344                 :            : /**
     345                 :            :  * drm_gtf_mode_complex - create the modeline based on the full GTF algorithm
     346                 :            :  * @dev: drm device
     347                 :            :  * @hdisplay: hdisplay size
     348                 :            :  * @vdisplay: vdisplay size
     349                 :            :  * @vrefresh: vrefresh rate.
     350                 :            :  * @interlaced: whether to compute an interlaced mode
     351                 :            :  * @margins: desired margin (borders) size
     352                 :            :  * @GTF_M: extended GTF formula parameters
     353                 :            :  * @GTF_2C: extended GTF formula parameters
     354                 :            :  * @GTF_K: extended GTF formula parameters
     355                 :            :  * @GTF_2J: extended GTF formula parameters
     356                 :            :  *
     357                 :            :  * GTF feature blocks specify C and J in multiples of 0.5, so we pass them
     358                 :            :  * in here multiplied by two.  For a C of 40, pass in 80.
     359                 :            :  *
     360                 :            :  * Returns:
     361                 :            :  * The modeline based on the full GTF algorithm stored in a drm_display_mode object.
     362                 :            :  * The display mode object is allocated with drm_mode_create(). Returns NULL
     363                 :            :  * when no mode could be allocated.
     364                 :            :  */
     365                 :            : struct drm_display_mode *
     366                 :          0 : drm_gtf_mode_complex(struct drm_device *dev, int hdisplay, int vdisplay,
     367                 :            :                      int vrefresh, bool interlaced, int margins,
     368                 :            :                      int GTF_M, int GTF_2C, int GTF_K, int GTF_2J)
     369                 :            : {       /* 1) top/bottom margin size (% of height) - default: 1.8, */
     370                 :            : #define GTF_MARGIN_PERCENTAGE           18
     371                 :            :         /* 2) character cell horizontal granularity (pixels) - default 8 */
     372                 :            : #define GTF_CELL_GRAN                   8
     373                 :            :         /* 3) Minimum vertical porch (lines) - default 3 */
     374                 :            : #define GTF_MIN_V_PORCH                 1
     375                 :            :         /* width of vsync in lines */
     376                 :            : #define V_SYNC_RQD                      3
     377                 :            :         /* width of hsync as % of total line */
     378                 :            : #define H_SYNC_PERCENT                  8
     379                 :            :         /* min time of vsync + back porch (microsec) */
     380                 :            : #define MIN_VSYNC_PLUS_BP               550
     381                 :            :         /* C' and M' are part of the Blanking Duty Cycle computation */
     382                 :            : #define GTF_C_PRIME     ((((GTF_2C - GTF_2J) * GTF_K / 256) + GTF_2J) / 2)
     383                 :            : #define GTF_M_PRIME     (GTF_K * GTF_M / 256)
     384                 :          0 :         struct drm_display_mode *drm_mode;
     385                 :          0 :         unsigned int hdisplay_rnd, vdisplay_rnd, vfieldrate_rqd;
     386                 :          0 :         int top_margin, bottom_margin;
     387                 :          0 :         int interlace;
     388                 :          0 :         unsigned int hfreq_est;
     389                 :          0 :         int vsync_plus_bp, __maybe_unused vback_porch;
     390                 :          0 :         unsigned int vtotal_lines, __maybe_unused vfieldrate_est;
     391                 :          0 :         unsigned int __maybe_unused hperiod;
     392                 :          0 :         unsigned int vfield_rate, __maybe_unused vframe_rate;
     393                 :          0 :         int left_margin, right_margin;
     394                 :          0 :         unsigned int total_active_pixels, ideal_duty_cycle;
     395                 :          0 :         unsigned int hblank, total_pixels, pixel_freq;
     396                 :          0 :         int hsync, hfront_porch, vodd_front_porch_lines;
     397                 :          0 :         unsigned int tmp1, tmp2;
     398                 :            : 
     399         [ #  # ]:          0 :         if (!hdisplay || !vdisplay)
     400                 :            :                 return NULL;
     401                 :            : 
     402                 :          0 :         drm_mode = drm_mode_create(dev);
     403                 :          0 :         if (!drm_mode)
     404                 :            :                 return NULL;
     405                 :            : 
     406                 :            :         /* 1. In order to give correct results, the number of horizontal
     407                 :            :          * pixels requested is first processed to ensure that it is divisible
     408                 :            :          * by the character size, by rounding it to the nearest character
     409                 :            :          * cell boundary:
     410                 :            :          */
     411                 :          0 :         hdisplay_rnd = (hdisplay + GTF_CELL_GRAN / 2) / GTF_CELL_GRAN;
     412                 :          0 :         hdisplay_rnd = hdisplay_rnd * GTF_CELL_GRAN;
     413                 :            : 
     414                 :            :         /* 2. If interlace is requested, the number of vertical lines assumed
     415                 :            :          * by the calculation must be halved, as the computation calculates
     416                 :            :          * the number of vertical lines per field.
     417                 :            :          */
     418         [ #  # ]:          0 :         if (interlaced)
     419                 :          0 :                 vdisplay_rnd = vdisplay / 2;
     420                 :            :         else
     421                 :          0 :                 vdisplay_rnd = vdisplay;
     422                 :            : 
     423                 :            :         /* 3. Find the frame rate required: */
     424         [ #  # ]:          0 :         if (interlaced)
     425                 :          0 :                 vfieldrate_rqd = vrefresh * 2;
     426                 :            :         else
     427                 :          0 :                 vfieldrate_rqd = vrefresh;
     428                 :            : 
     429                 :            :         /* 4. Find number of lines in Top margin: */
     430                 :          0 :         top_margin = 0;
     431         [ #  # ]:          0 :         if (margins)
     432                 :          0 :                 top_margin = (vdisplay_rnd * GTF_MARGIN_PERCENTAGE + 500) /
     433                 :            :                                 1000;
     434                 :            :         /* 5. Find number of lines in bottom margin: */
     435                 :          0 :         bottom_margin = top_margin;
     436                 :            : 
     437                 :            :         /* 6. If interlace is required, then set variable interlace: */
     438         [ #  # ]:          0 :         if (interlaced)
     439                 :            :                 interlace = 1;
     440                 :            :         else
     441                 :          0 :                 interlace = 0;
     442                 :            : 
     443                 :            :         /* 7. Estimate the Horizontal frequency */
     444                 :            :         {
     445                 :          0 :                 tmp1 = (1000000  - MIN_VSYNC_PLUS_BP * vfieldrate_rqd) / 500;
     446                 :          0 :                 tmp2 = (vdisplay_rnd + 2 * top_margin + GTF_MIN_V_PORCH) *
     447                 :          0 :                                 2 + interlace;
     448                 :          0 :                 hfreq_est = (tmp2 * 1000 * vfieldrate_rqd) / tmp1;
     449                 :            :         }
     450                 :            : 
     451                 :            :         /* 8. Find the number of lines in V sync + back porch */
     452                 :            :         /* [V SYNC+BP] = RINT(([MIN VSYNC+BP] * hfreq_est / 1000000)) */
     453                 :          0 :         vsync_plus_bp = MIN_VSYNC_PLUS_BP * hfreq_est / 1000;
     454                 :          0 :         vsync_plus_bp = (vsync_plus_bp + 500) / 1000;
     455                 :            :         /*  9. Find the number of lines in V back porch alone: */
     456                 :          0 :         vback_porch = vsync_plus_bp - V_SYNC_RQD;
     457                 :            :         /*  10. Find the total number of lines in Vertical field period: */
     458                 :          0 :         vtotal_lines = vdisplay_rnd + top_margin + bottom_margin +
     459                 :            :                         vsync_plus_bp + GTF_MIN_V_PORCH;
     460                 :            :         /*  11. Estimate the Vertical field frequency: */
     461                 :          0 :         vfieldrate_est = hfreq_est / vtotal_lines;
     462                 :            :         /*  12. Find the actual horizontal period: */
     463                 :          0 :         hperiod = 1000000 / (vfieldrate_rqd * vtotal_lines);
     464                 :            : 
     465                 :            :         /*  13. Find the actual Vertical field frequency: */
     466                 :          0 :         vfield_rate = hfreq_est / vtotal_lines;
     467                 :            :         /*  14. Find the Vertical frame frequency: */
     468                 :          0 :         if (interlaced)
     469                 :            :                 vframe_rate = vfield_rate / 2;
     470                 :            :         else
     471                 :            :                 vframe_rate = vfield_rate;
     472                 :            :         /*  15. Find number of pixels in left margin: */
     473         [ #  # ]:          0 :         if (margins)
     474                 :          0 :                 left_margin = (hdisplay_rnd * GTF_MARGIN_PERCENTAGE + 500) /
     475                 :            :                                 1000;
     476                 :            :         else
     477                 :            :                 left_margin = 0;
     478                 :            : 
     479                 :            :         /* 16.Find number of pixels in right margin: */
     480                 :          0 :         right_margin = left_margin;
     481                 :            :         /* 17.Find total number of active pixels in image and left and right */
     482                 :          0 :         total_active_pixels = hdisplay_rnd + left_margin + right_margin;
     483                 :            :         /* 18.Find the ideal blanking duty cycle from blanking duty cycle */
     484                 :          0 :         ideal_duty_cycle = GTF_C_PRIME * 1000 -
     485                 :          0 :                                 (GTF_M_PRIME * 1000000 / hfreq_est);
     486                 :            :         /* 19.Find the number of pixels in the blanking time to the nearest
     487                 :            :          * double character cell: */
     488                 :          0 :         hblank = total_active_pixels * ideal_duty_cycle /
     489                 :          0 :                         (100000 - ideal_duty_cycle);
     490                 :          0 :         hblank = (hblank + GTF_CELL_GRAN) / (2 * GTF_CELL_GRAN);
     491                 :          0 :         hblank = hblank * 2 * GTF_CELL_GRAN;
     492                 :            :         /* 20.Find total number of pixels: */
     493                 :          0 :         total_pixels = total_active_pixels + hblank;
     494                 :            :         /* 21.Find pixel clock frequency: */
     495                 :          0 :         pixel_freq = total_pixels * hfreq_est / 1000;
     496                 :            :         /* Stage 1 computations are now complete; I should really pass
     497                 :            :          * the results to another function and do the Stage 2 computations,
     498                 :            :          * but I only need a few more values so I'll just append the
     499                 :            :          * computations here for now */
     500                 :            :         /* 17. Find the number of pixels in the horizontal sync period: */
     501                 :          0 :         hsync = H_SYNC_PERCENT * total_pixels / 100;
     502                 :          0 :         hsync = (hsync + GTF_CELL_GRAN / 2) / GTF_CELL_GRAN;
     503                 :          0 :         hsync = hsync * GTF_CELL_GRAN;
     504                 :            :         /* 18. Find the number of pixels in horizontal front porch period */
     505                 :          0 :         hfront_porch = hblank / 2 - hsync;
     506                 :            :         /*  36. Find the number of lines in the odd front porch period: */
     507                 :          0 :         vodd_front_porch_lines = GTF_MIN_V_PORCH ;
     508                 :            : 
     509                 :            :         /* finally, pack the results in the mode struct */
     510                 :          0 :         drm_mode->hdisplay = hdisplay_rnd;
     511                 :          0 :         drm_mode->hsync_start = hdisplay_rnd + hfront_porch;
     512                 :          0 :         drm_mode->hsync_end = drm_mode->hsync_start + hsync;
     513                 :          0 :         drm_mode->htotal = total_pixels;
     514                 :          0 :         drm_mode->vdisplay = vdisplay_rnd;
     515                 :          0 :         drm_mode->vsync_start = vdisplay_rnd + vodd_front_porch_lines;
     516                 :          0 :         drm_mode->vsync_end = drm_mode->vsync_start + V_SYNC_RQD;
     517                 :          0 :         drm_mode->vtotal = vtotal_lines;
     518                 :            : 
     519                 :          0 :         drm_mode->clock = pixel_freq;
     520                 :            : 
     521         [ #  # ]:          0 :         if (interlaced) {
     522                 :          0 :                 drm_mode->vtotal *= 2;
     523                 :          0 :                 drm_mode->flags |= DRM_MODE_FLAG_INTERLACE;
     524                 :            :         }
     525                 :            : 
     526                 :          0 :         drm_mode_set_name(drm_mode);
     527   [ #  #  #  # ]:          0 :         if (GTF_M == 600 && GTF_2C == 80 && GTF_K == 128 && GTF_2J == 40)
     528                 :          0 :                 drm_mode->flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC;
     529                 :            :         else
     530                 :          0 :                 drm_mode->flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC;
     531                 :            : 
     532                 :            :         return drm_mode;
     533                 :            : }
     534                 :            : EXPORT_SYMBOL(drm_gtf_mode_complex);
     535                 :            : 
     536                 :            : /**
     537                 :            :  * drm_gtf_mode - create the modeline based on the GTF algorithm
     538                 :            :  * @dev: drm device
     539                 :            :  * @hdisplay: hdisplay size
     540                 :            :  * @vdisplay: vdisplay size
     541                 :            :  * @vrefresh: vrefresh rate.
     542                 :            :  * @interlaced: whether to compute an interlaced mode
     543                 :            :  * @margins: desired margin (borders) size
     544                 :            :  *
     545                 :            :  * return the modeline based on GTF algorithm
     546                 :            :  *
     547                 :            :  * This function is to create the modeline based on the GTF algorithm.
     548                 :            :  * Generalized Timing Formula is derived from:
     549                 :            :  *
     550                 :            :  *      GTF Spreadsheet by Andy Morrish (1/5/97)
     551                 :            :  *      available at http://www.vesa.org
     552                 :            :  *
     553                 :            :  * And it is copied from the file of xserver/hw/xfree86/modes/xf86gtf.c.
     554                 :            :  * What I have done is to translate it by using integer calculation.
     555                 :            :  * I also refer to the function of fb_get_mode in the file of
     556                 :            :  * drivers/video/fbmon.c
     557                 :            :  *
     558                 :            :  * Standard GTF parameters::
     559                 :            :  *
     560                 :            :  *     M = 600
     561                 :            :  *     C = 40
     562                 :            :  *     K = 128
     563                 :            :  *     J = 20
     564                 :            :  *
     565                 :            :  * Returns:
     566                 :            :  * The modeline based on the GTF algorithm stored in a drm_display_mode object.
     567                 :            :  * The display mode object is allocated with drm_mode_create(). Returns NULL
     568                 :            :  * when no mode could be allocated.
     569                 :            :  */
     570                 :            : struct drm_display_mode *
     571                 :          0 : drm_gtf_mode(struct drm_device *dev, int hdisplay, int vdisplay, int vrefresh,
     572                 :            :              bool interlaced, int margins)
     573                 :            : {
     574                 :          0 :         return drm_gtf_mode_complex(dev, hdisplay, vdisplay, vrefresh,
     575                 :            :                                     interlaced, margins,
     576                 :            :                                     600, 40 * 2, 128, 20 * 2);
     577                 :            : }
     578                 :            : EXPORT_SYMBOL(drm_gtf_mode);
     579                 :            : 
     580                 :            : #ifdef CONFIG_VIDEOMODE_HELPERS
     581                 :            : /**
     582                 :            :  * drm_display_mode_from_videomode - fill in @dmode using @vm,
     583                 :            :  * @vm: videomode structure to use as source
     584                 :            :  * @dmode: drm_display_mode structure to use as destination
     585                 :            :  *
     586                 :            :  * Fills out @dmode using the display mode specified in @vm.
     587                 :            :  */
     588                 :            : void drm_display_mode_from_videomode(const struct videomode *vm,
     589                 :            :                                      struct drm_display_mode *dmode)
     590                 :            : {
     591                 :            :         dmode->hdisplay = vm->hactive;
     592                 :            :         dmode->hsync_start = dmode->hdisplay + vm->hfront_porch;
     593                 :            :         dmode->hsync_end = dmode->hsync_start + vm->hsync_len;
     594                 :            :         dmode->htotal = dmode->hsync_end + vm->hback_porch;
     595                 :            : 
     596                 :            :         dmode->vdisplay = vm->vactive;
     597                 :            :         dmode->vsync_start = dmode->vdisplay + vm->vfront_porch;
     598                 :            :         dmode->vsync_end = dmode->vsync_start + vm->vsync_len;
     599                 :            :         dmode->vtotal = dmode->vsync_end + vm->vback_porch;
     600                 :            : 
     601                 :            :         dmode->clock = vm->pixelclock / 1000;
     602                 :            : 
     603                 :            :         dmode->flags = 0;
     604                 :            :         if (vm->flags & DISPLAY_FLAGS_HSYNC_HIGH)
     605                 :            :                 dmode->flags |= DRM_MODE_FLAG_PHSYNC;
     606                 :            :         else if (vm->flags & DISPLAY_FLAGS_HSYNC_LOW)
     607                 :            :                 dmode->flags |= DRM_MODE_FLAG_NHSYNC;
     608                 :            :         if (vm->flags & DISPLAY_FLAGS_VSYNC_HIGH)
     609                 :            :                 dmode->flags |= DRM_MODE_FLAG_PVSYNC;
     610                 :            :         else if (vm->flags & DISPLAY_FLAGS_VSYNC_LOW)
     611                 :            :                 dmode->flags |= DRM_MODE_FLAG_NVSYNC;
     612                 :            :         if (vm->flags & DISPLAY_FLAGS_INTERLACED)
     613                 :            :                 dmode->flags |= DRM_MODE_FLAG_INTERLACE;
     614                 :            :         if (vm->flags & DISPLAY_FLAGS_DOUBLESCAN)
     615                 :            :                 dmode->flags |= DRM_MODE_FLAG_DBLSCAN;
     616                 :            :         if (vm->flags & DISPLAY_FLAGS_DOUBLECLK)
     617                 :            :                 dmode->flags |= DRM_MODE_FLAG_DBLCLK;
     618                 :            :         drm_mode_set_name(dmode);
     619                 :            : }
     620                 :            : EXPORT_SYMBOL_GPL(drm_display_mode_from_videomode);
     621                 :            : 
     622                 :            : /**
     623                 :            :  * drm_display_mode_to_videomode - fill in @vm using @dmode,
     624                 :            :  * @dmode: drm_display_mode structure to use as source
     625                 :            :  * @vm: videomode structure to use as destination
     626                 :            :  *
     627                 :            :  * Fills out @vm using the display mode specified in @dmode.
     628                 :            :  */
     629                 :            : void drm_display_mode_to_videomode(const struct drm_display_mode *dmode,
     630                 :            :                                    struct videomode *vm)
     631                 :            : {
     632                 :            :         vm->hactive = dmode->hdisplay;
     633                 :            :         vm->hfront_porch = dmode->hsync_start - dmode->hdisplay;
     634                 :            :         vm->hsync_len = dmode->hsync_end - dmode->hsync_start;
     635                 :            :         vm->hback_porch = dmode->htotal - dmode->hsync_end;
     636                 :            : 
     637                 :            :         vm->vactive = dmode->vdisplay;
     638                 :            :         vm->vfront_porch = dmode->vsync_start - dmode->vdisplay;
     639                 :            :         vm->vsync_len = dmode->vsync_end - dmode->vsync_start;
     640                 :            :         vm->vback_porch = dmode->vtotal - dmode->vsync_end;
     641                 :            : 
     642                 :            :         vm->pixelclock = dmode->clock * 1000;
     643                 :            : 
     644                 :            :         vm->flags = 0;
     645                 :            :         if (dmode->flags & DRM_MODE_FLAG_PHSYNC)
     646                 :            :                 vm->flags |= DISPLAY_FLAGS_HSYNC_HIGH;
     647                 :            :         else if (dmode->flags & DRM_MODE_FLAG_NHSYNC)
     648                 :            :                 vm->flags |= DISPLAY_FLAGS_HSYNC_LOW;
     649                 :            :         if (dmode->flags & DRM_MODE_FLAG_PVSYNC)
     650                 :            :                 vm->flags |= DISPLAY_FLAGS_VSYNC_HIGH;
     651                 :            :         else if (dmode->flags & DRM_MODE_FLAG_NVSYNC)
     652                 :            :                 vm->flags |= DISPLAY_FLAGS_VSYNC_LOW;
     653                 :            :         if (dmode->flags & DRM_MODE_FLAG_INTERLACE)
     654                 :            :                 vm->flags |= DISPLAY_FLAGS_INTERLACED;
     655                 :            :         if (dmode->flags & DRM_MODE_FLAG_DBLSCAN)
     656                 :            :                 vm->flags |= DISPLAY_FLAGS_DOUBLESCAN;
     657                 :            :         if (dmode->flags & DRM_MODE_FLAG_DBLCLK)
     658                 :            :                 vm->flags |= DISPLAY_FLAGS_DOUBLECLK;
     659                 :            : }
     660                 :            : EXPORT_SYMBOL_GPL(drm_display_mode_to_videomode);
     661                 :            : 
     662                 :            : /**
     663                 :            :  * drm_bus_flags_from_videomode - extract information about pixelclk and
     664                 :            :  * DE polarity from videomode and store it in a separate variable
     665                 :            :  * @vm: videomode structure to use
     666                 :            :  * @bus_flags: information about pixelclk, sync and DE polarity will be stored
     667                 :            :  * here
     668                 :            :  *
     669                 :            :  * Sets DRM_BUS_FLAG_DE_(LOW|HIGH),  DRM_BUS_FLAG_PIXDATA_DRIVE_(POS|NEG)EDGE
     670                 :            :  * and DISPLAY_FLAGS_SYNC_(POS|NEG)EDGE in @bus_flags according to DISPLAY_FLAGS
     671                 :            :  * found in @vm
     672                 :            :  */
     673                 :            : void drm_bus_flags_from_videomode(const struct videomode *vm, u32 *bus_flags)
     674                 :            : {
     675                 :            :         *bus_flags = 0;
     676                 :            :         if (vm->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE)
     677                 :            :                 *bus_flags |= DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE;
     678                 :            :         if (vm->flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)
     679                 :            :                 *bus_flags |= DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE;
     680                 :            : 
     681                 :            :         if (vm->flags & DISPLAY_FLAGS_SYNC_POSEDGE)
     682                 :            :                 *bus_flags |= DRM_BUS_FLAG_SYNC_DRIVE_POSEDGE;
     683                 :            :         if (vm->flags & DISPLAY_FLAGS_SYNC_NEGEDGE)
     684                 :            :                 *bus_flags |= DRM_BUS_FLAG_SYNC_DRIVE_NEGEDGE;
     685                 :            : 
     686                 :            :         if (vm->flags & DISPLAY_FLAGS_DE_LOW)
     687                 :            :                 *bus_flags |= DRM_BUS_FLAG_DE_LOW;
     688                 :            :         if (vm->flags & DISPLAY_FLAGS_DE_HIGH)
     689                 :            :                 *bus_flags |= DRM_BUS_FLAG_DE_HIGH;
     690                 :            : }
     691                 :            : EXPORT_SYMBOL_GPL(drm_bus_flags_from_videomode);
     692                 :            : 
     693                 :            : #ifdef CONFIG_OF
     694                 :            : /**
     695                 :            :  * of_get_drm_display_mode - get a drm_display_mode from devicetree
     696                 :            :  * @np: device_node with the timing specification
     697                 :            :  * @dmode: will be set to the return value
     698                 :            :  * @bus_flags: information about pixelclk, sync and DE polarity
     699                 :            :  * @index: index into the list of display timings in devicetree
     700                 :            :  *
     701                 :            :  * This function is expensive and should only be used, if only one mode is to be
     702                 :            :  * read from DT. To get multiple modes start with of_get_display_timings and
     703                 :            :  * work with that instead.
     704                 :            :  *
     705                 :            :  * Returns:
     706                 :            :  * 0 on success, a negative errno code when no of videomode node was found.
     707                 :            :  */
     708                 :            : int of_get_drm_display_mode(struct device_node *np,
     709                 :            :                             struct drm_display_mode *dmode, u32 *bus_flags,
     710                 :            :                             int index)
     711                 :            : {
     712                 :            :         struct videomode vm;
     713                 :            :         int ret;
     714                 :            : 
     715                 :            :         ret = of_get_videomode(np, &vm, index);
     716                 :            :         if (ret)
     717                 :            :                 return ret;
     718                 :            : 
     719                 :            :         drm_display_mode_from_videomode(&vm, dmode);
     720                 :            :         if (bus_flags)
     721                 :            :                 drm_bus_flags_from_videomode(&vm, bus_flags);
     722                 :            : 
     723                 :            :         pr_debug("%pOF: got %dx%d display mode\n",
     724                 :            :                 np, vm.hactive, vm.vactive);
     725                 :            :         drm_mode_debug_printmodeline(dmode);
     726                 :            : 
     727                 :            :         return 0;
     728                 :            : }
     729                 :            : EXPORT_SYMBOL_GPL(of_get_drm_display_mode);
     730                 :            : #endif /* CONFIG_OF */
     731                 :            : #endif /* CONFIG_VIDEOMODE_HELPERS */
     732                 :            : 
     733                 :            : /**
     734                 :            :  * drm_mode_set_name - set the name on a mode
     735                 :            :  * @mode: name will be set in this mode
     736                 :            :  *
     737                 :            :  * Set the name of @mode to a standard format which is <hdisplay>x<vdisplay>
     738                 :            :  * with an optional 'i' suffix for interlaced modes.
     739                 :            :  */
     740                 :          0 : void drm_mode_set_name(struct drm_display_mode *mode)
     741                 :            : {
     742                 :          0 :         bool interlaced = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
     743                 :            : 
     744         [ #  # ]:          0 :         snprintf(mode->name, DRM_DISPLAY_MODE_LEN, "%dx%d%s",
     745                 :            :                  mode->hdisplay, mode->vdisplay,
     746                 :            :                  interlaced ? "i" : "");
     747                 :          0 : }
     748                 :            : EXPORT_SYMBOL(drm_mode_set_name);
     749                 :            : 
     750                 :            : /**
     751                 :            :  * drm_mode_hsync - get the hsync of a mode
     752                 :            :  * @mode: mode
     753                 :            :  *
     754                 :            :  * Returns:
     755                 :            :  * @modes's hsync rate in kHz, rounded to the nearest integer. Calculates the
     756                 :            :  * value first if it is not yet set.
     757                 :            :  */
     758                 :          0 : int drm_mode_hsync(const struct drm_display_mode *mode)
     759                 :            : {
     760                 :          0 :         unsigned int calc_val;
     761                 :            : 
     762         [ #  # ]:          0 :         if (mode->hsync)
     763                 :            :                 return mode->hsync;
     764                 :            : 
     765         [ #  # ]:          0 :         if (mode->htotal <= 0)
     766                 :            :                 return 0;
     767                 :            : 
     768                 :          0 :         calc_val = (mode->clock * 1000) / mode->htotal; /* hsync in Hz */
     769                 :          0 :         calc_val += 500;                                /* round to 1000Hz */
     770                 :          0 :         calc_val /= 1000;                               /* truncate to kHz */
     771                 :            : 
     772                 :          0 :         return calc_val;
     773                 :            : }
     774                 :            : EXPORT_SYMBOL(drm_mode_hsync);
     775                 :            : 
     776                 :            : /**
     777                 :            :  * drm_mode_vrefresh - get the vrefresh of a mode
     778                 :            :  * @mode: mode
     779                 :            :  *
     780                 :            :  * Returns:
     781                 :            :  * @modes's vrefresh rate in Hz, rounded to the nearest integer. Calculates the
     782                 :            :  * value first if it is not yet set.
     783                 :            :  */
     784                 :          0 : int drm_mode_vrefresh(const struct drm_display_mode *mode)
     785                 :            : {
     786                 :          0 :         int refresh = 0;
     787                 :            : 
     788         [ #  # ]:          0 :         if (mode->vrefresh > 0)
     789                 :            :                 refresh = mode->vrefresh;
     790   [ #  #  #  # ]:          0 :         else if (mode->htotal > 0 && mode->vtotal > 0) {
     791                 :          0 :                 unsigned int num, den;
     792                 :            : 
     793                 :          0 :                 num = mode->clock * 1000;
     794                 :          0 :                 den = mode->htotal * mode->vtotal;
     795                 :            : 
     796         [ #  # ]:          0 :                 if (mode->flags & DRM_MODE_FLAG_INTERLACE)
     797                 :          0 :                         num *= 2;
     798         [ #  # ]:          0 :                 if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
     799                 :          0 :                         den *= 2;
     800         [ #  # ]:          0 :                 if (mode->vscan > 1)
     801                 :          0 :                         den *= mode->vscan;
     802                 :            : 
     803                 :          0 :                 refresh = DIV_ROUND_CLOSEST(num, den);
     804                 :            :         }
     805                 :          0 :         return refresh;
     806                 :            : }
     807                 :            : EXPORT_SYMBOL(drm_mode_vrefresh);
     808                 :            : 
     809                 :            : /**
     810                 :            :  * drm_mode_get_hv_timing - Fetches hdisplay/vdisplay for given mode
     811                 :            :  * @mode: mode to query
     812                 :            :  * @hdisplay: hdisplay value to fill in
     813                 :            :  * @vdisplay: vdisplay value to fill in
     814                 :            :  *
     815                 :            :  * The vdisplay value will be doubled if the specified mode is a stereo mode of
     816                 :            :  * the appropriate layout.
     817                 :            :  */
     818                 :          0 : void drm_mode_get_hv_timing(const struct drm_display_mode *mode,
     819                 :            :                             int *hdisplay, int *vdisplay)
     820                 :            : {
     821                 :          0 :         struct drm_display_mode adjusted = *mode;
     822                 :            : 
     823                 :          0 :         drm_mode_set_crtcinfo(&adjusted, CRTC_STEREO_DOUBLE_ONLY);
     824                 :          0 :         *hdisplay = adjusted.crtc_hdisplay;
     825                 :          0 :         *vdisplay = adjusted.crtc_vdisplay;
     826                 :          0 : }
     827                 :            : EXPORT_SYMBOL(drm_mode_get_hv_timing);
     828                 :            : 
     829                 :            : /**
     830                 :            :  * drm_mode_set_crtcinfo - set CRTC modesetting timing parameters
     831                 :            :  * @p: mode
     832                 :            :  * @adjust_flags: a combination of adjustment flags
     833                 :            :  *
     834                 :            :  * Setup the CRTC modesetting timing parameters for @p, adjusting if necessary.
     835                 :            :  *
     836                 :            :  * - The CRTC_INTERLACE_HALVE_V flag can be used to halve vertical timings of
     837                 :            :  *   interlaced modes.
     838                 :            :  * - The CRTC_STEREO_DOUBLE flag can be used to compute the timings for
     839                 :            :  *   buffers containing two eyes (only adjust the timings when needed, eg. for
     840                 :            :  *   "frame packing" or "side by side full").
     841                 :            :  * - The CRTC_NO_DBLSCAN and CRTC_NO_VSCAN flags request that adjustment *not*
     842                 :            :  *   be performed for doublescan and vscan > 1 modes respectively.
     843                 :            :  */
     844                 :          0 : void drm_mode_set_crtcinfo(struct drm_display_mode *p, int adjust_flags)
     845                 :            : {
     846         [ #  # ]:          0 :         if (!p)
     847                 :            :                 return;
     848                 :            : 
     849                 :          0 :         p->crtc_clock = p->clock;
     850                 :          0 :         p->crtc_hdisplay = p->hdisplay;
     851                 :          0 :         p->crtc_hsync_start = p->hsync_start;
     852                 :          0 :         p->crtc_hsync_end = p->hsync_end;
     853                 :          0 :         p->crtc_htotal = p->htotal;
     854                 :          0 :         p->crtc_hskew = p->hskew;
     855                 :          0 :         p->crtc_vdisplay = p->vdisplay;
     856                 :          0 :         p->crtc_vsync_start = p->vsync_start;
     857                 :          0 :         p->crtc_vsync_end = p->vsync_end;
     858                 :          0 :         p->crtc_vtotal = p->vtotal;
     859                 :            : 
     860         [ #  # ]:          0 :         if (p->flags & DRM_MODE_FLAG_INTERLACE) {
     861         [ #  # ]:          0 :                 if (adjust_flags & CRTC_INTERLACE_HALVE_V) {
     862                 :          0 :                         p->crtc_vdisplay /= 2;
     863                 :          0 :                         p->crtc_vsync_start /= 2;
     864                 :          0 :                         p->crtc_vsync_end /= 2;
     865                 :          0 :                         p->crtc_vtotal /= 2;
     866                 :            :                 }
     867                 :            :         }
     868                 :            : 
     869         [ #  # ]:          0 :         if (!(adjust_flags & CRTC_NO_DBLSCAN)) {
     870         [ #  # ]:          0 :                 if (p->flags & DRM_MODE_FLAG_DBLSCAN) {
     871                 :          0 :                         p->crtc_vdisplay *= 2;
     872                 :          0 :                         p->crtc_vsync_start *= 2;
     873                 :          0 :                         p->crtc_vsync_end *= 2;
     874                 :          0 :                         p->crtc_vtotal *= 2;
     875                 :            :                 }
     876                 :            :         }
     877                 :            : 
     878         [ #  # ]:          0 :         if (!(adjust_flags & CRTC_NO_VSCAN)) {
     879         [ #  # ]:          0 :                 if (p->vscan > 1) {
     880                 :          0 :                         p->crtc_vdisplay *= p->vscan;
     881                 :          0 :                         p->crtc_vsync_start *= p->vscan;
     882                 :          0 :                         p->crtc_vsync_end *= p->vscan;
     883                 :          0 :                         p->crtc_vtotal *= p->vscan;
     884                 :            :                 }
     885                 :            :         }
     886                 :            : 
     887         [ #  # ]:          0 :         if (adjust_flags & CRTC_STEREO_DOUBLE) {
     888                 :          0 :                 unsigned int layout = p->flags & DRM_MODE_FLAG_3D_MASK;
     889                 :            : 
     890         [ #  # ]:          0 :                 switch (layout) {
     891                 :          0 :                 case DRM_MODE_FLAG_3D_FRAME_PACKING:
     892                 :          0 :                         p->crtc_clock *= 2;
     893                 :          0 :                         p->crtc_vdisplay += p->crtc_vtotal;
     894                 :          0 :                         p->crtc_vsync_start += p->crtc_vtotal;
     895                 :          0 :                         p->crtc_vsync_end += p->crtc_vtotal;
     896                 :          0 :                         p->crtc_vtotal += p->crtc_vtotal;
     897                 :          0 :                         break;
     898                 :            :                 }
     899                 :          0 :         }
     900                 :            : 
     901                 :          0 :         p->crtc_vblank_start = min(p->crtc_vsync_start, p->crtc_vdisplay);
     902                 :          0 :         p->crtc_vblank_end = max(p->crtc_vsync_end, p->crtc_vtotal);
     903                 :          0 :         p->crtc_hblank_start = min(p->crtc_hsync_start, p->crtc_hdisplay);
     904                 :          0 :         p->crtc_hblank_end = max(p->crtc_hsync_end, p->crtc_htotal);
     905                 :            : }
     906                 :            : EXPORT_SYMBOL(drm_mode_set_crtcinfo);
     907                 :            : 
     908                 :            : /**
     909                 :            :  * drm_mode_copy - copy the mode
     910                 :            :  * @dst: mode to overwrite
     911                 :            :  * @src: mode to copy
     912                 :            :  *
     913                 :            :  * Copy an existing mode into another mode, preserving the object id and
     914                 :            :  * list head of the destination mode.
     915                 :            :  */
     916                 :          0 : void drm_mode_copy(struct drm_display_mode *dst, const struct drm_display_mode *src)
     917                 :            : {
     918                 :          0 :         struct list_head head = dst->head;
     919                 :            : 
     920                 :          0 :         *dst = *src;
     921                 :          0 :         dst->head = head;
     922                 :          0 : }
     923                 :            : EXPORT_SYMBOL(drm_mode_copy);
     924                 :            : 
     925                 :            : /**
     926                 :            :  * drm_mode_duplicate - allocate and duplicate an existing mode
     927                 :            :  * @dev: drm_device to allocate the duplicated mode for
     928                 :            :  * @mode: mode to duplicate
     929                 :            :  *
     930                 :            :  * Just allocate a new mode, copy the existing mode into it, and return
     931                 :            :  * a pointer to it.  Used to create new instances of established modes.
     932                 :            :  *
     933                 :            :  * Returns:
     934                 :            :  * Pointer to duplicated mode on success, NULL on error.
     935                 :            :  */
     936                 :          0 : struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev,
     937                 :            :                                             const struct drm_display_mode *mode)
     938                 :            : {
     939                 :          0 :         struct drm_display_mode *nmode;
     940                 :            : 
     941                 :          0 :         nmode = drm_mode_create(dev);
     942                 :          0 :         if (!nmode)
     943                 :            :                 return NULL;
     944                 :            : 
     945                 :          0 :         drm_mode_copy(nmode, mode);
     946                 :            : 
     947                 :          0 :         return nmode;
     948                 :            : }
     949                 :            : EXPORT_SYMBOL(drm_mode_duplicate);
     950                 :            : 
     951                 :          0 : static bool drm_mode_match_timings(const struct drm_display_mode *mode1,
     952                 :            :                                    const struct drm_display_mode *mode2)
     953                 :            : {
     954                 :          0 :         return mode1->hdisplay == mode2->hdisplay &&
     955         [ #  # ]:          0 :                 mode1->hsync_start == mode2->hsync_start &&
     956                 :            :                 mode1->hsync_end == mode2->hsync_end &&
     957         [ #  # ]:          0 :                 mode1->htotal == mode2->htotal &&
     958                 :            :                 mode1->hskew == mode2->hskew &&
     959         [ #  # ]:          0 :                 mode1->vdisplay == mode2->vdisplay &&
     960                 :            :                 mode1->vsync_start == mode2->vsync_start &&
     961         [ #  # ]:          0 :                 mode1->vsync_end == mode2->vsync_end &&
     962         [ #  # ]:          0 :                 mode1->vtotal == mode2->vtotal &&
     963         [ #  # ]:          0 :                 mode1->vscan == mode2->vscan;
     964                 :            : }
     965                 :            : 
     966                 :          0 : static bool drm_mode_match_clock(const struct drm_display_mode *mode1,
     967                 :            :                                   const struct drm_display_mode *mode2)
     968                 :            : {
     969                 :            :         /*
     970                 :            :          * do clock check convert to PICOS
     971                 :            :          * so fb modes get matched the same
     972                 :            :          */
     973         [ #  # ]:          0 :         if (mode1->clock && mode2->clock)
     974                 :          0 :                 return KHZ2PICOS(mode1->clock) == KHZ2PICOS(mode2->clock);
     975                 :            :         else
     976                 :          0 :                 return mode1->clock == mode2->clock;
     977                 :            : }
     978                 :            : 
     979                 :          0 : static bool drm_mode_match_flags(const struct drm_display_mode *mode1,
     980                 :            :                                  const struct drm_display_mode *mode2)
     981                 :            : {
     982                 :          0 :         return (mode1->flags & ~DRM_MODE_FLAG_3D_MASK) ==
     983                 :            :                 (mode2->flags & ~DRM_MODE_FLAG_3D_MASK);
     984                 :            : }
     985                 :            : 
     986                 :          0 : static bool drm_mode_match_3d_flags(const struct drm_display_mode *mode1,
     987                 :            :                                     const struct drm_display_mode *mode2)
     988                 :            : {
     989                 :          0 :         return (mode1->flags & DRM_MODE_FLAG_3D_MASK) ==
     990                 :            :                 (mode2->flags & DRM_MODE_FLAG_3D_MASK);
     991                 :            : }
     992                 :            : 
     993                 :          0 : static bool drm_mode_match_aspect_ratio(const struct drm_display_mode *mode1,
     994                 :            :                                         const struct drm_display_mode *mode2)
     995                 :            : {
     996                 :          0 :         return mode1->picture_aspect_ratio == mode2->picture_aspect_ratio;
     997                 :            : }
     998                 :            : 
     999                 :            : /**
    1000                 :            :  * drm_mode_match - test modes for (partial) equality
    1001                 :            :  * @mode1: first mode
    1002                 :            :  * @mode2: second mode
    1003                 :            :  * @match_flags: which parts need to match (DRM_MODE_MATCH_*)
    1004                 :            :  *
    1005                 :            :  * Check to see if @mode1 and @mode2 are equivalent.
    1006                 :            :  *
    1007                 :            :  * Returns:
    1008                 :            :  * True if the modes are (partially) equal, false otherwise.
    1009                 :            :  */
    1010                 :          0 : bool drm_mode_match(const struct drm_display_mode *mode1,
    1011                 :            :                     const struct drm_display_mode *mode2,
    1012                 :            :                     unsigned int match_flags)
    1013                 :            : {
    1014         [ #  # ]:          0 :         if (!mode1 && !mode2)
    1015                 :            :                 return true;
    1016                 :            : 
    1017         [ #  # ]:          0 :         if (!mode1 || !mode2)
    1018                 :            :                 return false;
    1019                 :            : 
    1020   [ #  #  #  # ]:          0 :         if (match_flags & DRM_MODE_MATCH_TIMINGS &&
    1021                 :            :             !drm_mode_match_timings(mode1, mode2))
    1022                 :            :                 return false;
    1023                 :            : 
    1024   [ #  #  #  # ]:          0 :         if (match_flags & DRM_MODE_MATCH_CLOCK &&
    1025         [ #  # ]:          0 :             !drm_mode_match_clock(mode1, mode2))
    1026                 :            :                 return false;
    1027                 :            : 
    1028         [ #  # ]:          0 :         if (match_flags & DRM_MODE_MATCH_FLAGS &&
    1029         [ #  # ]:          0 :             !drm_mode_match_flags(mode1, mode2))
    1030                 :            :                 return false;
    1031                 :            : 
    1032         [ #  # ]:          0 :         if (match_flags & DRM_MODE_MATCH_3D_FLAGS &&
    1033         [ #  # ]:          0 :             !drm_mode_match_3d_flags(mode1, mode2))
    1034                 :            :                 return false;
    1035                 :            : 
    1036         [ #  # ]:          0 :         if (match_flags & DRM_MODE_MATCH_ASPECT_RATIO &&
    1037         [ #  # ]:          0 :             !drm_mode_match_aspect_ratio(mode1, mode2))
    1038                 :          0 :                 return false;
    1039                 :            : 
    1040                 :            :         return true;
    1041                 :            : }
    1042                 :            : EXPORT_SYMBOL(drm_mode_match);
    1043                 :            : 
    1044                 :            : /**
    1045                 :            :  * drm_mode_equal - test modes for equality
    1046                 :            :  * @mode1: first mode
    1047                 :            :  * @mode2: second mode
    1048                 :            :  *
    1049                 :            :  * Check to see if @mode1 and @mode2 are equivalent.
    1050                 :            :  *
    1051                 :            :  * Returns:
    1052                 :            :  * True if the modes are equal, false otherwise.
    1053                 :            :  */
    1054                 :          0 : bool drm_mode_equal(const struct drm_display_mode *mode1,
    1055                 :            :                     const struct drm_display_mode *mode2)
    1056                 :            : {
    1057                 :          0 :         return drm_mode_match(mode1, mode2,
    1058                 :            :                               DRM_MODE_MATCH_TIMINGS |
    1059                 :            :                               DRM_MODE_MATCH_CLOCK |
    1060                 :            :                               DRM_MODE_MATCH_FLAGS |
    1061                 :            :                               DRM_MODE_MATCH_3D_FLAGS|
    1062                 :            :                               DRM_MODE_MATCH_ASPECT_RATIO);
    1063                 :            : }
    1064                 :            : EXPORT_SYMBOL(drm_mode_equal);
    1065                 :            : 
    1066                 :            : /**
    1067                 :            :  * drm_mode_equal_no_clocks - test modes for equality
    1068                 :            :  * @mode1: first mode
    1069                 :            :  * @mode2: second mode
    1070                 :            :  *
    1071                 :            :  * Check to see if @mode1 and @mode2 are equivalent, but
    1072                 :            :  * don't check the pixel clocks.
    1073                 :            :  *
    1074                 :            :  * Returns:
    1075                 :            :  * True if the modes are equal, false otherwise.
    1076                 :            :  */
    1077                 :          0 : bool drm_mode_equal_no_clocks(const struct drm_display_mode *mode1,
    1078                 :            :                               const struct drm_display_mode *mode2)
    1079                 :            : {
    1080                 :          0 :         return drm_mode_match(mode1, mode2,
    1081                 :            :                               DRM_MODE_MATCH_TIMINGS |
    1082                 :            :                               DRM_MODE_MATCH_FLAGS |
    1083                 :            :                               DRM_MODE_MATCH_3D_FLAGS);
    1084                 :            : }
    1085                 :            : EXPORT_SYMBOL(drm_mode_equal_no_clocks);
    1086                 :            : 
    1087                 :            : /**
    1088                 :            :  * drm_mode_equal_no_clocks_no_stereo - test modes for equality
    1089                 :            :  * @mode1: first mode
    1090                 :            :  * @mode2: second mode
    1091                 :            :  *
    1092                 :            :  * Check to see if @mode1 and @mode2 are equivalent, but
    1093                 :            :  * don't check the pixel clocks nor the stereo layout.
    1094                 :            :  *
    1095                 :            :  * Returns:
    1096                 :            :  * True if the modes are equal, false otherwise.
    1097                 :            :  */
    1098                 :          0 : bool drm_mode_equal_no_clocks_no_stereo(const struct drm_display_mode *mode1,
    1099                 :            :                                         const struct drm_display_mode *mode2)
    1100                 :            : {
    1101                 :          0 :         return drm_mode_match(mode1, mode2,
    1102                 :            :                               DRM_MODE_MATCH_TIMINGS |
    1103                 :            :                               DRM_MODE_MATCH_FLAGS);
    1104                 :            : }
    1105                 :            : EXPORT_SYMBOL(drm_mode_equal_no_clocks_no_stereo);
    1106                 :            : 
    1107                 :            : static enum drm_mode_status
    1108                 :          0 : drm_mode_validate_basic(const struct drm_display_mode *mode)
    1109                 :            : {
    1110         [ #  # ]:          0 :         if (mode->type & ~DRM_MODE_TYPE_ALL)
    1111                 :            :                 return MODE_BAD;
    1112                 :            : 
    1113         [ #  # ]:          0 :         if (mode->flags & ~DRM_MODE_FLAG_ALL)
    1114                 :            :                 return MODE_BAD;
    1115                 :            : 
    1116         [ #  # ]:          0 :         if ((mode->flags & DRM_MODE_FLAG_3D_MASK) > DRM_MODE_FLAG_3D_MAX)
    1117                 :            :                 return MODE_BAD;
    1118                 :            : 
    1119         [ #  # ]:          0 :         if (mode->clock == 0)
    1120                 :            :                 return MODE_CLOCK_LOW;
    1121                 :            : 
    1122         [ #  # ]:          0 :         if (mode->hdisplay == 0 ||
    1123         [ #  # ]:          0 :             mode->hsync_start < mode->hdisplay ||
    1124         [ #  # ]:          0 :             mode->hsync_end < mode->hsync_start ||
    1125         [ #  # ]:          0 :             mode->htotal < mode->hsync_end)
    1126                 :            :                 return MODE_H_ILLEGAL;
    1127                 :            : 
    1128         [ #  # ]:          0 :         if (mode->vdisplay == 0 ||
    1129         [ #  # ]:          0 :             mode->vsync_start < mode->vdisplay ||
    1130         [ #  # ]:          0 :             mode->vsync_end < mode->vsync_start ||
    1131         [ #  # ]:          0 :             mode->vtotal < mode->vsync_end)
    1132                 :          0 :                 return MODE_V_ILLEGAL;
    1133                 :            : 
    1134                 :            :         return MODE_OK;
    1135                 :            : }
    1136                 :            : 
    1137                 :            : /**
    1138                 :            :  * drm_mode_validate_driver - make sure the mode is somewhat sane
    1139                 :            :  * @dev: drm device
    1140                 :            :  * @mode: mode to check
    1141                 :            :  *
    1142                 :            :  * First do basic validation on the mode, and then allow the driver
    1143                 :            :  * to check for device/driver specific limitations via the optional
    1144                 :            :  * &drm_mode_config_helper_funcs.mode_valid hook.
    1145                 :            :  *
    1146                 :            :  * Returns:
    1147                 :            :  * The mode status
    1148                 :            :  */
    1149                 :            : enum drm_mode_status
    1150                 :          0 : drm_mode_validate_driver(struct drm_device *dev,
    1151                 :            :                         const struct drm_display_mode *mode)
    1152                 :            : {
    1153                 :          0 :         enum drm_mode_status status;
    1154                 :            : 
    1155                 :          0 :         status = drm_mode_validate_basic(mode);
    1156         [ #  # ]:          0 :         if (status != MODE_OK)
    1157                 :            :                 return status;
    1158                 :            : 
    1159         [ #  # ]:          0 :         if (dev->mode_config.funcs->mode_valid)
    1160                 :          0 :                 return dev->mode_config.funcs->mode_valid(dev, mode);
    1161                 :            :         else
    1162                 :            :                 return MODE_OK;
    1163                 :            : }
    1164                 :            : EXPORT_SYMBOL(drm_mode_validate_driver);
    1165                 :            : 
    1166                 :            : /**
    1167                 :            :  * drm_mode_validate_size - make sure modes adhere to size constraints
    1168                 :            :  * @mode: mode to check
    1169                 :            :  * @maxX: maximum width
    1170                 :            :  * @maxY: maximum height
    1171                 :            :  *
    1172                 :            :  * This function is a helper which can be used to validate modes against size
    1173                 :            :  * limitations of the DRM device/connector. If a mode is too big its status
    1174                 :            :  * member is updated with the appropriate validation failure code. The list
    1175                 :            :  * itself is not changed.
    1176                 :            :  *
    1177                 :            :  * Returns:
    1178                 :            :  * The mode status
    1179                 :            :  */
    1180                 :            : enum drm_mode_status
    1181                 :          0 : drm_mode_validate_size(const struct drm_display_mode *mode,
    1182                 :            :                        int maxX, int maxY)
    1183                 :            : {
    1184   [ #  #  #  # ]:          0 :         if (maxX > 0 && mode->hdisplay > maxX)
    1185                 :            :                 return MODE_VIRTUAL_X;
    1186                 :            : 
    1187   [ #  #  #  # ]:          0 :         if (maxY > 0 && mode->vdisplay > maxY)
    1188                 :          0 :                 return MODE_VIRTUAL_Y;
    1189                 :            : 
    1190                 :            :         return MODE_OK;
    1191                 :            : }
    1192                 :            : EXPORT_SYMBOL(drm_mode_validate_size);
    1193                 :            : 
    1194                 :            : /**
    1195                 :            :  * drm_mode_validate_ycbcr420 - add 'ycbcr420-only' modes only when allowed
    1196                 :            :  * @mode: mode to check
    1197                 :            :  * @connector: drm connector under action
    1198                 :            :  *
    1199                 :            :  * This function is a helper which can be used to filter out any YCBCR420
    1200                 :            :  * only mode, when the source doesn't support it.
    1201                 :            :  *
    1202                 :            :  * Returns:
    1203                 :            :  * The mode status
    1204                 :            :  */
    1205                 :            : enum drm_mode_status
    1206                 :          0 : drm_mode_validate_ycbcr420(const struct drm_display_mode *mode,
    1207                 :            :                            struct drm_connector *connector)
    1208                 :            : {
    1209                 :          0 :         u8 vic = drm_match_cea_mode(mode);
    1210                 :          0 :         enum drm_mode_status status = MODE_OK;
    1211                 :          0 :         struct drm_hdmi_info *hdmi = &connector->display_info.hdmi;
    1212                 :            : 
    1213         [ #  # ]:          0 :         if (test_bit(vic, hdmi->y420_vdb_modes)) {
    1214         [ #  # ]:          0 :                 if (!connector->ycbcr_420_allowed)
    1215                 :          0 :                         status = MODE_NO_420;
    1216                 :            :         }
    1217                 :            : 
    1218                 :          0 :         return status;
    1219                 :            : }
    1220                 :            : EXPORT_SYMBOL(drm_mode_validate_ycbcr420);
    1221                 :            : 
    1222                 :            : #define MODE_STATUS(status) [MODE_ ## status + 3] = #status
    1223                 :            : 
    1224                 :            : static const char * const drm_mode_status_names[] = {
    1225                 :            :         MODE_STATUS(OK),
    1226                 :            :         MODE_STATUS(HSYNC),
    1227                 :            :         MODE_STATUS(VSYNC),
    1228                 :            :         MODE_STATUS(H_ILLEGAL),
    1229                 :            :         MODE_STATUS(V_ILLEGAL),
    1230                 :            :         MODE_STATUS(BAD_WIDTH),
    1231                 :            :         MODE_STATUS(NOMODE),
    1232                 :            :         MODE_STATUS(NO_INTERLACE),
    1233                 :            :         MODE_STATUS(NO_DBLESCAN),
    1234                 :            :         MODE_STATUS(NO_VSCAN),
    1235                 :            :         MODE_STATUS(MEM),
    1236                 :            :         MODE_STATUS(VIRTUAL_X),
    1237                 :            :         MODE_STATUS(VIRTUAL_Y),
    1238                 :            :         MODE_STATUS(MEM_VIRT),
    1239                 :            :         MODE_STATUS(NOCLOCK),
    1240                 :            :         MODE_STATUS(CLOCK_HIGH),
    1241                 :            :         MODE_STATUS(CLOCK_LOW),
    1242                 :            :         MODE_STATUS(CLOCK_RANGE),
    1243                 :            :         MODE_STATUS(BAD_HVALUE),
    1244                 :            :         MODE_STATUS(BAD_VVALUE),
    1245                 :            :         MODE_STATUS(BAD_VSCAN),
    1246                 :            :         MODE_STATUS(HSYNC_NARROW),
    1247                 :            :         MODE_STATUS(HSYNC_WIDE),
    1248                 :            :         MODE_STATUS(HBLANK_NARROW),
    1249                 :            :         MODE_STATUS(HBLANK_WIDE),
    1250                 :            :         MODE_STATUS(VSYNC_NARROW),
    1251                 :            :         MODE_STATUS(VSYNC_WIDE),
    1252                 :            :         MODE_STATUS(VBLANK_NARROW),
    1253                 :            :         MODE_STATUS(VBLANK_WIDE),
    1254                 :            :         MODE_STATUS(PANEL),
    1255                 :            :         MODE_STATUS(INTERLACE_WIDTH),
    1256                 :            :         MODE_STATUS(ONE_WIDTH),
    1257                 :            :         MODE_STATUS(ONE_HEIGHT),
    1258                 :            :         MODE_STATUS(ONE_SIZE),
    1259                 :            :         MODE_STATUS(NO_REDUCED),
    1260                 :            :         MODE_STATUS(NO_STEREO),
    1261                 :            :         MODE_STATUS(NO_420),
    1262                 :            :         MODE_STATUS(STALE),
    1263                 :            :         MODE_STATUS(BAD),
    1264                 :            :         MODE_STATUS(ERROR),
    1265                 :            : };
    1266                 :            : 
    1267                 :            : #undef MODE_STATUS
    1268                 :            : 
    1269                 :          0 : const char *drm_get_mode_status_name(enum drm_mode_status status)
    1270                 :            : {
    1271                 :          0 :         int index = status + 3;
    1272                 :            : 
    1273   [ #  #  #  #  :          0 :         if (WARN_ON(index < 0 || index >= ARRAY_SIZE(drm_mode_status_names)))
                   #  # ]
    1274                 :            :                 return "";
    1275                 :            : 
    1276                 :          0 :         return drm_mode_status_names[index];
    1277                 :            : }
    1278                 :            : 
    1279                 :            : /**
    1280                 :            :  * drm_mode_prune_invalid - remove invalid modes from mode list
    1281                 :            :  * @dev: DRM device
    1282                 :            :  * @mode_list: list of modes to check
    1283                 :            :  * @verbose: be verbose about it
    1284                 :            :  *
    1285                 :            :  * This helper function can be used to prune a display mode list after
    1286                 :            :  * validation has been completed. All modes whose status is not MODE_OK will be
    1287                 :            :  * removed from the list, and if @verbose the status code and mode name is also
    1288                 :            :  * printed to dmesg.
    1289                 :            :  */
    1290                 :          0 : void drm_mode_prune_invalid(struct drm_device *dev,
    1291                 :            :                             struct list_head *mode_list, bool verbose)
    1292                 :            : {
    1293                 :          0 :         struct drm_display_mode *mode, *t;
    1294                 :            : 
    1295         [ #  # ]:          0 :         list_for_each_entry_safe(mode, t, mode_list, head) {
    1296         [ #  # ]:          0 :                 if (mode->status != MODE_OK) {
    1297         [ #  # ]:          0 :                         list_del(&mode->head);
    1298         [ #  # ]:          0 :                         if (verbose) {
    1299                 :          0 :                                 drm_mode_debug_printmodeline(mode);
    1300         [ #  # ]:          0 :                                 DRM_DEBUG_KMS("Not using %s mode: %s\n",
    1301                 :            :                                               mode->name,
    1302                 :            :                                               drm_get_mode_status_name(mode->status));
    1303                 :            :                         }
    1304         [ #  # ]:          0 :                         drm_mode_destroy(dev, mode);
    1305                 :            :                 }
    1306                 :            :         }
    1307                 :          0 : }
    1308                 :            : EXPORT_SYMBOL(drm_mode_prune_invalid);
    1309                 :            : 
    1310                 :            : /**
    1311                 :            :  * drm_mode_compare - compare modes for favorability
    1312                 :            :  * @priv: unused
    1313                 :            :  * @lh_a: list_head for first mode
    1314                 :            :  * @lh_b: list_head for second mode
    1315                 :            :  *
    1316                 :            :  * Compare two modes, given by @lh_a and @lh_b, returning a value indicating
    1317                 :            :  * which is better.
    1318                 :            :  *
    1319                 :            :  * Returns:
    1320                 :            :  * Negative if @lh_a is better than @lh_b, zero if they're equivalent, or
    1321                 :            :  * positive if @lh_b is better than @lh_a.
    1322                 :            :  */
    1323                 :          0 : static int drm_mode_compare(void *priv, struct list_head *lh_a, struct list_head *lh_b)
    1324                 :            : {
    1325                 :          0 :         struct drm_display_mode *a = list_entry(lh_a, struct drm_display_mode, head);
    1326                 :          0 :         struct drm_display_mode *b = list_entry(lh_b, struct drm_display_mode, head);
    1327                 :          0 :         int diff;
    1328                 :            : 
    1329                 :          0 :         diff = ((b->type & DRM_MODE_TYPE_PREFERRED) != 0) -
    1330                 :          0 :                 ((a->type & DRM_MODE_TYPE_PREFERRED) != 0);
    1331         [ #  # ]:          0 :         if (diff)
    1332                 :            :                 return diff;
    1333                 :          0 :         diff = b->hdisplay * b->vdisplay - a->hdisplay * a->vdisplay;
    1334         [ #  # ]:          0 :         if (diff)
    1335                 :            :                 return diff;
    1336                 :            : 
    1337                 :          0 :         diff = b->vrefresh - a->vrefresh;
    1338         [ #  # ]:          0 :         if (diff)
    1339                 :            :                 return diff;
    1340                 :            : 
    1341                 :          0 :         diff = b->clock - a->clock;
    1342                 :          0 :         return diff;
    1343                 :            : }
    1344                 :            : 
    1345                 :            : /**
    1346                 :            :  * drm_mode_sort - sort mode list
    1347                 :            :  * @mode_list: list of drm_display_mode structures to sort
    1348                 :            :  *
    1349                 :            :  * Sort @mode_list by favorability, moving good modes to the head of the list.
    1350                 :            :  */
    1351                 :          0 : void drm_mode_sort(struct list_head *mode_list)
    1352                 :            : {
    1353                 :          0 :         list_sort(NULL, mode_list, drm_mode_compare);
    1354                 :          0 : }
    1355                 :            : EXPORT_SYMBOL(drm_mode_sort);
    1356                 :            : 
    1357                 :            : /**
    1358                 :            :  * drm_connector_list_update - update the mode list for the connector
    1359                 :            :  * @connector: the connector to update
    1360                 :            :  *
    1361                 :            :  * This moves the modes from the @connector probed_modes list
    1362                 :            :  * to the actual mode list. It compares the probed mode against the current
    1363                 :            :  * list and only adds different/new modes.
    1364                 :            :  *
    1365                 :            :  * This is just a helper functions doesn't validate any modes itself and also
    1366                 :            :  * doesn't prune any invalid modes. Callers need to do that themselves.
    1367                 :            :  */
    1368                 :          0 : void drm_connector_list_update(struct drm_connector *connector)
    1369                 :            : {
    1370                 :          0 :         struct drm_display_mode *pmode, *pt;
    1371                 :            : 
    1372         [ #  # ]:          0 :         WARN_ON(!mutex_is_locked(&connector->dev->mode_config.mutex));
    1373                 :            : 
    1374         [ #  # ]:          0 :         list_for_each_entry_safe(pmode, pt, &connector->probed_modes, head) {
    1375                 :          0 :                 struct drm_display_mode *mode;
    1376                 :          0 :                 bool found_it = false;
    1377                 :            : 
    1378                 :            :                 /* go through current modes checking for the new probed mode */
    1379         [ #  # ]:          0 :                 list_for_each_entry(mode, &connector->modes, head) {
    1380         [ #  # ]:          0 :                         if (!drm_mode_equal(pmode, mode))
    1381                 :          0 :                                 continue;
    1382                 :            : 
    1383                 :          0 :                         found_it = true;
    1384                 :            : 
    1385                 :            :                         /*
    1386                 :            :                          * If the old matching mode is stale (ie. left over
    1387                 :            :                          * from a previous probe) just replace it outright.
    1388                 :            :                          * Otherwise just merge the type bits between all
    1389                 :            :                          * equal probed modes.
    1390                 :            :                          *
    1391                 :            :                          * If two probed modes are considered equal, pick the
    1392                 :            :                          * actual timings from the one that's marked as
    1393                 :            :                          * preferred (in case the match isn't 100%). If
    1394                 :            :                          * multiple or zero preferred modes are present, favor
    1395                 :            :                          * the mode added to the probed_modes list first.
    1396                 :            :                          */
    1397         [ #  # ]:          0 :                         if (mode->status == MODE_STALE) {
    1398                 :          0 :                                 drm_mode_copy(mode, pmode);
    1399         [ #  # ]:          0 :                         } else if ((mode->type & DRM_MODE_TYPE_PREFERRED) == 0 &&
    1400         [ #  # ]:          0 :                                    (pmode->type & DRM_MODE_TYPE_PREFERRED) != 0) {
    1401                 :          0 :                                 pmode->type |= mode->type;
    1402                 :          0 :                                 drm_mode_copy(mode, pmode);
    1403                 :            :                         } else {
    1404                 :          0 :                                 mode->type |= pmode->type;
    1405                 :            :                         }
    1406                 :            : 
    1407         [ #  # ]:          0 :                         list_del(&pmode->head);
    1408         [ #  # ]:          0 :                         drm_mode_destroy(connector->dev, pmode);
    1409                 :            :                         break;
    1410                 :            :                 }
    1411                 :            : 
    1412                 :          0 :                 if (!found_it) {
    1413                 :          0 :                         list_move_tail(&pmode->head, &connector->modes);
    1414                 :            :                 }
    1415                 :            :         }
    1416                 :          0 : }
    1417                 :            : EXPORT_SYMBOL(drm_connector_list_update);
    1418                 :            : 
    1419                 :          0 : static int drm_mode_parse_cmdline_bpp(const char *str, char **end_ptr,
    1420                 :            :                                       struct drm_cmdline_mode *mode)
    1421                 :            : {
    1422                 :          0 :         unsigned int bpp;
    1423                 :            : 
    1424                 :          0 :         if (str[0] != '-')
    1425                 :            :                 return -EINVAL;
    1426                 :            : 
    1427                 :          0 :         str++;
    1428                 :          0 :         bpp = simple_strtol(str, end_ptr, 10);
    1429         [ #  # ]:          0 :         if (*end_ptr == str)
    1430                 :            :                 return -EINVAL;
    1431                 :            : 
    1432                 :          0 :         mode->bpp = bpp;
    1433                 :          0 :         mode->bpp_specified = true;
    1434                 :            : 
    1435                 :          0 :         return 0;
    1436                 :            : }
    1437                 :            : 
    1438                 :          0 : static int drm_mode_parse_cmdline_refresh(const char *str, char **end_ptr,
    1439                 :            :                                           struct drm_cmdline_mode *mode)
    1440                 :            : {
    1441                 :          0 :         unsigned int refresh;
    1442                 :            : 
    1443                 :          0 :         if (str[0] != '@')
    1444                 :            :                 return -EINVAL;
    1445                 :            : 
    1446                 :          0 :         str++;
    1447                 :          0 :         refresh = simple_strtol(str, end_ptr, 10);
    1448         [ #  # ]:          0 :         if (*end_ptr == str)
    1449                 :            :                 return -EINVAL;
    1450                 :            : 
    1451                 :          0 :         mode->refresh = refresh;
    1452                 :          0 :         mode->refresh_specified = true;
    1453                 :            : 
    1454                 :          0 :         return 0;
    1455                 :            : }
    1456                 :            : 
    1457                 :          0 : static int drm_mode_parse_cmdline_extra(const char *str, int length,
    1458                 :            :                                         bool freestanding,
    1459                 :            :                                         const struct drm_connector *connector,
    1460                 :            :                                         struct drm_cmdline_mode *mode)
    1461                 :            : {
    1462                 :          0 :         int i;
    1463                 :            : 
    1464         [ #  # ]:          0 :         for (i = 0; i < length; i++) {
    1465   [ #  #  #  #  :          0 :                 switch (str[i]) {
                   #  # ]
    1466                 :          0 :                 case 'i':
    1467         [ #  # ]:          0 :                         if (freestanding)
    1468                 :            :                                 return -EINVAL;
    1469                 :            : 
    1470                 :          0 :                         mode->interlace = true;
    1471                 :          0 :                         break;
    1472                 :          0 :                 case 'm':
    1473         [ #  # ]:          0 :                         if (freestanding)
    1474                 :            :                                 return -EINVAL;
    1475                 :            : 
    1476                 :          0 :                         mode->margins = true;
    1477                 :          0 :                         break;
    1478                 :          0 :                 case 'D':
    1479         [ #  # ]:          0 :                         if (mode->force != DRM_FORCE_UNSPECIFIED)
    1480                 :            :                                 return -EINVAL;
    1481                 :            : 
    1482         [ #  # ]:          0 :                         if ((connector->connector_type != DRM_MODE_CONNECTOR_DVII) &&
    1483                 :            :                             (connector->connector_type != DRM_MODE_CONNECTOR_HDMIB))
    1484                 :          0 :                                 mode->force = DRM_FORCE_ON;
    1485                 :            :                         else
    1486                 :          0 :                                 mode->force = DRM_FORCE_ON_DIGITAL;
    1487                 :            :                         break;
    1488                 :          0 :                 case 'd':
    1489         [ #  # ]:          0 :                         if (mode->force != DRM_FORCE_UNSPECIFIED)
    1490                 :            :                                 return -EINVAL;
    1491                 :            : 
    1492                 :          0 :                         mode->force = DRM_FORCE_OFF;
    1493                 :          0 :                         break;
    1494                 :          0 :                 case 'e':
    1495         [ #  # ]:          0 :                         if (mode->force != DRM_FORCE_UNSPECIFIED)
    1496                 :            :                                 return -EINVAL;
    1497                 :            : 
    1498                 :          0 :                         mode->force = DRM_FORCE_ON;
    1499                 :          0 :                         break;
    1500                 :            :                 default:
    1501                 :            :                         return -EINVAL;
    1502                 :            :                 }
    1503                 :            :         }
    1504                 :            : 
    1505                 :            :         return 0;
    1506                 :            : }
    1507                 :            : 
    1508                 :          0 : static int drm_mode_parse_cmdline_res_mode(const char *str, unsigned int length,
    1509                 :            :                                            bool extras,
    1510                 :            :                                            const struct drm_connector *connector,
    1511                 :            :                                            struct drm_cmdline_mode *mode)
    1512                 :            : {
    1513                 :          0 :         const char *str_start = str;
    1514                 :          0 :         bool rb = false, cvt = false;
    1515                 :          0 :         int xres = 0, yres = 0;
    1516                 :          0 :         int remaining, i;
    1517                 :          0 :         char *end_ptr;
    1518                 :            : 
    1519                 :          0 :         xres = simple_strtol(str, &end_ptr, 10);
    1520         [ #  # ]:          0 :         if (end_ptr == str)
    1521                 :            :                 return -EINVAL;
    1522                 :            : 
    1523         [ #  # ]:          0 :         if (end_ptr[0] != 'x')
    1524                 :            :                 return -EINVAL;
    1525                 :          0 :         end_ptr++;
    1526                 :            : 
    1527                 :          0 :         str = end_ptr;
    1528                 :          0 :         yres = simple_strtol(str, &end_ptr, 10);
    1529         [ #  # ]:          0 :         if (end_ptr == str)
    1530                 :            :                 return -EINVAL;
    1531                 :            : 
    1532                 :          0 :         remaining = length - (end_ptr - str_start);
    1533         [ #  # ]:          0 :         if (remaining < 0)
    1534                 :            :                 return -EINVAL;
    1535                 :            : 
    1536         [ #  # ]:          0 :         for (i = 0; i < remaining; i++) {
    1537      [ #  #  # ]:          0 :                 switch (end_ptr[i]) {
    1538                 :            :                 case 'M':
    1539                 :            :                         cvt = true;
    1540                 :            :                         break;
    1541                 :          0 :                 case 'R':
    1542                 :          0 :                         rb = true;
    1543                 :          0 :                         break;
    1544                 :          0 :                 default:
    1545                 :            :                         /*
    1546                 :            :                          * Try to pass that to our extras parsing
    1547                 :            :                          * function to handle the case where the
    1548                 :            :                          * extras are directly after the resolution
    1549                 :            :                          */
    1550         [ #  # ]:          0 :                         if (extras) {
    1551                 :          0 :                                 int ret = drm_mode_parse_cmdline_extra(end_ptr + i,
    1552                 :            :                                                                        1,
    1553                 :            :                                                                        false,
    1554                 :            :                                                                        connector,
    1555                 :            :                                                                        mode);
    1556         [ #  # ]:          0 :                                 if (ret)
    1557                 :          0 :                                         return ret;
    1558                 :            :                         } else {
    1559                 :            :                                 return -EINVAL;
    1560                 :            :                         }
    1561                 :            :                 }
    1562                 :            :         }
    1563                 :            : 
    1564                 :          0 :         mode->xres = xres;
    1565                 :          0 :         mode->yres = yres;
    1566                 :          0 :         mode->cvt = cvt;
    1567                 :          0 :         mode->rb = rb;
    1568                 :            : 
    1569                 :          0 :         return 0;
    1570                 :            : }
    1571                 :            : 
    1572                 :          0 : static int drm_mode_parse_cmdline_int(const char *delim, unsigned int *int_ret)
    1573                 :            : {
    1574                 :          0 :         const char *value;
    1575                 :          0 :         char *endp;
    1576                 :            : 
    1577                 :            :         /*
    1578                 :            :          * delim must point to the '=', otherwise it is a syntax error and
    1579                 :            :          * if delim points to the terminating zero, then delim + 1 wil point
    1580                 :            :          * past the end of the string.
    1581                 :            :          */
    1582         [ #  # ]:          0 :         if (*delim != '=')
    1583                 :            :                 return -EINVAL;
    1584                 :            : 
    1585                 :          0 :         value = delim + 1;
    1586                 :          0 :         *int_ret = simple_strtol(value, &endp, 10);
    1587                 :            : 
    1588                 :            :         /* Make sure we have parsed something */
    1589         [ #  # ]:          0 :         if (endp == value)
    1590                 :          0 :                 return -EINVAL;
    1591                 :            : 
    1592                 :            :         return 0;
    1593                 :            : }
    1594                 :            : 
    1595                 :            : static int drm_mode_parse_panel_orientation(const char *delim,
    1596                 :            :                                             struct drm_cmdline_mode *mode)
    1597                 :            : {
    1598                 :            :         const char *value;
    1599                 :            : 
    1600                 :            :         if (*delim != '=')
    1601                 :            :                 return -EINVAL;
    1602                 :            : 
    1603                 :            :         value = delim + 1;
    1604                 :            :         delim = strchr(value, ',');
    1605                 :            :         if (!delim)
    1606                 :            :                 delim = value + strlen(value);
    1607                 :            : 
    1608                 :            :         if (!strncmp(value, "normal", delim - value))
    1609                 :            :                 mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_NORMAL;
    1610                 :            :         else if (!strncmp(value, "upside_down", delim - value))
    1611                 :            :                 mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP;
    1612                 :            :         else if (!strncmp(value, "left_side_up", delim - value))
    1613                 :            :                 mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP;
    1614                 :            :         else if (!strncmp(value, "right_side_up", delim - value))
    1615                 :            :                 mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP;
    1616                 :            :         else
    1617                 :            :                 return -EINVAL;
    1618                 :            : 
    1619                 :            :         return 0;
    1620                 :            : }
    1621                 :            : 
    1622                 :          0 : static int drm_mode_parse_cmdline_options(const char *str,
    1623                 :            :                                           bool freestanding,
    1624                 :            :                                           const struct drm_connector *connector,
    1625                 :            :                                           struct drm_cmdline_mode *mode)
    1626                 :            : {
    1627                 :          0 :         unsigned int deg, margin, rotation = 0;
    1628                 :          0 :         const char *delim, *option, *sep;
    1629                 :            : 
    1630                 :          0 :         option = str;
    1631                 :          0 :         do {
    1632                 :          0 :                 delim = strchr(option, '=');
    1633         [ #  # ]:          0 :                 if (!delim) {
    1634                 :          0 :                         delim = strchr(option, ',');
    1635                 :            : 
    1636         [ #  # ]:          0 :                         if (!delim)
    1637                 :          0 :                                 delim = option + strlen(option);
    1638                 :            :                 }
    1639                 :            : 
    1640         [ #  # ]:          0 :                 if (!strncmp(option, "rotate", delim - option)) {
    1641         [ #  # ]:          0 :                         if (drm_mode_parse_cmdline_int(delim, &deg))
    1642                 :            :                                 return -EINVAL;
    1643                 :            : 
    1644   [ #  #  #  #  :          0 :                         switch (deg) {
                      # ]
    1645                 :          0 :                         case 0:
    1646                 :          0 :                                 rotation |= DRM_MODE_ROTATE_0;
    1647                 :          0 :                                 break;
    1648                 :            : 
    1649                 :          0 :                         case 90:
    1650                 :          0 :                                 rotation |= DRM_MODE_ROTATE_90;
    1651                 :          0 :                                 break;
    1652                 :            : 
    1653                 :          0 :                         case 180:
    1654                 :          0 :                                 rotation |= DRM_MODE_ROTATE_180;
    1655                 :          0 :                                 break;
    1656                 :            : 
    1657                 :          0 :                         case 270:
    1658                 :          0 :                                 rotation |= DRM_MODE_ROTATE_270;
    1659                 :          0 :                                 break;
    1660                 :            : 
    1661                 :            :                         default:
    1662                 :            :                                 return -EINVAL;
    1663                 :            :                         }
    1664         [ #  # ]:          0 :                 } else if (!strncmp(option, "reflect_x", delim - option)) {
    1665                 :          0 :                         rotation |= DRM_MODE_REFLECT_X;
    1666         [ #  # ]:          0 :                 } else if (!strncmp(option, "reflect_y", delim - option)) {
    1667                 :          0 :                         rotation |= DRM_MODE_REFLECT_Y;
    1668         [ #  # ]:          0 :                 } else if (!strncmp(option, "margin_right", delim - option)) {
    1669         [ #  # ]:          0 :                         if (drm_mode_parse_cmdline_int(delim, &margin))
    1670                 :            :                                 return -EINVAL;
    1671                 :            : 
    1672                 :          0 :                         mode->tv_margins.right = margin;
    1673         [ #  # ]:          0 :                 } else if (!strncmp(option, "margin_left", delim - option)) {
    1674         [ #  # ]:          0 :                         if (drm_mode_parse_cmdline_int(delim, &margin))
    1675                 :            :                                 return -EINVAL;
    1676                 :            : 
    1677                 :          0 :                         mode->tv_margins.left = margin;
    1678         [ #  # ]:          0 :                 } else if (!strncmp(option, "margin_top", delim - option)) {
    1679         [ #  # ]:          0 :                         if (drm_mode_parse_cmdline_int(delim, &margin))
    1680                 :            :                                 return -EINVAL;
    1681                 :            : 
    1682                 :          0 :                         mode->tv_margins.top = margin;
    1683         [ #  # ]:          0 :                 } else if (!strncmp(option, "margin_bottom", delim - option)) {
    1684         [ #  # ]:          0 :                         if (drm_mode_parse_cmdline_int(delim, &margin))
    1685                 :            :                                 return -EINVAL;
    1686                 :            : 
    1687                 :          0 :                         mode->tv_margins.bottom = margin;
    1688         [ #  # ]:          0 :                 } else if (!strncmp(option, "panel_orientation", delim - option)) {
    1689         [ #  # ]:          0 :                         if (drm_mode_parse_panel_orientation(delim, mode))
    1690                 :            :                                 return -EINVAL;
    1691                 :            :                 } else {
    1692                 :            :                         return -EINVAL;
    1693                 :            :                 }
    1694                 :          0 :                 sep = strchr(delim, ',');
    1695                 :          0 :                 option = sep + 1;
    1696         [ #  # ]:          0 :         } while (sep);
    1697                 :            : 
    1698         [ #  # ]:          0 :         if (rotation && freestanding)
    1699                 :            :                 return -EINVAL;
    1700                 :            : 
    1701         [ #  # ]:          0 :         if (!(rotation & DRM_MODE_ROTATE_MASK))
    1702                 :          0 :                 rotation |= DRM_MODE_ROTATE_0;
    1703                 :            : 
    1704                 :            :         /* Make sure there is exactly one rotation defined */
    1705   [ #  #  #  # ]:          0 :         if (!is_power_of_2(rotation & DRM_MODE_ROTATE_MASK))
    1706                 :            :                 return -EINVAL;
    1707                 :            : 
    1708                 :          0 :         mode->rotation_reflection = rotation;
    1709                 :            : 
    1710                 :          0 :         return 0;
    1711                 :            : }
    1712                 :            : 
    1713                 :            : static const char * const drm_named_modes_whitelist[] = {
    1714                 :            :         "NTSC",
    1715                 :            :         "PAL",
    1716                 :            : };
    1717                 :            : 
    1718                 :            : /**
    1719                 :            :  * drm_mode_parse_command_line_for_connector - parse command line modeline for connector
    1720                 :            :  * @mode_option: optional per connector mode option
    1721                 :            :  * @connector: connector to parse modeline for
    1722                 :            :  * @mode: preallocated drm_cmdline_mode structure to fill out
    1723                 :            :  *
    1724                 :            :  * This parses @mode_option command line modeline for modes and options to
    1725                 :            :  * configure the connector. If @mode_option is NULL the default command line
    1726                 :            :  * modeline in fb_mode_option will be parsed instead.
    1727                 :            :  *
    1728                 :            :  * This uses the same parameters as the fb modedb.c, except for an extra
    1729                 :            :  * force-enable, force-enable-digital and force-disable bit at the end::
    1730                 :            :  *
    1731                 :            :  *      <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m][eDd]
    1732                 :            :  *
    1733                 :            :  * Additionals options can be provided following the mode, using a comma to
    1734                 :            :  * separate each option. Valid options can be found in
    1735                 :            :  * Documentation/fb/modedb.rst.
    1736                 :            :  *
    1737                 :            :  * The intermediate drm_cmdline_mode structure is required to store additional
    1738                 :            :  * options from the command line modline like the force-enable/disable flag.
    1739                 :            :  *
    1740                 :            :  * Returns:
    1741                 :            :  * True if a valid modeline has been parsed, false otherwise.
    1742                 :            :  */
    1743                 :          0 : bool drm_mode_parse_command_line_for_connector(const char *mode_option,
    1744                 :            :                                                const struct drm_connector *connector,
    1745                 :            :                                                struct drm_cmdline_mode *mode)
    1746                 :            : {
    1747                 :          0 :         const char *name;
    1748                 :          0 :         bool freestanding = false, parse_extras = false;
    1749                 :          0 :         unsigned int bpp_off = 0, refresh_off = 0, options_off = 0;
    1750                 :          0 :         unsigned int mode_end = 0;
    1751                 :          0 :         const char *bpp_ptr = NULL, *refresh_ptr = NULL, *extra_ptr = NULL;
    1752                 :          0 :         const char *options_ptr = NULL;
    1753                 :          0 :         char *bpp_end_ptr = NULL, *refresh_end_ptr = NULL;
    1754                 :          0 :         int i, len, ret;
    1755                 :            : 
    1756                 :          0 :         memset(mode, 0, sizeof(*mode));
    1757                 :          0 :         mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
    1758                 :            : 
    1759         [ #  # ]:          0 :         if (!mode_option)
    1760                 :            :                 return false;
    1761                 :            : 
    1762                 :          0 :         name = mode_option;
    1763                 :            : 
    1764                 :            :         /* Try to locate the bpp and refresh specifiers, if any */
    1765                 :          0 :         bpp_ptr = strchr(name, '-');
    1766         [ #  # ]:          0 :         if (bpp_ptr)
    1767                 :          0 :                 bpp_off = bpp_ptr - name;
    1768                 :            : 
    1769                 :          0 :         refresh_ptr = strchr(name, '@');
    1770         [ #  # ]:          0 :         if (refresh_ptr)
    1771                 :          0 :                 refresh_off = refresh_ptr - name;
    1772                 :            : 
    1773                 :            :         /* Locate the start of named options */
    1774                 :          0 :         options_ptr = strchr(name, ',');
    1775         [ #  # ]:          0 :         if (options_ptr)
    1776                 :          0 :                 options_off = options_ptr - name;
    1777                 :            : 
    1778                 :            :         /* Locate the end of the name / resolution, and parse it */
    1779         [ #  # ]:          0 :         if (bpp_ptr) {
    1780                 :            :                 mode_end = bpp_off;
    1781         [ #  # ]:          0 :         } else if (refresh_ptr) {
    1782                 :            :                 mode_end = refresh_off;
    1783         [ #  # ]:          0 :         } else if (options_ptr) {
    1784                 :            :                 mode_end = options_off;
    1785                 :            :                 parse_extras = true;
    1786                 :            :         } else {
    1787                 :          0 :                 mode_end = strlen(name);
    1788                 :          0 :                 parse_extras = true;
    1789                 :            :         }
    1790                 :            : 
    1791                 :            :         /* First check for a named mode */
    1792         [ #  # ]:          0 :         for (i = 0; i < ARRAY_SIZE(drm_named_modes_whitelist); i++) {
    1793         [ #  # ]:          0 :                 ret = str_has_prefix(name, drm_named_modes_whitelist[i]);
    1794         [ #  # ]:          0 :                 if (ret == mode_end) {
    1795         [ #  # ]:          0 :                         if (refresh_ptr)
    1796                 :            :                                 return false; /* named + refresh is invalid */
    1797                 :            : 
    1798                 :          0 :                         strcpy(mode->name, drm_named_modes_whitelist[i]);
    1799                 :          0 :                         mode->specified = true;
    1800                 :          0 :                         break;
    1801                 :            :                 }
    1802                 :            :         }
    1803                 :            : 
    1804                 :            :         /* No named mode? Check for a normal mode argument, e.g. 1024x768 */
    1805   [ #  #  #  # ]:          0 :         if (!mode->specified && isdigit(name[0])) {
    1806                 :          0 :                 ret = drm_mode_parse_cmdline_res_mode(name, mode_end,
    1807                 :            :                                                       parse_extras,
    1808                 :            :                                                       connector,
    1809                 :            :                                                       mode);
    1810         [ #  # ]:          0 :                 if (ret)
    1811                 :            :                         return false;
    1812                 :            : 
    1813                 :          0 :                 mode->specified = true;
    1814                 :            :         }
    1815                 :            : 
    1816                 :            :         /* No mode? Check for freestanding extras and/or options */
    1817         [ #  # ]:          0 :         if (!mode->specified) {
    1818                 :          0 :                 unsigned int len = strlen(mode_option);
    1819                 :            : 
    1820         [ #  # ]:          0 :                 if (bpp_ptr || refresh_ptr)
    1821                 :            :                         return false; /* syntax error */
    1822                 :            : 
    1823   [ #  #  #  #  :          0 :                 if (len == 1 || (len >= 2 && mode_option[1] == ','))
                   #  # ]
    1824                 :            :                         extra_ptr = mode_option;
    1825                 :            :                 else
    1826                 :          0 :                         options_ptr = mode_option - 1;
    1827                 :            : 
    1828                 :            :                 freestanding = true;
    1829                 :            :         }
    1830                 :            : 
    1831         [ #  # ]:          0 :         if (bpp_ptr) {
    1832         [ #  # ]:          0 :                 ret = drm_mode_parse_cmdline_bpp(bpp_ptr, &bpp_end_ptr, mode);
    1833                 :          0 :                 if (ret)
    1834                 :          0 :                         return false;
    1835                 :            : 
    1836                 :          0 :                 mode->bpp_specified = true;
    1837                 :            :         }
    1838                 :            : 
    1839         [ #  # ]:          0 :         if (refresh_ptr) {
    1840         [ #  # ]:          0 :                 ret = drm_mode_parse_cmdline_refresh(refresh_ptr,
    1841                 :            :                                                      &refresh_end_ptr, mode);
    1842                 :          0 :                 if (ret)
    1843                 :          0 :                         return false;
    1844                 :            : 
    1845                 :          0 :                 mode->refresh_specified = true;
    1846                 :            :         }
    1847                 :            : 
    1848                 :            :         /*
    1849                 :            :          * Locate the end of the bpp / refresh, and parse the extras
    1850                 :            :          * if relevant
    1851                 :            :          */
    1852         [ #  # ]:          0 :         if (bpp_ptr && refresh_ptr)
    1853                 :          0 :                 extra_ptr = max(bpp_end_ptr, refresh_end_ptr);
    1854         [ #  # ]:          0 :         else if (bpp_ptr)
    1855                 :          0 :                 extra_ptr = bpp_end_ptr;
    1856         [ #  # ]:          0 :         else if (refresh_ptr)
    1857                 :          0 :                 extra_ptr = refresh_end_ptr;
    1858                 :            : 
    1859         [ #  # ]:          0 :         if (extra_ptr) {
    1860         [ #  # ]:          0 :                 if (options_ptr)
    1861                 :          0 :                         len = options_ptr - extra_ptr;
    1862                 :            :                 else
    1863                 :          0 :                         len = strlen(extra_ptr);
    1864                 :            : 
    1865                 :          0 :                 ret = drm_mode_parse_cmdline_extra(extra_ptr, len, freestanding,
    1866                 :            :                                                    connector, mode);
    1867         [ #  # ]:          0 :                 if (ret)
    1868                 :            :                         return false;
    1869                 :            :         }
    1870                 :            : 
    1871         [ #  # ]:          0 :         if (options_ptr) {
    1872                 :          0 :                 ret = drm_mode_parse_cmdline_options(options_ptr + 1,
    1873                 :            :                                                      freestanding,
    1874                 :            :                                                      connector, mode);
    1875         [ #  # ]:          0 :                 if (ret)
    1876                 :          0 :                         return false;
    1877                 :            :         }
    1878                 :            : 
    1879                 :            :         return true;
    1880                 :            : }
    1881                 :            : EXPORT_SYMBOL(drm_mode_parse_command_line_for_connector);
    1882                 :            : 
    1883                 :            : /**
    1884                 :            :  * drm_mode_create_from_cmdline_mode - convert a command line modeline into a DRM display mode
    1885                 :            :  * @dev: DRM device to create the new mode for
    1886                 :            :  * @cmd: input command line modeline
    1887                 :            :  *
    1888                 :            :  * Returns:
    1889                 :            :  * Pointer to converted mode on success, NULL on error.
    1890                 :            :  */
    1891                 :            : struct drm_display_mode *
    1892                 :          0 : drm_mode_create_from_cmdline_mode(struct drm_device *dev,
    1893                 :            :                                   struct drm_cmdline_mode *cmd)
    1894                 :            : {
    1895                 :          0 :         struct drm_display_mode *mode;
    1896                 :            : 
    1897         [ #  # ]:          0 :         if (cmd->cvt)
    1898                 :          0 :                 mode = drm_cvt_mode(dev,
    1899                 :            :                                     cmd->xres, cmd->yres,
    1900                 :          0 :                                     cmd->refresh_specified ? cmd->refresh : 60,
    1901                 :          0 :                                     cmd->rb, cmd->interlace,
    1902         [ #  # ]:          0 :                                     cmd->margins);
    1903                 :            :         else
    1904                 :          0 :                 mode = drm_gtf_mode(dev,
    1905                 :            :                                     cmd->xres, cmd->yres,
    1906                 :          0 :                                     cmd->refresh_specified ? cmd->refresh : 60,
    1907                 :          0 :                                     cmd->interlace,
    1908         [ #  # ]:          0 :                                     cmd->margins);
    1909         [ #  # ]:          0 :         if (!mode)
    1910                 :            :                 return NULL;
    1911                 :            : 
    1912                 :          0 :         mode->type |= DRM_MODE_TYPE_USERDEF;
    1913                 :            :         /* fix up 1368x768: GFT/CVT can't express 1366 width due to alignment */
    1914         [ #  # ]:          0 :         if (cmd->xres == 1366)
    1915                 :          0 :                 drm_mode_fixup_1366x768(mode);
    1916                 :          0 :         drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
    1917                 :          0 :         return mode;
    1918                 :            : }
    1919                 :            : EXPORT_SYMBOL(drm_mode_create_from_cmdline_mode);
    1920                 :            : 
    1921                 :            : /**
    1922                 :            :  * drm_crtc_convert_to_umode - convert a drm_display_mode into a modeinfo
    1923                 :            :  * @out: drm_mode_modeinfo struct to return to the user
    1924                 :            :  * @in: drm_display_mode to use
    1925                 :            :  *
    1926                 :            :  * Convert a drm_display_mode into a drm_mode_modeinfo structure to return to
    1927                 :            :  * the user.
    1928                 :            :  */
    1929                 :          0 : void drm_mode_convert_to_umode(struct drm_mode_modeinfo *out,
    1930                 :            :                                const struct drm_display_mode *in)
    1931                 :            : {
    1932   [ #  #  #  #  :          0 :         WARN(in->hdisplay > USHRT_MAX || in->hsync_start > USHRT_MAX ||
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
    1933                 :            :              in->hsync_end > USHRT_MAX || in->htotal > USHRT_MAX ||
    1934                 :            :              in->hskew > USHRT_MAX || in->vdisplay > USHRT_MAX ||
    1935                 :            :              in->vsync_start > USHRT_MAX || in->vsync_end > USHRT_MAX ||
    1936                 :            :              in->vtotal > USHRT_MAX || in->vscan > USHRT_MAX,
    1937                 :            :              "timing values too large for mode info\n");
    1938                 :            : 
    1939                 :          0 :         out->clock = in->clock;
    1940                 :          0 :         out->hdisplay = in->hdisplay;
    1941                 :          0 :         out->hsync_start = in->hsync_start;
    1942                 :          0 :         out->hsync_end = in->hsync_end;
    1943                 :          0 :         out->htotal = in->htotal;
    1944                 :          0 :         out->hskew = in->hskew;
    1945                 :          0 :         out->vdisplay = in->vdisplay;
    1946                 :          0 :         out->vsync_start = in->vsync_start;
    1947                 :          0 :         out->vsync_end = in->vsync_end;
    1948                 :          0 :         out->vtotal = in->vtotal;
    1949                 :          0 :         out->vscan = in->vscan;
    1950                 :          0 :         out->vrefresh = in->vrefresh;
    1951                 :          0 :         out->flags = in->flags;
    1952                 :          0 :         out->type = in->type;
    1953                 :            : 
    1954   [ #  #  #  #  :          0 :         switch (in->picture_aspect_ratio) {
                   #  # ]
    1955                 :          0 :         case HDMI_PICTURE_ASPECT_4_3:
    1956                 :          0 :                 out->flags |= DRM_MODE_FLAG_PIC_AR_4_3;
    1957                 :          0 :                 break;
    1958                 :          0 :         case HDMI_PICTURE_ASPECT_16_9:
    1959                 :          0 :                 out->flags |= DRM_MODE_FLAG_PIC_AR_16_9;
    1960                 :          0 :                 break;
    1961                 :          0 :         case HDMI_PICTURE_ASPECT_64_27:
    1962                 :          0 :                 out->flags |= DRM_MODE_FLAG_PIC_AR_64_27;
    1963                 :          0 :                 break;
    1964                 :          0 :         case HDMI_PICTURE_ASPECT_256_135:
    1965                 :          0 :                 out->flags |= DRM_MODE_FLAG_PIC_AR_256_135;
    1966                 :          0 :                 break;
    1967                 :            :         default:
    1968                 :          0 :                 WARN(1, "Invalid aspect ratio (0%x) on mode\n",
    1969                 :            :                      in->picture_aspect_ratio);
    1970                 :            :                 /* fall through */
    1971                 :          0 :         case HDMI_PICTURE_ASPECT_NONE:
    1972                 :          0 :                 out->flags |= DRM_MODE_FLAG_PIC_AR_NONE;
    1973                 :          0 :                 break;
    1974                 :            :         }
    1975                 :            : 
    1976                 :          0 :         strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN);
    1977                 :          0 :         out->name[DRM_DISPLAY_MODE_LEN-1] = 0;
    1978                 :          0 : }
    1979                 :            : 
    1980                 :            : /**
    1981                 :            :  * drm_crtc_convert_umode - convert a modeinfo into a drm_display_mode
    1982                 :            :  * @dev: drm device
    1983                 :            :  * @out: drm_display_mode to return to the user
    1984                 :            :  * @in: drm_mode_modeinfo to use
    1985                 :            :  *
    1986                 :            :  * Convert a drm_mode_modeinfo into a drm_display_mode structure to return to
    1987                 :            :  * the caller.
    1988                 :            :  *
    1989                 :            :  * Returns:
    1990                 :            :  * Zero on success, negative errno on failure.
    1991                 :            :  */
    1992                 :          0 : int drm_mode_convert_umode(struct drm_device *dev,
    1993                 :            :                            struct drm_display_mode *out,
    1994                 :            :                            const struct drm_mode_modeinfo *in)
    1995                 :            : {
    1996   [ #  #  #  # ]:          0 :         if (in->clock > INT_MAX || in->vrefresh > INT_MAX)
    1997                 :            :                 return -ERANGE;
    1998                 :            : 
    1999                 :          0 :         out->clock = in->clock;
    2000                 :          0 :         out->hdisplay = in->hdisplay;
    2001                 :          0 :         out->hsync_start = in->hsync_start;
    2002                 :          0 :         out->hsync_end = in->hsync_end;
    2003                 :          0 :         out->htotal = in->htotal;
    2004                 :          0 :         out->hskew = in->hskew;
    2005                 :          0 :         out->vdisplay = in->vdisplay;
    2006                 :          0 :         out->vsync_start = in->vsync_start;
    2007                 :          0 :         out->vsync_end = in->vsync_end;
    2008                 :          0 :         out->vtotal = in->vtotal;
    2009                 :          0 :         out->vscan = in->vscan;
    2010                 :          0 :         out->vrefresh = in->vrefresh;
    2011                 :          0 :         out->flags = in->flags;
    2012                 :            :         /*
    2013                 :            :          * Old xf86-video-vmware (possibly others too) used to
    2014                 :            :          * leave 'type' unititialized. Just ignore any bits we
    2015                 :            :          * don't like. It's a just hint after all, and more
    2016                 :            :          * useful for the kernel->userspace direction anyway.
    2017                 :            :          */
    2018                 :          0 :         out->type = in->type & DRM_MODE_TYPE_ALL;
    2019                 :          0 :         strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN);
    2020                 :          0 :         out->name[DRM_DISPLAY_MODE_LEN-1] = 0;
    2021                 :            : 
    2022                 :            :         /* Clearing picture aspect ratio bits from out flags,
    2023                 :            :          * as the aspect-ratio information is not stored in
    2024                 :            :          * flags for kernel-mode, but in picture_aspect_ratio.
    2025                 :            :          */
    2026                 :          0 :         out->flags &= ~DRM_MODE_FLAG_PIC_AR_MASK;
    2027                 :            : 
    2028   [ #  #  #  #  :          0 :         switch (in->flags & DRM_MODE_FLAG_PIC_AR_MASK) {
                   #  # ]
    2029                 :          0 :         case DRM_MODE_FLAG_PIC_AR_4_3:
    2030                 :          0 :                 out->picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3;
    2031                 :          0 :                 break;
    2032                 :          0 :         case DRM_MODE_FLAG_PIC_AR_16_9:
    2033                 :          0 :                 out->picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9;
    2034                 :          0 :                 break;
    2035                 :          0 :         case DRM_MODE_FLAG_PIC_AR_64_27:
    2036                 :          0 :                 out->picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27;
    2037                 :          0 :                 break;
    2038                 :          0 :         case DRM_MODE_FLAG_PIC_AR_256_135:
    2039                 :          0 :                 out->picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135;
    2040                 :          0 :                 break;
    2041                 :          0 :         case DRM_MODE_FLAG_PIC_AR_NONE:
    2042                 :          0 :                 out->picture_aspect_ratio = HDMI_PICTURE_ASPECT_NONE;
    2043                 :          0 :                 break;
    2044                 :            :         default:
    2045                 :            :                 return -EINVAL;
    2046                 :            :         }
    2047                 :            : 
    2048                 :          0 :         out->status = drm_mode_validate_driver(dev, out);
    2049         [ #  # ]:          0 :         if (out->status != MODE_OK)
    2050                 :            :                 return -EINVAL;
    2051                 :            : 
    2052                 :          0 :         drm_mode_set_crtcinfo(out, CRTC_INTERLACE_HALVE_V);
    2053                 :            : 
    2054                 :          0 :         return 0;
    2055                 :            : }
    2056                 :            : 
    2057                 :            : /**
    2058                 :            :  * drm_mode_is_420_only - if a given videomode can be only supported in YCBCR420
    2059                 :            :  * output format
    2060                 :            :  *
    2061                 :            :  * @display: display under action
    2062                 :            :  * @mode: video mode to be tested.
    2063                 :            :  *
    2064                 :            :  * Returns:
    2065                 :            :  * true if the mode can be supported in YCBCR420 format
    2066                 :            :  * false if not.
    2067                 :            :  */
    2068                 :          0 : bool drm_mode_is_420_only(const struct drm_display_info *display,
    2069                 :            :                           const struct drm_display_mode *mode)
    2070                 :            : {
    2071                 :          0 :         u8 vic = drm_match_cea_mode(mode);
    2072                 :            : 
    2073                 :          0 :         return test_bit(vic, display->hdmi.y420_vdb_modes);
    2074                 :            : }
    2075                 :            : EXPORT_SYMBOL(drm_mode_is_420_only);
    2076                 :            : 
    2077                 :            : /**
    2078                 :            :  * drm_mode_is_420_also - if a given videomode can be supported in YCBCR420
    2079                 :            :  * output format also (along with RGB/YCBCR444/422)
    2080                 :            :  *
    2081                 :            :  * @display: display under action.
    2082                 :            :  * @mode: video mode to be tested.
    2083                 :            :  *
    2084                 :            :  * Returns:
    2085                 :            :  * true if the mode can be support YCBCR420 format
    2086                 :            :  * false if not.
    2087                 :            :  */
    2088                 :          0 : bool drm_mode_is_420_also(const struct drm_display_info *display,
    2089                 :            :                           const struct drm_display_mode *mode)
    2090                 :            : {
    2091                 :          0 :         u8 vic = drm_match_cea_mode(mode);
    2092                 :            : 
    2093                 :          0 :         return test_bit(vic, display->hdmi.y420_cmdb_modes);
    2094                 :            : }
    2095                 :            : EXPORT_SYMBOL(drm_mode_is_420_also);
    2096                 :            : /**
    2097                 :            :  * drm_mode_is_420 - if a given videomode can be supported in YCBCR420
    2098                 :            :  * output format
    2099                 :            :  *
    2100                 :            :  * @display: display under action.
    2101                 :            :  * @mode: video mode to be tested.
    2102                 :            :  *
    2103                 :            :  * Returns:
    2104                 :            :  * true if the mode can be supported in YCBCR420 format
    2105                 :            :  * false if not.
    2106                 :            :  */
    2107                 :          0 : bool drm_mode_is_420(const struct drm_display_info *display,
    2108                 :            :                      const struct drm_display_mode *mode)
    2109                 :            : {
    2110   [ #  #  #  # ]:          0 :         return drm_mode_is_420_only(display, mode) ||
    2111                 :            :                 drm_mode_is_420_also(display, mode);
    2112                 :            : }
    2113                 :            : EXPORT_SYMBOL(drm_mode_is_420);

Generated by: LCOV version 1.14