LCOV - code coverage report
Current view: top level - drivers/gpu/drm - drm_modes.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 448 764 58.6 %
Date: 2023-03-27 20:00:47 Functions: 31 44 70.5 %

          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/export.h>
      35             : #include <linux/fb.h> /* for KHZ2PICOS() */
      36             : #include <linux/list.h>
      37             : #include <linux/list_sort.h>
      38             : #include <linux/of.h>
      39             : 
      40             : #include <video/of_display_timing.h>
      41             : #include <video/of_videomode.h>
      42             : #include <video/videomode.h>
      43             : 
      44             : #include <drm/drm_crtc.h>
      45             : #include <drm/drm_device.h>
      46             : #include <drm/drm_edid.h>
      47             : #include <drm/drm_modes.h>
      48             : #include <drm/drm_print.h>
      49             : 
      50             : #include "drm_crtc_internal.h"
      51             : 
      52             : /**
      53             :  * drm_mode_debug_printmodeline - print a mode to dmesg
      54             :  * @mode: mode to print
      55             :  *
      56             :  * Describe @mode using DRM_DEBUG.
      57             :  */
      58         140 : void drm_mode_debug_printmodeline(const struct drm_display_mode *mode)
      59             : {
      60         140 :         DRM_DEBUG_KMS("Modeline " DRM_MODE_FMT "\n", DRM_MODE_ARG(mode));
      61         140 : }
      62             : EXPORT_SYMBOL(drm_mode_debug_printmodeline);
      63             : 
      64             : /**
      65             :  * drm_mode_create - create a new display mode
      66             :  * @dev: DRM device
      67             :  *
      68             :  * Create a new, cleared drm_display_mode with kzalloc, allocate an ID for it
      69             :  * and return it.
      70             :  *
      71             :  * Returns:
      72             :  * Pointer to new mode on success, NULL on error.
      73             :  */
      74           0 : struct drm_display_mode *drm_mode_create(struct drm_device *dev)
      75             : {
      76             :         struct drm_display_mode *nmode;
      77             : 
      78         178 :         nmode = kzalloc(sizeof(struct drm_display_mode), GFP_KERNEL);
      79         178 :         if (!nmode)
      80             :                 return NULL;
      81             : 
      82           0 :         return nmode;
      83             : }
      84             : EXPORT_SYMBOL(drm_mode_create);
      85             : 
      86             : /**
      87             :  * drm_mode_destroy - remove a mode
      88             :  * @dev: DRM device
      89             :  * @mode: mode to remove
      90             :  *
      91             :  * Release @mode's unique ID, then free it @mode structure itself using kfree.
      92             :  */
      93         135 : void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode)
      94             : {
      95         150 :         if (!mode)
      96             :                 return;
      97             : 
      98         150 :         kfree(mode);
      99             : }
     100             : EXPORT_SYMBOL(drm_mode_destroy);
     101             : 
     102             : /**
     103             :  * drm_mode_probed_add - add a mode to a connector's probed_mode list
     104             :  * @connector: connector the new mode
     105             :  * @mode: mode data
     106             :  *
     107             :  * Add @mode to @connector's probed_mode list for later use. This list should
     108             :  * then in a second step get filtered and all the modes actually supported by
     109             :  * the hardware moved to the @connector's modes list.
     110             :  */
     111         150 : void drm_mode_probed_add(struct drm_connector *connector,
     112             :                          struct drm_display_mode *mode)
     113             : {
     114         150 :         WARN_ON(!mutex_is_locked(&connector->dev->mode_config.mutex));
     115             : 
     116         300 :         list_add_tail(&mode->head, &connector->probed_modes);
     117         150 : }
     118             : EXPORT_SYMBOL(drm_mode_probed_add);
     119             : 
     120             : enum drm_mode_analog {
     121             :         DRM_MODE_ANALOG_NTSC, /* 525 lines, 60Hz */
     122             :         DRM_MODE_ANALOG_PAL, /* 625 lines, 50Hz */
     123             : };
     124             : 
     125             : /*
     126             :  * The timings come from:
     127             :  * - https://web.archive.org/web/20220406232708/http://www.kolumbus.fi/pami1/video/pal_ntsc.html
     128             :  * - https://web.archive.org/web/20220406124914/http://martin.hinner.info/vga/pal.html
     129             :  * - https://web.archive.org/web/20220609202433/http://www.batsocks.co.uk/readme/video_timing.htm
     130             :  */
     131             : #define NTSC_LINE_DURATION_NS           63556U
     132             : #define NTSC_LINES_NUMBER               525
     133             : 
     134             : #define NTSC_HBLK_DURATION_TYP_NS       10900U
     135             : #define NTSC_HBLK_DURATION_MIN_NS       (NTSC_HBLK_DURATION_TYP_NS - 200)
     136             : #define NTSC_HBLK_DURATION_MAX_NS       (NTSC_HBLK_DURATION_TYP_NS + 200)
     137             : 
     138             : #define NTSC_HACT_DURATION_TYP_NS       (NTSC_LINE_DURATION_NS - NTSC_HBLK_DURATION_TYP_NS)
     139             : #define NTSC_HACT_DURATION_MIN_NS       (NTSC_LINE_DURATION_NS - NTSC_HBLK_DURATION_MAX_NS)
     140             : #define NTSC_HACT_DURATION_MAX_NS       (NTSC_LINE_DURATION_NS - NTSC_HBLK_DURATION_MIN_NS)
     141             : 
     142             : #define NTSC_HFP_DURATION_TYP_NS        1500
     143             : #define NTSC_HFP_DURATION_MIN_NS        1270
     144             : #define NTSC_HFP_DURATION_MAX_NS        2220
     145             : 
     146             : #define NTSC_HSLEN_DURATION_TYP_NS      4700
     147             : #define NTSC_HSLEN_DURATION_MIN_NS      (NTSC_HSLEN_DURATION_TYP_NS - 100)
     148             : #define NTSC_HSLEN_DURATION_MAX_NS      (NTSC_HSLEN_DURATION_TYP_NS + 100)
     149             : 
     150             : #define NTSC_HBP_DURATION_TYP_NS        4700
     151             : 
     152             : /*
     153             :  * I couldn't find the actual tolerance for the back porch, so let's
     154             :  * just reuse the sync length ones.
     155             :  */
     156             : #define NTSC_HBP_DURATION_MIN_NS        (NTSC_HBP_DURATION_TYP_NS - 100)
     157             : #define NTSC_HBP_DURATION_MAX_NS        (NTSC_HBP_DURATION_TYP_NS + 100)
     158             : 
     159             : #define PAL_LINE_DURATION_NS            64000U
     160             : #define PAL_LINES_NUMBER                625
     161             : 
     162             : #define PAL_HACT_DURATION_TYP_NS        51950U
     163             : #define PAL_HACT_DURATION_MIN_NS        (PAL_HACT_DURATION_TYP_NS - 100)
     164             : #define PAL_HACT_DURATION_MAX_NS        (PAL_HACT_DURATION_TYP_NS + 400)
     165             : 
     166             : #define PAL_HBLK_DURATION_TYP_NS        (PAL_LINE_DURATION_NS - PAL_HACT_DURATION_TYP_NS)
     167             : #define PAL_HBLK_DURATION_MIN_NS        (PAL_LINE_DURATION_NS - PAL_HACT_DURATION_MAX_NS)
     168             : #define PAL_HBLK_DURATION_MAX_NS        (PAL_LINE_DURATION_NS - PAL_HACT_DURATION_MIN_NS)
     169             : 
     170             : #define PAL_HFP_DURATION_TYP_NS         1650
     171             : #define PAL_HFP_DURATION_MIN_NS         (PAL_HFP_DURATION_TYP_NS - 100)
     172             : #define PAL_HFP_DURATION_MAX_NS         (PAL_HFP_DURATION_TYP_NS + 400)
     173             : 
     174             : #define PAL_HSLEN_DURATION_TYP_NS       4700
     175             : #define PAL_HSLEN_DURATION_MIN_NS       (PAL_HSLEN_DURATION_TYP_NS - 200)
     176             : #define PAL_HSLEN_DURATION_MAX_NS       (PAL_HSLEN_DURATION_TYP_NS + 200)
     177             : 
     178             : #define PAL_HBP_DURATION_TYP_NS         5700
     179             : #define PAL_HBP_DURATION_MIN_NS         (PAL_HBP_DURATION_TYP_NS - 200)
     180             : #define PAL_HBP_DURATION_MAX_NS         (PAL_HBP_DURATION_TYP_NS + 200)
     181             : 
     182             : struct analog_param_field {
     183             :         unsigned int even, odd;
     184             : };
     185             : 
     186             : #define PARAM_FIELD(_odd, _even)                \
     187             :         { .even = _even, .odd = _odd }
     188             : 
     189             : struct analog_param_range {
     190             :         unsigned int    min, typ, max;
     191             : };
     192             : 
     193             : #define PARAM_RANGE(_min, _typ, _max)           \
     194             :         { .min = _min, .typ = _typ, .max = _max }
     195             : 
     196             : struct analog_parameters {
     197             :         unsigned int                    num_lines;
     198             :         unsigned int                    line_duration_ns;
     199             : 
     200             :         struct analog_param_range       hact_ns;
     201             :         struct analog_param_range       hfp_ns;
     202             :         struct analog_param_range       hslen_ns;
     203             :         struct analog_param_range       hbp_ns;
     204             :         struct analog_param_range       hblk_ns;
     205             : 
     206             :         unsigned int                    bt601_hfp;
     207             : 
     208             :         struct analog_param_field       vfp_lines;
     209             :         struct analog_param_field       vslen_lines;
     210             :         struct analog_param_field       vbp_lines;
     211             : };
     212             : 
     213             : #define TV_MODE_PARAMETER(_mode, _lines, _line_dur, _hact, _hfp,        \
     214             :                           _hslen, _hbp, _hblk, _bt601_hfp, _vfp,        \
     215             :                           _vslen, _vbp)                                 \
     216             :         [_mode] = {                                                     \
     217             :                 .num_lines = _lines,                                    \
     218             :                 .line_duration_ns = _line_dur,                          \
     219             :                 .hact_ns = _hact,                                       \
     220             :                 .hfp_ns = _hfp,                                         \
     221             :                 .hslen_ns = _hslen,                                     \
     222             :                 .hbp_ns = _hbp,                                         \
     223             :                 .hblk_ns = _hblk,                                       \
     224             :                 .bt601_hfp = _bt601_hfp,                                \
     225             :                 .vfp_lines = _vfp,                                      \
     226             :                 .vslen_lines = _vslen,                                  \
     227             :                 .vbp_lines = _vbp,                                      \
     228             :         }
     229             : 
     230             : static const struct analog_parameters tv_modes_parameters[] = {
     231             :         TV_MODE_PARAMETER(DRM_MODE_ANALOG_NTSC,
     232             :                           NTSC_LINES_NUMBER,
     233             :                           NTSC_LINE_DURATION_NS,
     234             :                           PARAM_RANGE(NTSC_HACT_DURATION_MIN_NS,
     235             :                                       NTSC_HACT_DURATION_TYP_NS,
     236             :                                       NTSC_HACT_DURATION_MAX_NS),
     237             :                           PARAM_RANGE(NTSC_HFP_DURATION_MIN_NS,
     238             :                                       NTSC_HFP_DURATION_TYP_NS,
     239             :                                       NTSC_HFP_DURATION_MAX_NS),
     240             :                           PARAM_RANGE(NTSC_HSLEN_DURATION_MIN_NS,
     241             :                                       NTSC_HSLEN_DURATION_TYP_NS,
     242             :                                       NTSC_HSLEN_DURATION_MAX_NS),
     243             :                           PARAM_RANGE(NTSC_HBP_DURATION_MIN_NS,
     244             :                                       NTSC_HBP_DURATION_TYP_NS,
     245             :                                       NTSC_HBP_DURATION_MAX_NS),
     246             :                           PARAM_RANGE(NTSC_HBLK_DURATION_MIN_NS,
     247             :                                       NTSC_HBLK_DURATION_TYP_NS,
     248             :                                       NTSC_HBLK_DURATION_MAX_NS),
     249             :                           16,
     250             :                           PARAM_FIELD(3, 3),
     251             :                           PARAM_FIELD(3, 3),
     252             :                           PARAM_FIELD(16, 17)),
     253             :         TV_MODE_PARAMETER(DRM_MODE_ANALOG_PAL,
     254             :                           PAL_LINES_NUMBER,
     255             :                           PAL_LINE_DURATION_NS,
     256             :                           PARAM_RANGE(PAL_HACT_DURATION_MIN_NS,
     257             :                                       PAL_HACT_DURATION_TYP_NS,
     258             :                                       PAL_HACT_DURATION_MAX_NS),
     259             :                           PARAM_RANGE(PAL_HFP_DURATION_MIN_NS,
     260             :                                       PAL_HFP_DURATION_TYP_NS,
     261             :                                       PAL_HFP_DURATION_MAX_NS),
     262             :                           PARAM_RANGE(PAL_HSLEN_DURATION_MIN_NS,
     263             :                                       PAL_HSLEN_DURATION_TYP_NS,
     264             :                                       PAL_HSLEN_DURATION_MAX_NS),
     265             :                           PARAM_RANGE(PAL_HBP_DURATION_MIN_NS,
     266             :                                       PAL_HBP_DURATION_TYP_NS,
     267             :                                       PAL_HBP_DURATION_MAX_NS),
     268             :                           PARAM_RANGE(PAL_HBLK_DURATION_MIN_NS,
     269             :                                       PAL_HBLK_DURATION_TYP_NS,
     270             :                                       PAL_HBLK_DURATION_MAX_NS),
     271             :                           12,
     272             : 
     273             :                           /*
     274             :                            * The front porch is actually 6 short sync
     275             :                            * pulses for the even field, and 5 for the
     276             :                            * odd field. Each sync takes half a life so
     277             :                            * the odd field front porch is shorter by
     278             :                            * half a line.
     279             :                            *
     280             :                            * In progressive, we're supposed to use 6
     281             :                            * pulses, so we're fine there
     282             :                            */
     283             :                           PARAM_FIELD(3, 2),
     284             : 
     285             :                           /*
     286             :                            * The vsync length is 5 long sync pulses,
     287             :                            * each field taking half a line. We're
     288             :                            * shorter for both fields by half a line.
     289             :                            *
     290             :                            * In progressive, we're supposed to use 5
     291             :                            * pulses, so we're off by half
     292             :                            * a line.
     293             :                            *
     294             :                            * In interlace, we're now off by half a line
     295             :                            * for the even field and one line for the odd
     296             :                            * field.
     297             :                            */
     298             :                           PARAM_FIELD(3, 3),
     299             : 
     300             :                           /*
     301             :                            * The back porch starts with post-equalizing
     302             :                            * pulses, consisting in 5 short sync pulses
     303             :                            * for the even field, 4 for the odd field. In
     304             :                            * progressive, it's 5 short syncs.
     305             :                            *
     306             :                            * In progressive, we thus have 2.5 lines,
     307             :                            * plus the 0.5 line we were missing
     308             :                            * previously, so we should use 3 lines.
     309             :                            *
     310             :                            * In interlace, the even field is in the
     311             :                            * exact same case than progressive. For the
     312             :                            * odd field, we should be using 2 lines but
     313             :                            * we're one line short, so we'll make up for
     314             :                            * it here by using 3.
     315             :                            *
     316             :                            * The entire blanking area is supposed to
     317             :                            * take 25 lines, so we also need to account
     318             :                            * for the rest of the blanking area that
     319             :                            * can't be in either the front porch or sync
     320             :                            * period.
     321             :                            */
     322             :                           PARAM_FIELD(19, 20)),
     323             : };
     324             : 
     325          47 : static int fill_analog_mode(struct drm_device *dev,
     326             :                             struct drm_display_mode *mode,
     327             :                             const struct analog_parameters *params,
     328             :                             unsigned long pixel_clock_hz,
     329             :                             unsigned int hactive,
     330             :                             unsigned int vactive,
     331             :                             bool interlace)
     332             : {
     333          47 :         unsigned long pixel_duration_ns = NSEC_PER_SEC / pixel_clock_hz;
     334             :         unsigned int htotal, vtotal;
     335             :         unsigned int max_hact, hact_duration_ns;
     336             :         unsigned int hblk, hblk_duration_ns;
     337             :         unsigned int hfp, hfp_duration_ns;
     338             :         unsigned int hslen, hslen_duration_ns;
     339             :         unsigned int hbp, hbp_duration_ns;
     340             :         unsigned int porches, porches_duration_ns;
     341             :         unsigned int vfp, vfp_min;
     342             :         unsigned int vbp, vbp_min;
     343             :         unsigned int vslen;
     344          47 :         bool bt601 = false;
     345             :         int porches_rem;
     346             :         u64 result;
     347             : 
     348          47 :         drm_dbg_kms(dev,
     349             :                     "Generating a %ux%u%c, %u-line mode with a %lu kHz clock\n",
     350             :                     hactive, vactive,
     351             :                     interlace ? 'i' : 'p',
     352             :                     params->num_lines,
     353             :                     pixel_clock_hz / 1000);
     354             : 
     355          47 :         max_hact = params->hact_ns.max / pixel_duration_ns;
     356          47 :         if (pixel_clock_hz == 13500000 && hactive > max_hact && hactive <= 720) {
     357          47 :                 drm_dbg_kms(dev, "Trying to generate a BT.601 mode. Disabling checks.\n");
     358          47 :                 bt601 = true;
     359             :         }
     360             : 
     361             :         /*
     362             :          * Our pixel duration is going to be round down by the division,
     363             :          * so rounding up is probably going to introduce even more
     364             :          * deviation.
     365             :          */
     366          47 :         result = (u64)params->line_duration_ns * pixel_clock_hz;
     367          47 :         do_div(result, NSEC_PER_SEC);
     368          47 :         htotal = result;
     369             : 
     370          47 :         drm_dbg_kms(dev, "Total Horizontal Number of Pixels: %u\n", htotal);
     371             : 
     372          47 :         hact_duration_ns = hactive * pixel_duration_ns;
     373          47 :         if (!bt601 &&
     374           0 :             (hact_duration_ns < params->hact_ns.min ||
     375           0 :              hact_duration_ns > params->hact_ns.max)) {
     376           0 :                 DRM_ERROR("Invalid horizontal active area duration: %uns (min: %u, max %u)\n",
     377             :                           hact_duration_ns, params->hact_ns.min, params->hact_ns.max);
     378           0 :                 return -EINVAL;
     379             :         }
     380             : 
     381          47 :         hblk = htotal - hactive;
     382          47 :         drm_dbg_kms(dev, "Horizontal Blanking Period: %u\n", hblk);
     383             : 
     384          47 :         hblk_duration_ns = hblk * pixel_duration_ns;
     385          47 :         if (!bt601 &&
     386           0 :             (hblk_duration_ns < params->hblk_ns.min ||
     387           0 :              hblk_duration_ns > params->hblk_ns.max)) {
     388           0 :                 DRM_ERROR("Invalid horizontal blanking duration: %uns (min: %u, max %u)\n",
     389             :                           hblk_duration_ns, params->hblk_ns.min, params->hblk_ns.max);
     390           0 :                 return -EINVAL;
     391             :         }
     392             : 
     393          47 :         hslen = DIV_ROUND_UP(params->hslen_ns.typ, pixel_duration_ns);
     394          47 :         drm_dbg_kms(dev, "Horizontal Sync Period: %u\n", hslen);
     395             : 
     396          47 :         hslen_duration_ns = hslen * pixel_duration_ns;
     397          47 :         if (!bt601 &&
     398           0 :             (hslen_duration_ns < params->hslen_ns.min ||
     399           0 :              hslen_duration_ns > params->hslen_ns.max)) {
     400           0 :                 DRM_ERROR("Invalid horizontal sync duration: %uns (min: %u, max %u)\n",
     401             :                           hslen_duration_ns, params->hslen_ns.min, params->hslen_ns.max);
     402           0 :                 return -EINVAL;
     403             :         }
     404             : 
     405          47 :         porches = hblk - hslen;
     406          47 :         drm_dbg_kms(dev, "Remaining horizontal pixels for both porches: %u\n", porches);
     407             : 
     408          47 :         porches_duration_ns = porches * pixel_duration_ns;
     409          47 :         if (!bt601 &&
     410           0 :             (porches_duration_ns > (params->hfp_ns.max + params->hbp_ns.max) ||
     411           0 :              porches_duration_ns < (params->hfp_ns.min + params->hbp_ns.min))) {
     412           0 :                 DRM_ERROR("Invalid horizontal porches duration: %uns\n", porches_duration_ns);
     413           0 :                 return -EINVAL;
     414             :         }
     415             : 
     416          47 :         if (bt601) {
     417          47 :                 hfp = params->bt601_hfp;
     418             :         } else {
     419           0 :                 unsigned int hfp_min = DIV_ROUND_UP(params->hfp_ns.min,
     420             :                                                     pixel_duration_ns);
     421           0 :                 unsigned int hbp_min = DIV_ROUND_UP(params->hbp_ns.min,
     422             :                                                     pixel_duration_ns);
     423           0 :                 int porches_rem = porches - hfp_min - hbp_min;
     424             : 
     425           0 :                 hfp = hfp_min + DIV_ROUND_UP(porches_rem, 2);
     426             :         }
     427             : 
     428          47 :         drm_dbg_kms(dev, "Horizontal Front Porch: %u\n", hfp);
     429             : 
     430          47 :         hfp_duration_ns = hfp * pixel_duration_ns;
     431          47 :         if (!bt601 &&
     432           0 :             (hfp_duration_ns < params->hfp_ns.min ||
     433           0 :              hfp_duration_ns > params->hfp_ns.max)) {
     434           0 :                 DRM_ERROR("Invalid horizontal front porch duration: %uns (min: %u, max %u)\n",
     435             :                           hfp_duration_ns, params->hfp_ns.min, params->hfp_ns.max);
     436           0 :                 return -EINVAL;
     437             :         }
     438             : 
     439          47 :         hbp = porches - hfp;
     440          47 :         drm_dbg_kms(dev, "Horizontal Back Porch: %u\n", hbp);
     441             : 
     442          47 :         hbp_duration_ns = hbp * pixel_duration_ns;
     443          47 :         if (!bt601 &&
     444           0 :             (hbp_duration_ns < params->hbp_ns.min ||
     445           0 :              hbp_duration_ns > params->hbp_ns.max)) {
     446           0 :                 DRM_ERROR("Invalid horizontal back porch duration: %uns (min: %u, max %u)\n",
     447             :                           hbp_duration_ns, params->hbp_ns.min, params->hbp_ns.max);
     448           0 :                 return -EINVAL;
     449             :         }
     450             : 
     451          47 :         if (htotal != (hactive + hfp + hslen + hbp))
     452             :                 return -EINVAL;
     453             : 
     454          47 :         mode->clock = pixel_clock_hz / 1000;
     455          47 :         mode->hdisplay = hactive;
     456          47 :         mode->hsync_start = mode->hdisplay + hfp;
     457          47 :         mode->hsync_end = mode->hsync_start + hslen;
     458          47 :         mode->htotal = mode->hsync_end + hbp;
     459             : 
     460          47 :         if (interlace) {
     461          47 :                 vfp_min = params->vfp_lines.even + params->vfp_lines.odd;
     462          47 :                 vbp_min = params->vbp_lines.even + params->vbp_lines.odd;
     463          47 :                 vslen = params->vslen_lines.even + params->vslen_lines.odd;
     464             :         } else {
     465             :                 /*
     466             :                  * By convention, NTSC (aka 525/60) systems start with
     467             :                  * the even field, but PAL (aka 625/50) systems start
     468             :                  * with the odd one.
     469             :                  *
     470             :                  * PAL systems also have asymmetric timings between the
     471             :                  * even and odd field, while NTSC is symmetric.
     472             :                  *
     473             :                  * Moreover, if we want to create a progressive mode for
     474             :                  * PAL, we need to use the odd field timings.
     475             :                  *
     476             :                  * Since odd == even for NTSC, we can just use the odd
     477             :                  * one all the time to simplify the code a bit.
     478             :                  */
     479           0 :                 vfp_min = params->vfp_lines.odd;
     480           0 :                 vbp_min = params->vbp_lines.odd;
     481           0 :                 vslen = params->vslen_lines.odd;
     482             :         }
     483             : 
     484          47 :         drm_dbg_kms(dev, "Vertical Sync Period: %u\n", vslen);
     485             : 
     486          47 :         porches = params->num_lines - vactive - vslen;
     487          47 :         drm_dbg_kms(dev, "Remaining vertical pixels for both porches: %u\n", porches);
     488             : 
     489          47 :         porches_rem = porches - vfp_min - vbp_min;
     490          47 :         vfp = vfp_min + (porches_rem / 2);
     491          47 :         drm_dbg_kms(dev, "Vertical Front Porch: %u\n", vfp);
     492             : 
     493          47 :         vbp = porches - vfp;
     494          47 :         drm_dbg_kms(dev, "Vertical Back Porch: %u\n", vbp);
     495             : 
     496          47 :         vtotal = vactive + vfp + vslen + vbp;
     497          47 :         if (params->num_lines != vtotal) {
     498           0 :                 DRM_ERROR("Invalid vertical total: %upx (expected %upx)\n",
     499             :                           vtotal, params->num_lines);
     500           0 :                 return -EINVAL;
     501             :         }
     502             : 
     503          47 :         mode->vdisplay = vactive;
     504          47 :         mode->vsync_start = mode->vdisplay + vfp;
     505          47 :         mode->vsync_end = mode->vsync_start + vslen;
     506          47 :         mode->vtotal = mode->vsync_end + vbp;
     507             : 
     508          47 :         if (mode->vtotal != params->num_lines)
     509             :                 return -EINVAL;
     510             : 
     511          47 :         mode->type = DRM_MODE_TYPE_DRIVER;
     512          47 :         mode->flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC;
     513          47 :         if (interlace)
     514          47 :                 mode->flags |= DRM_MODE_FLAG_INTERLACE;
     515             : 
     516          47 :         drm_mode_set_name(mode);
     517             : 
     518          47 :         drm_dbg_kms(dev, "Generated mode " DRM_MODE_FMT "\n", DRM_MODE_ARG(mode));
     519             : 
     520          47 :         return 0;
     521             : }
     522             : 
     523             : /**
     524             :  * drm_analog_tv_mode - create a display mode for an analog TV
     525             :  * @dev: drm device
     526             :  * @tv_mode: TV Mode standard to create a mode for. See DRM_MODE_TV_MODE_*.
     527             :  * @pixel_clock_hz: Pixel Clock Frequency, in Hertz
     528             :  * @hdisplay: hdisplay size
     529             :  * @vdisplay: vdisplay size
     530             :  * @interlace: whether to compute an interlaced mode
     531             :  *
     532             :  * This function creates a struct drm_display_mode instance suited for
     533             :  * an analog TV output, for one of the usual analog TV mode.
     534             :  *
     535             :  * Note that @hdisplay is larger than the usual constraints for the PAL
     536             :  * and NTSC timings, and we'll choose to ignore most timings constraints
     537             :  * to reach those resolutions.
     538             :  *
     539             :  * Returns:
     540             :  *
     541             :  * A pointer to the mode, allocated with drm_mode_create(). Returns NULL
     542             :  * on error.
     543             :  */
     544          47 : struct drm_display_mode *drm_analog_tv_mode(struct drm_device *dev,
     545             :                                             enum drm_connector_tv_mode tv_mode,
     546             :                                             unsigned long pixel_clock_hz,
     547             :                                             unsigned int hdisplay,
     548             :                                             unsigned int vdisplay,
     549             :                                             bool interlace)
     550             : {
     551             :         struct drm_display_mode *mode;
     552             :         enum drm_mode_analog analog;
     553             :         int ret;
     554             : 
     555             :         switch (tv_mode) {
     556             :         case DRM_MODE_TV_MODE_NTSC:
     557             :                 fallthrough;
     558             :         case DRM_MODE_TV_MODE_NTSC_443:
     559             :                 fallthrough;
     560             :         case DRM_MODE_TV_MODE_NTSC_J:
     561             :                 fallthrough;
     562             :         case DRM_MODE_TV_MODE_PAL_M:
     563             :                 analog = DRM_MODE_ANALOG_NTSC;
     564             :                 break;
     565             : 
     566             :         case DRM_MODE_TV_MODE_PAL:
     567             :                 fallthrough;
     568             :         case DRM_MODE_TV_MODE_PAL_N:
     569             :                 fallthrough;
     570             :         case DRM_MODE_TV_MODE_SECAM:
     571          22 :                 analog = DRM_MODE_ANALOG_PAL;
     572          22 :                 break;
     573             : 
     574             :         default:
     575             :                 return NULL;
     576             :         }
     577             : 
     578          47 :         mode = drm_mode_create(dev);
     579          47 :         if (!mode)
     580             :                 return NULL;
     581             : 
     582          47 :         ret = fill_analog_mode(dev, mode,
     583             :                                &tv_modes_parameters[analog],
     584             :                                pixel_clock_hz, hdisplay, vdisplay, interlace);
     585          47 :         if (ret)
     586             :                 goto err_free_mode;
     587             : 
     588             :         return mode;
     589             : 
     590             : err_free_mode:
     591           0 :         drm_mode_destroy(dev, mode);
     592           0 :         return NULL;
     593             : }
     594             : EXPORT_SYMBOL(drm_analog_tv_mode);
     595             : 
     596             : /**
     597             :  * drm_cvt_mode -create a modeline based on the CVT algorithm
     598             :  * @dev: drm device
     599             :  * @hdisplay: hdisplay size
     600             :  * @vdisplay: vdisplay size
     601             :  * @vrefresh: vrefresh rate
     602             :  * @reduced: whether to use reduced blanking
     603             :  * @interlaced: whether to compute an interlaced mode
     604             :  * @margins: whether to add margins (borders)
     605             :  *
     606             :  * This function is called to generate the modeline based on CVT algorithm
     607             :  * according to the hdisplay, vdisplay, vrefresh.
     608             :  * It is based from the VESA(TM) Coordinated Video Timing Generator by
     609             :  * Graham Loveridge April 9, 2003 available at
     610             :  * http://www.elo.utfsm.cl/~elo212/docs/CVTd6r1.xls
     611             :  *
     612             :  * And it is copied from xf86CVTmode in xserver/hw/xfree86/modes/xf86cvt.c.
     613             :  * What I have done is to translate it by using integer calculation.
     614             :  *
     615             :  * Returns:
     616             :  * The modeline based on the CVT algorithm stored in a drm_display_mode object.
     617             :  * The display mode object is allocated with drm_mode_create(). Returns NULL
     618             :  * when no mode could be allocated.
     619             :  */
     620           0 : struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, int hdisplay,
     621             :                                       int vdisplay, int vrefresh,
     622             :                                       bool reduced, bool interlaced, bool margins)
     623             : {
     624             : #define HV_FACTOR                       1000
     625             :         /* 1) top/bottom margin size (% of height) - default: 1.8, */
     626             : #define CVT_MARGIN_PERCENTAGE           18
     627             :         /* 2) character cell horizontal granularity (pixels) - default 8 */
     628             : #define CVT_H_GRANULARITY               8
     629             :         /* 3) Minimum vertical porch (lines) - default 3 */
     630             : #define CVT_MIN_V_PORCH                 3
     631             :         /* 4) Minimum number of vertical back porch lines - default 6 */
     632             : #define CVT_MIN_V_BPORCH                6
     633             :         /* Pixel Clock step (kHz) */
     634             : #define CVT_CLOCK_STEP                  250
     635             :         struct drm_display_mode *drm_mode;
     636             :         unsigned int vfieldrate, hperiod;
     637             :         int hdisplay_rnd, hmargin, vdisplay_rnd, vmargin, vsync;
     638             :         int interlace;
     639             :         u64 tmp;
     640             : 
     641           0 :         if (!hdisplay || !vdisplay)
     642             :                 return NULL;
     643             : 
     644             :         /* allocate the drm_display_mode structure. If failure, we will
     645             :          * return directly
     646             :          */
     647           0 :         drm_mode = drm_mode_create(dev);
     648           0 :         if (!drm_mode)
     649             :                 return NULL;
     650             : 
     651             :         /* the CVT default refresh rate is 60Hz */
     652           0 :         if (!vrefresh)
     653           0 :                 vrefresh = 60;
     654             : 
     655             :         /* the required field fresh rate */
     656           0 :         if (interlaced)
     657           0 :                 vfieldrate = vrefresh * 2;
     658             :         else
     659           0 :                 vfieldrate = vrefresh;
     660             : 
     661             :         /* horizontal pixels */
     662           0 :         hdisplay_rnd = hdisplay - (hdisplay % CVT_H_GRANULARITY);
     663             : 
     664             :         /* determine the left&right borders */
     665           0 :         hmargin = 0;
     666           0 :         if (margins) {
     667           0 :                 hmargin = hdisplay_rnd * CVT_MARGIN_PERCENTAGE / 1000;
     668           0 :                 hmargin -= hmargin % CVT_H_GRANULARITY;
     669             :         }
     670             :         /* find the total active pixels */
     671           0 :         drm_mode->hdisplay = hdisplay_rnd + 2 * hmargin;
     672             : 
     673             :         /* find the number of lines per field */
     674           0 :         if (interlaced)
     675           0 :                 vdisplay_rnd = vdisplay / 2;
     676             :         else
     677             :                 vdisplay_rnd = vdisplay;
     678             : 
     679             :         /* find the top & bottom borders */
     680           0 :         vmargin = 0;
     681           0 :         if (margins)
     682           0 :                 vmargin = vdisplay_rnd * CVT_MARGIN_PERCENTAGE / 1000;
     683             : 
     684           0 :         drm_mode->vdisplay = vdisplay + 2 * vmargin;
     685             : 
     686             :         /* Interlaced */
     687           0 :         if (interlaced)
     688             :                 interlace = 1;
     689             :         else
     690           0 :                 interlace = 0;
     691             : 
     692             :         /* Determine VSync Width from aspect ratio */
     693           0 :         if (!(vdisplay % 3) && ((vdisplay * 4 / 3) == hdisplay))
     694             :                 vsync = 4;
     695           0 :         else if (!(vdisplay % 9) && ((vdisplay * 16 / 9) == hdisplay))
     696             :                 vsync = 5;
     697           0 :         else if (!(vdisplay % 10) && ((vdisplay * 16 / 10) == hdisplay))
     698             :                 vsync = 6;
     699           0 :         else if (!(vdisplay % 4) && ((vdisplay * 5 / 4) == hdisplay))
     700             :                 vsync = 7;
     701           0 :         else if (!(vdisplay % 9) && ((vdisplay * 15 / 9) == hdisplay))
     702             :                 vsync = 7;
     703             :         else /* custom */
     704           0 :                 vsync = 10;
     705             : 
     706           0 :         if (!reduced) {
     707             :                 /* simplify the GTF calculation */
     708             :                 /* 4) Minimum time of vertical sync + back porch interval (µs)
     709             :                  * default 550.0
     710             :                  */
     711             :                 int tmp1, tmp2;
     712             : #define CVT_MIN_VSYNC_BP        550
     713             :                 /* 3) Nominal HSync width (% of line period) - default 8 */
     714             : #define CVT_HSYNC_PERCENTAGE    8
     715             :                 unsigned int hblank_percentage;
     716             :                 int vsyncandback_porch, __maybe_unused vback_porch, hblank;
     717             : 
     718             :                 /* estimated the horizontal period */
     719           0 :                 tmp1 = HV_FACTOR * 1000000  -
     720           0 :                                 CVT_MIN_VSYNC_BP * HV_FACTOR * vfieldrate;
     721           0 :                 tmp2 = (vdisplay_rnd + 2 * vmargin + CVT_MIN_V_PORCH) * 2 +
     722             :                                 interlace;
     723           0 :                 hperiod = tmp1 * 2 / (tmp2 * vfieldrate);
     724             : 
     725           0 :                 tmp1 = CVT_MIN_VSYNC_BP * HV_FACTOR / hperiod + 1;
     726             :                 /* 9. Find number of lines in sync + backporch */
     727           0 :                 if (tmp1 < (vsync + CVT_MIN_V_PORCH))
     728           0 :                         vsyncandback_porch = vsync + CVT_MIN_V_PORCH;
     729             :                 else
     730             :                         vsyncandback_porch = tmp1;
     731             :                 /* 10. Find number of lines in back porch */
     732           0 :                 vback_porch = vsyncandback_porch - vsync;
     733           0 :                 drm_mode->vtotal = vdisplay_rnd + 2 * vmargin +
     734           0 :                                 vsyncandback_porch + CVT_MIN_V_PORCH;
     735             :                 /* 5) Definition of Horizontal blanking time limitation */
     736             :                 /* Gradient (%/kHz) - default 600 */
     737             : #define CVT_M_FACTOR    600
     738             :                 /* Offset (%) - default 40 */
     739             : #define CVT_C_FACTOR    40
     740             :                 /* Blanking time scaling factor - default 128 */
     741             : #define CVT_K_FACTOR    128
     742             :                 /* Scaling factor weighting - default 20 */
     743             : #define CVT_J_FACTOR    20
     744             : #define CVT_M_PRIME     (CVT_M_FACTOR * CVT_K_FACTOR / 256)
     745             : #define CVT_C_PRIME     ((CVT_C_FACTOR - CVT_J_FACTOR) * CVT_K_FACTOR / 256 + \
     746             :                          CVT_J_FACTOR)
     747             :                 /* 12. Find ideal blanking duty cycle from formula */
     748           0 :                 hblank_percentage = CVT_C_PRIME * HV_FACTOR - CVT_M_PRIME *
     749           0 :                                         hperiod / 1000;
     750             :                 /* 13. Blanking time */
     751           0 :                 if (hblank_percentage < 20 * HV_FACTOR)
     752           0 :                         hblank_percentage = 20 * HV_FACTOR;
     753           0 :                 hblank = drm_mode->hdisplay * hblank_percentage /
     754           0 :                          (100 * HV_FACTOR - hblank_percentage);
     755           0 :                 hblank -= hblank % (2 * CVT_H_GRANULARITY);
     756             :                 /* 14. find the total pixels per line */
     757           0 :                 drm_mode->htotal = drm_mode->hdisplay + hblank;
     758           0 :                 drm_mode->hsync_end = drm_mode->hdisplay + hblank / 2;
     759           0 :                 drm_mode->hsync_start = drm_mode->hsync_end -
     760           0 :                         (drm_mode->htotal * CVT_HSYNC_PERCENTAGE) / 100;
     761           0 :                 drm_mode->hsync_start += CVT_H_GRANULARITY -
     762             :                         drm_mode->hsync_start % CVT_H_GRANULARITY;
     763             :                 /* fill the Vsync values */
     764           0 :                 drm_mode->vsync_start = drm_mode->vdisplay + CVT_MIN_V_PORCH;
     765           0 :                 drm_mode->vsync_end = drm_mode->vsync_start + vsync;
     766             :         } else {
     767             :                 /* Reduced blanking */
     768             :                 /* Minimum vertical blanking interval time (µs)- default 460 */
     769             : #define CVT_RB_MIN_VBLANK       460
     770             :                 /* Fixed number of clocks for horizontal sync */
     771             : #define CVT_RB_H_SYNC           32
     772             :                 /* Fixed number of clocks for horizontal blanking */
     773             : #define CVT_RB_H_BLANK          160
     774             :                 /* Fixed number of lines for vertical front porch - default 3*/
     775             : #define CVT_RB_VFPORCH          3
     776             :                 int vbilines;
     777             :                 int tmp1, tmp2;
     778             :                 /* 8. Estimate Horizontal period. */
     779           0 :                 tmp1 = HV_FACTOR * 1000000 -
     780           0 :                         CVT_RB_MIN_VBLANK * HV_FACTOR * vfieldrate;
     781           0 :                 tmp2 = vdisplay_rnd + 2 * vmargin;
     782           0 :                 hperiod = tmp1 / (tmp2 * vfieldrate);
     783             :                 /* 9. Find number of lines in vertical blanking */
     784           0 :                 vbilines = CVT_RB_MIN_VBLANK * HV_FACTOR / hperiod + 1;
     785             :                 /* 10. Check if vertical blanking is sufficient */
     786           0 :                 if (vbilines < (CVT_RB_VFPORCH + vsync + CVT_MIN_V_BPORCH))
     787           0 :                         vbilines = CVT_RB_VFPORCH + vsync + CVT_MIN_V_BPORCH;
     788             :                 /* 11. Find total number of lines in vertical field */
     789           0 :                 drm_mode->vtotal = vdisplay_rnd + 2 * vmargin + vbilines;
     790             :                 /* 12. Find total number of pixels in a line */
     791           0 :                 drm_mode->htotal = drm_mode->hdisplay + CVT_RB_H_BLANK;
     792             :                 /* Fill in HSync values */
     793           0 :                 drm_mode->hsync_end = drm_mode->hdisplay + CVT_RB_H_BLANK / 2;
     794           0 :                 drm_mode->hsync_start = drm_mode->hsync_end - CVT_RB_H_SYNC;
     795             :                 /* Fill in VSync values */
     796           0 :                 drm_mode->vsync_start = drm_mode->vdisplay + CVT_RB_VFPORCH;
     797           0 :                 drm_mode->vsync_end = drm_mode->vsync_start + vsync;
     798             :         }
     799             :         /* 15/13. Find pixel clock frequency (kHz for xf86) */
     800           0 :         tmp = drm_mode->htotal; /* perform intermediate calcs in u64 */
     801           0 :         tmp *= HV_FACTOR * 1000;
     802           0 :         do_div(tmp, hperiod);
     803           0 :         tmp -= drm_mode->clock % CVT_CLOCK_STEP;
     804           0 :         drm_mode->clock = tmp;
     805             :         /* 18/16. Find actual vertical frame frequency */
     806             :         /* ignore - just set the mode flag for interlaced */
     807           0 :         if (interlaced) {
     808           0 :                 drm_mode->vtotal *= 2;
     809           0 :                 drm_mode->flags |= DRM_MODE_FLAG_INTERLACE;
     810             :         }
     811             :         /* Fill the mode line name */
     812           0 :         drm_mode_set_name(drm_mode);
     813           0 :         if (reduced)
     814           0 :                 drm_mode->flags |= (DRM_MODE_FLAG_PHSYNC |
     815             :                                         DRM_MODE_FLAG_NVSYNC);
     816             :         else
     817           0 :                 drm_mode->flags |= (DRM_MODE_FLAG_PVSYNC |
     818             :                                         DRM_MODE_FLAG_NHSYNC);
     819             : 
     820             :         return drm_mode;
     821             : }
     822             : EXPORT_SYMBOL(drm_cvt_mode);
     823             : 
     824             : /**
     825             :  * drm_gtf_mode_complex - create the modeline based on the full GTF algorithm
     826             :  * @dev: drm device
     827             :  * @hdisplay: hdisplay size
     828             :  * @vdisplay: vdisplay size
     829             :  * @vrefresh: vrefresh rate.
     830             :  * @interlaced: whether to compute an interlaced mode
     831             :  * @margins: desired margin (borders) size
     832             :  * @GTF_M: extended GTF formula parameters
     833             :  * @GTF_2C: extended GTF formula parameters
     834             :  * @GTF_K: extended GTF formula parameters
     835             :  * @GTF_2J: extended GTF formula parameters
     836             :  *
     837             :  * GTF feature blocks specify C and J in multiples of 0.5, so we pass them
     838             :  * in here multiplied by two.  For a C of 40, pass in 80.
     839             :  *
     840             :  * Returns:
     841             :  * The modeline based on the full GTF algorithm stored in a drm_display_mode object.
     842             :  * The display mode object is allocated with drm_mode_create(). Returns NULL
     843             :  * when no mode could be allocated.
     844             :  */
     845             : struct drm_display_mode *
     846           0 : drm_gtf_mode_complex(struct drm_device *dev, int hdisplay, int vdisplay,
     847             :                      int vrefresh, bool interlaced, int margins,
     848             :                      int GTF_M, int GTF_2C, int GTF_K, int GTF_2J)
     849             : {       /* 1) top/bottom margin size (% of height) - default: 1.8, */
     850             : #define GTF_MARGIN_PERCENTAGE           18
     851             :         /* 2) character cell horizontal granularity (pixels) - default 8 */
     852             : #define GTF_CELL_GRAN                   8
     853             :         /* 3) Minimum vertical porch (lines) - default 3 */
     854             : #define GTF_MIN_V_PORCH                 1
     855             :         /* width of vsync in lines */
     856             : #define V_SYNC_RQD                      3
     857             :         /* width of hsync as % of total line */
     858             : #define H_SYNC_PERCENT                  8
     859             :         /* min time of vsync + back porch (microsec) */
     860             : #define MIN_VSYNC_PLUS_BP               550
     861             :         /* C' and M' are part of the Blanking Duty Cycle computation */
     862             : #define GTF_C_PRIME     ((((GTF_2C - GTF_2J) * GTF_K / 256) + GTF_2J) / 2)
     863             : #define GTF_M_PRIME     (GTF_K * GTF_M / 256)
     864             :         struct drm_display_mode *drm_mode;
     865             :         unsigned int hdisplay_rnd, vdisplay_rnd, vfieldrate_rqd;
     866             :         int top_margin, bottom_margin;
     867             :         int interlace;
     868             :         unsigned int hfreq_est;
     869             :         int vsync_plus_bp, __maybe_unused vback_porch;
     870             :         unsigned int vtotal_lines, __maybe_unused vfieldrate_est;
     871             :         unsigned int __maybe_unused hperiod;
     872             :         unsigned int vfield_rate, __maybe_unused vframe_rate;
     873             :         int left_margin, right_margin;
     874             :         unsigned int total_active_pixels, ideal_duty_cycle;
     875             :         unsigned int hblank, total_pixels, pixel_freq;
     876             :         int hsync, hfront_porch, vodd_front_porch_lines;
     877             :         unsigned int tmp1, tmp2;
     878             : 
     879           0 :         if (!hdisplay || !vdisplay)
     880             :                 return NULL;
     881             : 
     882           0 :         drm_mode = drm_mode_create(dev);
     883           0 :         if (!drm_mode)
     884             :                 return NULL;
     885             : 
     886             :         /* 1. In order to give correct results, the number of horizontal
     887             :          * pixels requested is first processed to ensure that it is divisible
     888             :          * by the character size, by rounding it to the nearest character
     889             :          * cell boundary:
     890             :          */
     891           0 :         hdisplay_rnd = (hdisplay + GTF_CELL_GRAN / 2) / GTF_CELL_GRAN;
     892           0 :         hdisplay_rnd = hdisplay_rnd * GTF_CELL_GRAN;
     893             : 
     894             :         /* 2. If interlace is requested, the number of vertical lines assumed
     895             :          * by the calculation must be halved, as the computation calculates
     896             :          * the number of vertical lines per field.
     897             :          */
     898           0 :         if (interlaced)
     899           0 :                 vdisplay_rnd = vdisplay / 2;
     900             :         else
     901           0 :                 vdisplay_rnd = vdisplay;
     902             : 
     903             :         /* 3. Find the frame rate required: */
     904           0 :         if (interlaced)
     905           0 :                 vfieldrate_rqd = vrefresh * 2;
     906             :         else
     907           0 :                 vfieldrate_rqd = vrefresh;
     908             : 
     909             :         /* 4. Find number of lines in Top margin: */
     910           0 :         top_margin = 0;
     911           0 :         if (margins)
     912           0 :                 top_margin = (vdisplay_rnd * GTF_MARGIN_PERCENTAGE + 500) /
     913             :                                 1000;
     914             :         /* 5. Find number of lines in bottom margin: */
     915           0 :         bottom_margin = top_margin;
     916             : 
     917             :         /* 6. If interlace is required, then set variable interlace: */
     918           0 :         if (interlaced)
     919             :                 interlace = 1;
     920             :         else
     921           0 :                 interlace = 0;
     922             : 
     923             :         /* 7. Estimate the Horizontal frequency */
     924             :         {
     925           0 :                 tmp1 = (1000000  - MIN_VSYNC_PLUS_BP * vfieldrate_rqd) / 500;
     926           0 :                 tmp2 = (vdisplay_rnd + 2 * top_margin + GTF_MIN_V_PORCH) *
     927           0 :                                 2 + interlace;
     928           0 :                 hfreq_est = (tmp2 * 1000 * vfieldrate_rqd) / tmp1;
     929             :         }
     930             : 
     931             :         /* 8. Find the number of lines in V sync + back porch */
     932             :         /* [V SYNC+BP] = RINT(([MIN VSYNC+BP] * hfreq_est / 1000000)) */
     933           0 :         vsync_plus_bp = MIN_VSYNC_PLUS_BP * hfreq_est / 1000;
     934           0 :         vsync_plus_bp = (vsync_plus_bp + 500) / 1000;
     935             :         /*  9. Find the number of lines in V back porch alone: */
     936           0 :         vback_porch = vsync_plus_bp - V_SYNC_RQD;
     937             :         /*  10. Find the total number of lines in Vertical field period: */
     938           0 :         vtotal_lines = vdisplay_rnd + top_margin + bottom_margin +
     939             :                         vsync_plus_bp + GTF_MIN_V_PORCH;
     940             :         /*  11. Estimate the Vertical field frequency: */
     941           0 :         vfieldrate_est = hfreq_est / vtotal_lines;
     942             :         /*  12. Find the actual horizontal period: */
     943           0 :         hperiod = 1000000 / (vfieldrate_rqd * vtotal_lines);
     944             : 
     945             :         /*  13. Find the actual Vertical field frequency: */
     946           0 :         vfield_rate = hfreq_est / vtotal_lines;
     947             :         /*  14. Find the Vertical frame frequency: */
     948             :         if (interlaced)
     949             :                 vframe_rate = vfield_rate / 2;
     950             :         else
     951             :                 vframe_rate = vfield_rate;
     952             :         /*  15. Find number of pixels in left margin: */
     953           0 :         if (margins)
     954           0 :                 left_margin = (hdisplay_rnd * GTF_MARGIN_PERCENTAGE + 500) /
     955             :                                 1000;
     956             :         else
     957             :                 left_margin = 0;
     958             : 
     959             :         /* 16.Find number of pixels in right margin: */
     960           0 :         right_margin = left_margin;
     961             :         /* 17.Find total number of active pixels in image and left and right */
     962           0 :         total_active_pixels = hdisplay_rnd + left_margin + right_margin;
     963             :         /* 18.Find the ideal blanking duty cycle from blanking duty cycle */
     964           0 :         ideal_duty_cycle = GTF_C_PRIME * 1000 -
     965           0 :                                 (GTF_M_PRIME * 1000000 / hfreq_est);
     966             :         /* 19.Find the number of pixels in the blanking time to the nearest
     967             :          * double character cell: */
     968           0 :         hblank = total_active_pixels * ideal_duty_cycle /
     969           0 :                         (100000 - ideal_duty_cycle);
     970           0 :         hblank = (hblank + GTF_CELL_GRAN) / (2 * GTF_CELL_GRAN);
     971           0 :         hblank = hblank * 2 * GTF_CELL_GRAN;
     972             :         /* 20.Find total number of pixels: */
     973           0 :         total_pixels = total_active_pixels + hblank;
     974             :         /* 21.Find pixel clock frequency: */
     975           0 :         pixel_freq = total_pixels * hfreq_est / 1000;
     976             :         /* Stage 1 computations are now complete; I should really pass
     977             :          * the results to another function and do the Stage 2 computations,
     978             :          * but I only need a few more values so I'll just append the
     979             :          * computations here for now */
     980             :         /* 17. Find the number of pixels in the horizontal sync period: */
     981           0 :         hsync = H_SYNC_PERCENT * total_pixels / 100;
     982           0 :         hsync = (hsync + GTF_CELL_GRAN / 2) / GTF_CELL_GRAN;
     983           0 :         hsync = hsync * GTF_CELL_GRAN;
     984             :         /* 18. Find the number of pixels in horizontal front porch period */
     985           0 :         hfront_porch = hblank / 2 - hsync;
     986             :         /*  36. Find the number of lines in the odd front porch period: */
     987           0 :         vodd_front_porch_lines = GTF_MIN_V_PORCH ;
     988             : 
     989             :         /* finally, pack the results in the mode struct */
     990           0 :         drm_mode->hdisplay = hdisplay_rnd;
     991           0 :         drm_mode->hsync_start = hdisplay_rnd + hfront_porch;
     992           0 :         drm_mode->hsync_end = drm_mode->hsync_start + hsync;
     993           0 :         drm_mode->htotal = total_pixels;
     994           0 :         drm_mode->vdisplay = vdisplay_rnd;
     995           0 :         drm_mode->vsync_start = vdisplay_rnd + vodd_front_porch_lines;
     996           0 :         drm_mode->vsync_end = drm_mode->vsync_start + V_SYNC_RQD;
     997           0 :         drm_mode->vtotal = vtotal_lines;
     998             : 
     999           0 :         drm_mode->clock = pixel_freq;
    1000             : 
    1001           0 :         if (interlaced) {
    1002           0 :                 drm_mode->vtotal *= 2;
    1003           0 :                 drm_mode->flags |= DRM_MODE_FLAG_INTERLACE;
    1004             :         }
    1005             : 
    1006           0 :         drm_mode_set_name(drm_mode);
    1007           0 :         if (GTF_M == 600 && GTF_2C == 80 && GTF_K == 128 && GTF_2J == 40)
    1008           0 :                 drm_mode->flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC;
    1009             :         else
    1010           0 :                 drm_mode->flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC;
    1011             : 
    1012             :         return drm_mode;
    1013             : }
    1014             : EXPORT_SYMBOL(drm_gtf_mode_complex);
    1015             : 
    1016             : /**
    1017             :  * drm_gtf_mode - create the modeline based on the GTF algorithm
    1018             :  * @dev: drm device
    1019             :  * @hdisplay: hdisplay size
    1020             :  * @vdisplay: vdisplay size
    1021             :  * @vrefresh: vrefresh rate.
    1022             :  * @interlaced: whether to compute an interlaced mode
    1023             :  * @margins: desired margin (borders) size
    1024             :  *
    1025             :  * return the modeline based on GTF algorithm
    1026             :  *
    1027             :  * This function is to create the modeline based on the GTF algorithm.
    1028             :  * Generalized Timing Formula is derived from:
    1029             :  *
    1030             :  *      GTF Spreadsheet by Andy Morrish (1/5/97)
    1031             :  *      available at https://www.vesa.org
    1032             :  *
    1033             :  * And it is copied from the file of xserver/hw/xfree86/modes/xf86gtf.c.
    1034             :  * What I have done is to translate it by using integer calculation.
    1035             :  * I also refer to the function of fb_get_mode in the file of
    1036             :  * drivers/video/fbmon.c
    1037             :  *
    1038             :  * Standard GTF parameters::
    1039             :  *
    1040             :  *     M = 600
    1041             :  *     C = 40
    1042             :  *     K = 128
    1043             :  *     J = 20
    1044             :  *
    1045             :  * Returns:
    1046             :  * The modeline based on the GTF algorithm stored in a drm_display_mode object.
    1047             :  * The display mode object is allocated with drm_mode_create(). Returns NULL
    1048             :  * when no mode could be allocated.
    1049             :  */
    1050             : struct drm_display_mode *
    1051           0 : drm_gtf_mode(struct drm_device *dev, int hdisplay, int vdisplay, int vrefresh,
    1052             :              bool interlaced, int margins)
    1053             : {
    1054           0 :         return drm_gtf_mode_complex(dev, hdisplay, vdisplay, vrefresh,
    1055             :                                     interlaced, margins,
    1056             :                                     600, 40 * 2, 128, 20 * 2);
    1057             : }
    1058             : EXPORT_SYMBOL(drm_gtf_mode);
    1059             : 
    1060             : #ifdef CONFIG_VIDEOMODE_HELPERS
    1061             : /**
    1062             :  * drm_display_mode_from_videomode - fill in @dmode using @vm,
    1063             :  * @vm: videomode structure to use as source
    1064             :  * @dmode: drm_display_mode structure to use as destination
    1065             :  *
    1066             :  * Fills out @dmode using the display mode specified in @vm.
    1067             :  */
    1068             : void drm_display_mode_from_videomode(const struct videomode *vm,
    1069             :                                      struct drm_display_mode *dmode)
    1070             : {
    1071             :         dmode->hdisplay = vm->hactive;
    1072             :         dmode->hsync_start = dmode->hdisplay + vm->hfront_porch;
    1073             :         dmode->hsync_end = dmode->hsync_start + vm->hsync_len;
    1074             :         dmode->htotal = dmode->hsync_end + vm->hback_porch;
    1075             : 
    1076             :         dmode->vdisplay = vm->vactive;
    1077             :         dmode->vsync_start = dmode->vdisplay + vm->vfront_porch;
    1078             :         dmode->vsync_end = dmode->vsync_start + vm->vsync_len;
    1079             :         dmode->vtotal = dmode->vsync_end + vm->vback_porch;
    1080             : 
    1081             :         dmode->clock = vm->pixelclock / 1000;
    1082             : 
    1083             :         dmode->flags = 0;
    1084             :         if (vm->flags & DISPLAY_FLAGS_HSYNC_HIGH)
    1085             :                 dmode->flags |= DRM_MODE_FLAG_PHSYNC;
    1086             :         else if (vm->flags & DISPLAY_FLAGS_HSYNC_LOW)
    1087             :                 dmode->flags |= DRM_MODE_FLAG_NHSYNC;
    1088             :         if (vm->flags & DISPLAY_FLAGS_VSYNC_HIGH)
    1089             :                 dmode->flags |= DRM_MODE_FLAG_PVSYNC;
    1090             :         else if (vm->flags & DISPLAY_FLAGS_VSYNC_LOW)
    1091             :                 dmode->flags |= DRM_MODE_FLAG_NVSYNC;
    1092             :         if (vm->flags & DISPLAY_FLAGS_INTERLACED)
    1093             :                 dmode->flags |= DRM_MODE_FLAG_INTERLACE;
    1094             :         if (vm->flags & DISPLAY_FLAGS_DOUBLESCAN)
    1095             :                 dmode->flags |= DRM_MODE_FLAG_DBLSCAN;
    1096             :         if (vm->flags & DISPLAY_FLAGS_DOUBLECLK)
    1097             :                 dmode->flags |= DRM_MODE_FLAG_DBLCLK;
    1098             :         drm_mode_set_name(dmode);
    1099             : }
    1100             : EXPORT_SYMBOL_GPL(drm_display_mode_from_videomode);
    1101             : 
    1102             : /**
    1103             :  * drm_display_mode_to_videomode - fill in @vm using @dmode,
    1104             :  * @dmode: drm_display_mode structure to use as source
    1105             :  * @vm: videomode structure to use as destination
    1106             :  *
    1107             :  * Fills out @vm using the display mode specified in @dmode.
    1108             :  */
    1109             : void drm_display_mode_to_videomode(const struct drm_display_mode *dmode,
    1110             :                                    struct videomode *vm)
    1111             : {
    1112             :         vm->hactive = dmode->hdisplay;
    1113             :         vm->hfront_porch = dmode->hsync_start - dmode->hdisplay;
    1114             :         vm->hsync_len = dmode->hsync_end - dmode->hsync_start;
    1115             :         vm->hback_porch = dmode->htotal - dmode->hsync_end;
    1116             : 
    1117             :         vm->vactive = dmode->vdisplay;
    1118             :         vm->vfront_porch = dmode->vsync_start - dmode->vdisplay;
    1119             :         vm->vsync_len = dmode->vsync_end - dmode->vsync_start;
    1120             :         vm->vback_porch = dmode->vtotal - dmode->vsync_end;
    1121             : 
    1122             :         vm->pixelclock = dmode->clock * 1000;
    1123             : 
    1124             :         vm->flags = 0;
    1125             :         if (dmode->flags & DRM_MODE_FLAG_PHSYNC)
    1126             :                 vm->flags |= DISPLAY_FLAGS_HSYNC_HIGH;
    1127             :         else if (dmode->flags & DRM_MODE_FLAG_NHSYNC)
    1128             :                 vm->flags |= DISPLAY_FLAGS_HSYNC_LOW;
    1129             :         if (dmode->flags & DRM_MODE_FLAG_PVSYNC)
    1130             :                 vm->flags |= DISPLAY_FLAGS_VSYNC_HIGH;
    1131             :         else if (dmode->flags & DRM_MODE_FLAG_NVSYNC)
    1132             :                 vm->flags |= DISPLAY_FLAGS_VSYNC_LOW;
    1133             :         if (dmode->flags & DRM_MODE_FLAG_INTERLACE)
    1134             :                 vm->flags |= DISPLAY_FLAGS_INTERLACED;
    1135             :         if (dmode->flags & DRM_MODE_FLAG_DBLSCAN)
    1136             :                 vm->flags |= DISPLAY_FLAGS_DOUBLESCAN;
    1137             :         if (dmode->flags & DRM_MODE_FLAG_DBLCLK)
    1138             :                 vm->flags |= DISPLAY_FLAGS_DOUBLECLK;
    1139             : }
    1140             : EXPORT_SYMBOL_GPL(drm_display_mode_to_videomode);
    1141             : 
    1142             : /**
    1143             :  * drm_bus_flags_from_videomode - extract information about pixelclk and
    1144             :  * DE polarity from videomode and store it in a separate variable
    1145             :  * @vm: videomode structure to use
    1146             :  * @bus_flags: information about pixelclk, sync and DE polarity will be stored
    1147             :  * here
    1148             :  *
    1149             :  * Sets DRM_BUS_FLAG_DE_(LOW|HIGH),  DRM_BUS_FLAG_PIXDATA_DRIVE_(POS|NEG)EDGE
    1150             :  * and DISPLAY_FLAGS_SYNC_(POS|NEG)EDGE in @bus_flags according to DISPLAY_FLAGS
    1151             :  * found in @vm
    1152             :  */
    1153             : void drm_bus_flags_from_videomode(const struct videomode *vm, u32 *bus_flags)
    1154             : {
    1155             :         *bus_flags = 0;
    1156             :         if (vm->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE)
    1157             :                 *bus_flags |= DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE;
    1158             :         if (vm->flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)
    1159             :                 *bus_flags |= DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE;
    1160             : 
    1161             :         if (vm->flags & DISPLAY_FLAGS_SYNC_POSEDGE)
    1162             :                 *bus_flags |= DRM_BUS_FLAG_SYNC_DRIVE_POSEDGE;
    1163             :         if (vm->flags & DISPLAY_FLAGS_SYNC_NEGEDGE)
    1164             :                 *bus_flags |= DRM_BUS_FLAG_SYNC_DRIVE_NEGEDGE;
    1165             : 
    1166             :         if (vm->flags & DISPLAY_FLAGS_DE_LOW)
    1167             :                 *bus_flags |= DRM_BUS_FLAG_DE_LOW;
    1168             :         if (vm->flags & DISPLAY_FLAGS_DE_HIGH)
    1169             :                 *bus_flags |= DRM_BUS_FLAG_DE_HIGH;
    1170             : }
    1171             : EXPORT_SYMBOL_GPL(drm_bus_flags_from_videomode);
    1172             : 
    1173             : #ifdef CONFIG_OF
    1174             : /**
    1175             :  * of_get_drm_display_mode - get a drm_display_mode from devicetree
    1176             :  * @np: device_node with the timing specification
    1177             :  * @dmode: will be set to the return value
    1178             :  * @bus_flags: information about pixelclk, sync and DE polarity
    1179             :  * @index: index into the list of display timings in devicetree
    1180             :  *
    1181             :  * This function is expensive and should only be used, if only one mode is to be
    1182             :  * read from DT. To get multiple modes start with of_get_display_timings and
    1183             :  * work with that instead.
    1184             :  *
    1185             :  * Returns:
    1186             :  * 0 on success, a negative errno code when no of videomode node was found.
    1187             :  */
    1188             : int of_get_drm_display_mode(struct device_node *np,
    1189             :                             struct drm_display_mode *dmode, u32 *bus_flags,
    1190             :                             int index)
    1191             : {
    1192             :         struct videomode vm;
    1193             :         int ret;
    1194             : 
    1195             :         ret = of_get_videomode(np, &vm, index);
    1196             :         if (ret)
    1197             :                 return ret;
    1198             : 
    1199             :         drm_display_mode_from_videomode(&vm, dmode);
    1200             :         if (bus_flags)
    1201             :                 drm_bus_flags_from_videomode(&vm, bus_flags);
    1202             : 
    1203             :         pr_debug("%pOF: got %dx%d display mode\n",
    1204             :                 np, vm.hactive, vm.vactive);
    1205             :         drm_mode_debug_printmodeline(dmode);
    1206             : 
    1207             :         return 0;
    1208             : }
    1209             : EXPORT_SYMBOL_GPL(of_get_drm_display_mode);
    1210             : 
    1211             : /**
    1212             :  * of_get_drm_panel_display_mode - get a panel-timing drm_display_mode from devicetree
    1213             :  * @np: device_node with the panel-timing specification
    1214             :  * @dmode: will be set to the return value
    1215             :  * @bus_flags: information about pixelclk, sync and DE polarity
    1216             :  *
    1217             :  * The mandatory Device Tree properties width-mm and height-mm
    1218             :  * are read and set on the display mode.
    1219             :  *
    1220             :  * Returns:
    1221             :  * Zero on success, negative error code on failure.
    1222             :  */
    1223             : int of_get_drm_panel_display_mode(struct device_node *np,
    1224             :                                   struct drm_display_mode *dmode, u32 *bus_flags)
    1225             : {
    1226             :         u32 width_mm = 0, height_mm = 0;
    1227             :         struct display_timing timing;
    1228             :         struct videomode vm;
    1229             :         int ret;
    1230             : 
    1231             :         ret = of_get_display_timing(np, "panel-timing", &timing);
    1232             :         if (ret)
    1233             :                 return ret;
    1234             : 
    1235             :         videomode_from_timing(&timing, &vm);
    1236             : 
    1237             :         memset(dmode, 0, sizeof(*dmode));
    1238             :         drm_display_mode_from_videomode(&vm, dmode);
    1239             :         if (bus_flags)
    1240             :                 drm_bus_flags_from_videomode(&vm, bus_flags);
    1241             : 
    1242             :         ret = of_property_read_u32(np, "width-mm", &width_mm);
    1243             :         if (ret)
    1244             :                 return ret;
    1245             : 
    1246             :         ret = of_property_read_u32(np, "height-mm", &height_mm);
    1247             :         if (ret)
    1248             :                 return ret;
    1249             : 
    1250             :         dmode->width_mm = width_mm;
    1251             :         dmode->height_mm = height_mm;
    1252             : 
    1253             :         drm_mode_debug_printmodeline(dmode);
    1254             : 
    1255             :         return 0;
    1256             : }
    1257             : EXPORT_SYMBOL_GPL(of_get_drm_panel_display_mode);
    1258             : #endif /* CONFIG_OF */
    1259             : #endif /* CONFIG_VIDEOMODE_HELPERS */
    1260             : 
    1261             : /**
    1262             :  * drm_mode_set_name - set the name on a mode
    1263             :  * @mode: name will be set in this mode
    1264             :  *
    1265             :  * Set the name of @mode to a standard format which is <hdisplay>x<vdisplay>
    1266             :  * with an optional 'i' suffix for interlaced modes.
    1267             :  */
    1268          47 : void drm_mode_set_name(struct drm_display_mode *mode)
    1269             : {
    1270          47 :         bool interlaced = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
    1271             : 
    1272         141 :         snprintf(mode->name, DRM_DISPLAY_MODE_LEN, "%dx%d%s",
    1273          94 :                  mode->hdisplay, mode->vdisplay,
    1274             :                  interlaced ? "i" : "");
    1275          47 : }
    1276             : EXPORT_SYMBOL(drm_mode_set_name);
    1277             : 
    1278             : /**
    1279             :  * drm_mode_vrefresh - get the vrefresh of a mode
    1280             :  * @mode: mode
    1281             :  *
    1282             :  * Returns:
    1283             :  * @modes's vrefresh rate in Hz, rounded to the nearest integer. Calculates the
    1284             :  * value first if it is not yet set.
    1285             :  */
    1286       18351 : int drm_mode_vrefresh(const struct drm_display_mode *mode)
    1287             : {
    1288             :         unsigned int num, den;
    1289             : 
    1290       18351 :         if (mode->htotal == 0 || mode->vtotal == 0)
    1291             :                 return 0;
    1292             : 
    1293       18351 :         num = mode->clock;
    1294       18351 :         den = mode->htotal * mode->vtotal;
    1295             : 
    1296       18351 :         if (mode->flags & DRM_MODE_FLAG_INTERLACE)
    1297        2479 :                 num *= 2;
    1298       18351 :         if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
    1299           0 :                 den *= 2;
    1300       18351 :         if (mode->vscan > 1)
    1301           0 :                 den *= mode->vscan;
    1302             : 
    1303       36702 :         return DIV_ROUND_CLOSEST_ULL(mul_u32_u32(num, 1000), den);
    1304             : }
    1305             : EXPORT_SYMBOL(drm_mode_vrefresh);
    1306             : 
    1307             : /**
    1308             :  * drm_mode_get_hv_timing - Fetches hdisplay/vdisplay for given mode
    1309             :  * @mode: mode to query
    1310             :  * @hdisplay: hdisplay value to fill in
    1311             :  * @vdisplay: vdisplay value to fill in
    1312             :  *
    1313             :  * The vdisplay value will be doubled if the specified mode is a stereo mode of
    1314             :  * the appropriate layout.
    1315             :  */
    1316          10 : void drm_mode_get_hv_timing(const struct drm_display_mode *mode,
    1317             :                             int *hdisplay, int *vdisplay)
    1318             : {
    1319             :         struct drm_display_mode adjusted;
    1320             : 
    1321          10 :         drm_mode_init(&adjusted, mode);
    1322             : 
    1323          10 :         drm_mode_set_crtcinfo(&adjusted, CRTC_STEREO_DOUBLE_ONLY);
    1324          10 :         *hdisplay = adjusted.crtc_hdisplay;
    1325          10 :         *vdisplay = adjusted.crtc_vdisplay;
    1326          10 : }
    1327             : EXPORT_SYMBOL(drm_mode_get_hv_timing);
    1328             : 
    1329             : /**
    1330             :  * drm_mode_set_crtcinfo - set CRTC modesetting timing parameters
    1331             :  * @p: mode
    1332             :  * @adjust_flags: a combination of adjustment flags
    1333             :  *
    1334             :  * Setup the CRTC modesetting timing parameters for @p, adjusting if necessary.
    1335             :  *
    1336             :  * - The CRTC_INTERLACE_HALVE_V flag can be used to halve vertical timings of
    1337             :  *   interlaced modes.
    1338             :  * - The CRTC_STEREO_DOUBLE flag can be used to compute the timings for
    1339             :  *   buffers containing two eyes (only adjust the timings when needed, eg. for
    1340             :  *   "frame packing" or "side by side full").
    1341             :  * - The CRTC_NO_DBLSCAN and CRTC_NO_VSCAN flags request that adjustment *not*
    1342             :  *   be performed for doublescan and vscan > 1 modes respectively.
    1343             :  */
    1344         135 : void drm_mode_set_crtcinfo(struct drm_display_mode *p, int adjust_flags)
    1345             : {
    1346         135 :         if (!p)
    1347             :                 return;
    1348             : 
    1349         135 :         p->crtc_clock = p->clock;
    1350         135 :         p->crtc_hdisplay = p->hdisplay;
    1351         135 :         p->crtc_hsync_start = p->hsync_start;
    1352         135 :         p->crtc_hsync_end = p->hsync_end;
    1353         135 :         p->crtc_htotal = p->htotal;
    1354         135 :         p->crtc_hskew = p->hskew;
    1355         135 :         p->crtc_vdisplay = p->vdisplay;
    1356         135 :         p->crtc_vsync_start = p->vsync_start;
    1357         135 :         p->crtc_vsync_end = p->vsync_end;
    1358         135 :         p->crtc_vtotal = p->vtotal;
    1359             : 
    1360         135 :         if (p->flags & DRM_MODE_FLAG_INTERLACE) {
    1361          10 :                 if (adjust_flags & CRTC_INTERLACE_HALVE_V) {
    1362          10 :                         p->crtc_vdisplay /= 2;
    1363          10 :                         p->crtc_vsync_start /= 2;
    1364          10 :                         p->crtc_vsync_end /= 2;
    1365          10 :                         p->crtc_vtotal /= 2;
    1366             :                 }
    1367             :         }
    1368             : 
    1369         135 :         if (!(adjust_flags & CRTC_NO_DBLSCAN)) {
    1370         125 :                 if (p->flags & DRM_MODE_FLAG_DBLSCAN) {
    1371           0 :                         p->crtc_vdisplay *= 2;
    1372           0 :                         p->crtc_vsync_start *= 2;
    1373           0 :                         p->crtc_vsync_end *= 2;
    1374           0 :                         p->crtc_vtotal *= 2;
    1375             :                 }
    1376             :         }
    1377             : 
    1378         135 :         if (!(adjust_flags & CRTC_NO_VSCAN)) {
    1379         125 :                 if (p->vscan > 1) {
    1380           0 :                         p->crtc_vdisplay *= p->vscan;
    1381           0 :                         p->crtc_vsync_start *= p->vscan;
    1382           0 :                         p->crtc_vsync_end *= p->vscan;
    1383           0 :                         p->crtc_vtotal *= p->vscan;
    1384             :                 }
    1385             :         }
    1386             : 
    1387         135 :         if (adjust_flags & CRTC_STEREO_DOUBLE) {
    1388          10 :                 unsigned int layout = p->flags & DRM_MODE_FLAG_3D_MASK;
    1389             : 
    1390          10 :                 switch (layout) {
    1391             :                 case DRM_MODE_FLAG_3D_FRAME_PACKING:
    1392           0 :                         p->crtc_clock *= 2;
    1393           0 :                         p->crtc_vdisplay += p->crtc_vtotal;
    1394           0 :                         p->crtc_vsync_start += p->crtc_vtotal;
    1395           0 :                         p->crtc_vsync_end += p->crtc_vtotal;
    1396           0 :                         p->crtc_vtotal += p->crtc_vtotal;
    1397           0 :                         break;
    1398             :                 }
    1399             :         }
    1400             : 
    1401         135 :         p->crtc_vblank_start = min(p->crtc_vsync_start, p->crtc_vdisplay);
    1402         135 :         p->crtc_vblank_end = max(p->crtc_vsync_end, p->crtc_vtotal);
    1403         135 :         p->crtc_hblank_start = min(p->crtc_hsync_start, p->crtc_hdisplay);
    1404         135 :         p->crtc_hblank_end = max(p->crtc_hsync_end, p->crtc_htotal);
    1405             : }
    1406             : EXPORT_SYMBOL(drm_mode_set_crtcinfo);
    1407             : 
    1408             : /**
    1409             :  * drm_mode_copy - copy the mode
    1410             :  * @dst: mode to overwrite
    1411             :  * @src: mode to copy
    1412             :  *
    1413             :  * Copy an existing mode into another mode, preserving the
    1414             :  * list head of the destination mode.
    1415             :  */
    1416           0 : void drm_mode_copy(struct drm_display_mode *dst, const struct drm_display_mode *src)
    1417             : {
    1418       17876 :         struct list_head head = dst->head;
    1419             : 
    1420       17876 :         *dst = *src;
    1421       17876 :         dst->head = head;
    1422           0 : }
    1423             : EXPORT_SYMBOL(drm_mode_copy);
    1424             : 
    1425             : /**
    1426             :  * drm_mode_init - initialize the mode from another mode
    1427             :  * @dst: mode to overwrite
    1428             :  * @src: mode to copy
    1429             :  *
    1430             :  * Copy an existing mode into another mode, zeroing the
    1431             :  * list head of the destination mode. Typically used
    1432             :  * to guarantee the list head is not left with stack
    1433             :  * garbage in on-stack modes.
    1434             :  */
    1435       17735 : void drm_mode_init(struct drm_display_mode *dst, const struct drm_display_mode *src)
    1436             : {
    1437       17745 :         memset(dst, 0, sizeof(*dst));
    1438       17745 :         drm_mode_copy(dst, src);
    1439       17735 : }
    1440             : EXPORT_SYMBOL(drm_mode_init);
    1441             : 
    1442             : /**
    1443             :  * drm_mode_duplicate - allocate and duplicate an existing mode
    1444             :  * @dev: drm_device to allocate the duplicated mode for
    1445             :  * @mode: mode to duplicate
    1446             :  *
    1447             :  * Just allocate a new mode, copy the existing mode into it, and return
    1448             :  * a pointer to it.  Used to create new instances of established modes.
    1449             :  *
    1450             :  * Returns:
    1451             :  * Pointer to duplicated mode on success, NULL on error.
    1452             :  */
    1453         131 : struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev,
    1454             :                                             const struct drm_display_mode *mode)
    1455             : {
    1456             :         struct drm_display_mode *nmode;
    1457             : 
    1458         131 :         nmode = drm_mode_create(dev);
    1459         131 :         if (!nmode)
    1460             :                 return NULL;
    1461             : 
    1462         131 :         drm_mode_copy(nmode, mode);
    1463             : 
    1464         131 :         return nmode;
    1465             : }
    1466             : EXPORT_SYMBOL(drm_mode_duplicate);
    1467             : 
    1468             : static bool drm_mode_match_timings(const struct drm_display_mode *mode1,
    1469             :                                    const struct drm_display_mode *mode2)
    1470             : {
    1471        2242 :         return mode1->hdisplay == mode2->hdisplay &&
    1472             :                 mode1->hsync_start == mode2->hsync_start &&
    1473             :                 mode1->hsync_end == mode2->hsync_end &&
    1474             :                 mode1->htotal == mode2->htotal &&
    1475          97 :                 mode1->hskew == mode2->hskew &&
    1476             :                 mode1->vdisplay == mode2->vdisplay &&
    1477             :                 mode1->vsync_start == mode2->vsync_start &&
    1478             :                 mode1->vsync_end == mode2->vsync_end &&
    1479        2284 :                 mode1->vtotal == mode2->vtotal &&
    1480             :                 mode1->vscan == mode2->vscan;
    1481             : }
    1482             : 
    1483             : static bool drm_mode_match_clock(const struct drm_display_mode *mode1,
    1484             :                                   const struct drm_display_mode *mode2)
    1485             : {
    1486             :         /*
    1487             :          * do clock check convert to PICOS
    1488             :          * so fb modes get matched the same
    1489             :          */
    1490          17 :         if (mode1->clock && mode2->clock)
    1491          17 :                 return KHZ2PICOS(mode1->clock) == KHZ2PICOS(mode2->clock);
    1492             :         else
    1493           0 :                 return mode1->clock == mode2->clock;
    1494             : }
    1495             : 
    1496             : static bool drm_mode_match_flags(const struct drm_display_mode *mode1,
    1497             :                                  const struct drm_display_mode *mode2)
    1498             : {
    1499          37 :         return (mode1->flags & ~DRM_MODE_FLAG_3D_MASK) ==
    1500             :                 (mode2->flags & ~DRM_MODE_FLAG_3D_MASK);
    1501             : }
    1502             : 
    1503             : static bool drm_mode_match_3d_flags(const struct drm_display_mode *mode1,
    1504             :                                     const struct drm_display_mode *mode2)
    1505             : {
    1506          17 :         return (mode1->flags & DRM_MODE_FLAG_3D_MASK) ==
    1507             :                 (mode2->flags & DRM_MODE_FLAG_3D_MASK);
    1508             : }
    1509             : 
    1510             : static bool drm_mode_match_aspect_ratio(const struct drm_display_mode *mode1,
    1511             :                                         const struct drm_display_mode *mode2)
    1512             : {
    1513             :         return mode1->picture_aspect_ratio == mode2->picture_aspect_ratio;
    1514             : }
    1515             : 
    1516             : /**
    1517             :  * drm_mode_match - test modes for (partial) equality
    1518             :  * @mode1: first mode
    1519             :  * @mode2: second mode
    1520             :  * @match_flags: which parts need to match (DRM_MODE_MATCH_*)
    1521             :  *
    1522             :  * Check to see if @mode1 and @mode2 are equivalent.
    1523             :  *
    1524             :  * Returns:
    1525             :  * True if the modes are (partially) equal, false otherwise.
    1526             :  */
    1527        2242 : bool drm_mode_match(const struct drm_display_mode *mode1,
    1528             :                     const struct drm_display_mode *mode2,
    1529             :                     unsigned int match_flags)
    1530             : {
    1531        2242 :         if (!mode1 && !mode2)
    1532             :                 return true;
    1533             : 
    1534        2242 :         if (!mode1 || !mode2)
    1535             :                 return false;
    1536             : 
    1537        4484 :         if (match_flags & DRM_MODE_MATCH_TIMINGS &&
    1538        2242 :             !drm_mode_match_timings(mode1, mode2))
    1539             :                 return false;
    1540             : 
    1541          54 :         if (match_flags & DRM_MODE_MATCH_CLOCK &&
    1542          17 :             !drm_mode_match_clock(mode1, mode2))
    1543             :                 return false;
    1544             : 
    1545          74 :         if (match_flags & DRM_MODE_MATCH_FLAGS &&
    1546          37 :             !drm_mode_match_flags(mode1, mode2))
    1547             :                 return false;
    1548             : 
    1549          44 :         if (match_flags & DRM_MODE_MATCH_3D_FLAGS &&
    1550          17 :             !drm_mode_match_3d_flags(mode1, mode2))
    1551             :                 return false;
    1552             : 
    1553          44 :         if (match_flags & DRM_MODE_MATCH_ASPECT_RATIO &&
    1554          17 :             !drm_mode_match_aspect_ratio(mode1, mode2))
    1555             :                 return false;
    1556             : 
    1557             :         return true;
    1558             : }
    1559             : EXPORT_SYMBOL(drm_mode_match);
    1560             : 
    1561             : /**
    1562             :  * drm_mode_equal - test modes for equality
    1563             :  * @mode1: first mode
    1564             :  * @mode2: second mode
    1565             :  *
    1566             :  * Check to see if @mode1 and @mode2 are equivalent.
    1567             :  *
    1568             :  * Returns:
    1569             :  * True if the modes are equal, false otherwise.
    1570             :  */
    1571          17 : bool drm_mode_equal(const struct drm_display_mode *mode1,
    1572             :                     const struct drm_display_mode *mode2)
    1573             : {
    1574        1907 :         return drm_mode_match(mode1, mode2,
    1575             :                               DRM_MODE_MATCH_TIMINGS |
    1576             :                               DRM_MODE_MATCH_CLOCK |
    1577             :                               DRM_MODE_MATCH_FLAGS |
    1578             :                               DRM_MODE_MATCH_3D_FLAGS|
    1579             :                               DRM_MODE_MATCH_ASPECT_RATIO);
    1580             : }
    1581             : EXPORT_SYMBOL(drm_mode_equal);
    1582             : 
    1583             : /**
    1584             :  * drm_mode_equal_no_clocks - test modes for equality
    1585             :  * @mode1: first mode
    1586             :  * @mode2: second mode
    1587             :  *
    1588             :  * Check to see if @mode1 and @mode2 are equivalent, but
    1589             :  * don't check the pixel clocks.
    1590             :  *
    1591             :  * Returns:
    1592             :  * True if the modes are equal, false otherwise.
    1593             :  */
    1594           0 : bool drm_mode_equal_no_clocks(const struct drm_display_mode *mode1,
    1595             :                               const struct drm_display_mode *mode2)
    1596             : {
    1597           0 :         return drm_mode_match(mode1, mode2,
    1598             :                               DRM_MODE_MATCH_TIMINGS |
    1599             :                               DRM_MODE_MATCH_FLAGS |
    1600             :                               DRM_MODE_MATCH_3D_FLAGS);
    1601             : }
    1602             : EXPORT_SYMBOL(drm_mode_equal_no_clocks);
    1603             : 
    1604             : /**
    1605             :  * drm_mode_equal_no_clocks_no_stereo - test modes for equality
    1606             :  * @mode1: first mode
    1607             :  * @mode2: second mode
    1608             :  *
    1609             :  * Check to see if @mode1 and @mode2 are equivalent, but
    1610             :  * don't check the pixel clocks nor the stereo layout.
    1611             :  *
    1612             :  * Returns:
    1613             :  * True if the modes are equal, false otherwise.
    1614             :  */
    1615           0 : bool drm_mode_equal_no_clocks_no_stereo(const struct drm_display_mode *mode1,
    1616             :                                         const struct drm_display_mode *mode2)
    1617             : {
    1618           0 :         return drm_mode_match(mode1, mode2,
    1619             :                               DRM_MODE_MATCH_TIMINGS |
    1620             :                               DRM_MODE_MATCH_FLAGS);
    1621             : }
    1622             : EXPORT_SYMBOL(drm_mode_equal_no_clocks_no_stereo);
    1623             : 
    1624             : static enum drm_mode_status
    1625         140 : drm_mode_validate_basic(const struct drm_display_mode *mode)
    1626             : {
    1627         140 :         if (mode->type & ~DRM_MODE_TYPE_ALL)
    1628             :                 return MODE_BAD;
    1629             : 
    1630         140 :         if (mode->flags & ~DRM_MODE_FLAG_ALL)
    1631             :                 return MODE_BAD;
    1632             : 
    1633         140 :         if ((mode->flags & DRM_MODE_FLAG_3D_MASK) > DRM_MODE_FLAG_3D_MAX)
    1634             :                 return MODE_BAD;
    1635             : 
    1636         140 :         if (mode->clock == 0)
    1637             :                 return MODE_CLOCK_LOW;
    1638             : 
    1639         280 :         if (mode->hdisplay == 0 ||
    1640         280 :             mode->hsync_start < mode->hdisplay ||
    1641         280 :             mode->hsync_end < mode->hsync_start ||
    1642         140 :             mode->htotal < mode->hsync_end)
    1643             :                 return MODE_H_ILLEGAL;
    1644             : 
    1645         280 :         if (mode->vdisplay == 0 ||
    1646         280 :             mode->vsync_start < mode->vdisplay ||
    1647         280 :             mode->vsync_end < mode->vsync_start ||
    1648         140 :             mode->vtotal < mode->vsync_end)
    1649             :                 return MODE_V_ILLEGAL;
    1650             : 
    1651         140 :         return MODE_OK;
    1652             : }
    1653             : 
    1654             : /**
    1655             :  * drm_mode_validate_driver - make sure the mode is somewhat sane
    1656             :  * @dev: drm device
    1657             :  * @mode: mode to check
    1658             :  *
    1659             :  * First do basic validation on the mode, and then allow the driver
    1660             :  * to check for device/driver specific limitations via the optional
    1661             :  * &drm_mode_config_helper_funcs.mode_valid hook.
    1662             :  *
    1663             :  * Returns:
    1664             :  * The mode status
    1665             :  */
    1666             : enum drm_mode_status
    1667         140 : drm_mode_validate_driver(struct drm_device *dev,
    1668             :                         const struct drm_display_mode *mode)
    1669             : {
    1670             :         enum drm_mode_status status;
    1671             : 
    1672         140 :         status = drm_mode_validate_basic(mode);
    1673         140 :         if (status != MODE_OK)
    1674             :                 return status;
    1675             : 
    1676         140 :         if (dev->mode_config.funcs->mode_valid)
    1677           0 :                 return dev->mode_config.funcs->mode_valid(dev, mode);
    1678             :         else
    1679             :                 return MODE_OK;
    1680             : }
    1681             : EXPORT_SYMBOL(drm_mode_validate_driver);
    1682             : 
    1683             : /**
    1684             :  * drm_mode_validate_size - make sure modes adhere to size constraints
    1685             :  * @mode: mode to check
    1686             :  * @maxX: maximum width
    1687             :  * @maxY: maximum height
    1688             :  *
    1689             :  * This function is a helper which can be used to validate modes against size
    1690             :  * limitations of the DRM device/connector. If a mode is too big its status
    1691             :  * member is updated with the appropriate validation failure code. The list
    1692             :  * itself is not changed.
    1693             :  *
    1694             :  * Returns:
    1695             :  * The mode status
    1696             :  */
    1697             : enum drm_mode_status
    1698         140 : drm_mode_validate_size(const struct drm_display_mode *mode,
    1699             :                        int maxX, int maxY)
    1700             : {
    1701         140 :         if (maxX > 0 && mode->hdisplay > maxX)
    1702             :                 return MODE_VIRTUAL_X;
    1703             : 
    1704         140 :         if (maxY > 0 && mode->vdisplay > maxY)
    1705             :                 return MODE_VIRTUAL_Y;
    1706             : 
    1707         125 :         return MODE_OK;
    1708             : }
    1709             : EXPORT_SYMBOL(drm_mode_validate_size);
    1710             : 
    1711             : /**
    1712             :  * drm_mode_validate_ycbcr420 - add 'ycbcr420-only' modes only when allowed
    1713             :  * @mode: mode to check
    1714             :  * @connector: drm connector under action
    1715             :  *
    1716             :  * This function is a helper which can be used to filter out any YCBCR420
    1717             :  * only mode, when the source doesn't support it.
    1718             :  *
    1719             :  * Returns:
    1720             :  * The mode status
    1721             :  */
    1722             : enum drm_mode_status
    1723         125 : drm_mode_validate_ycbcr420(const struct drm_display_mode *mode,
    1724             :                            struct drm_connector *connector)
    1725             : {
    1726         250 :         if (!connector->ycbcr_420_allowed &&
    1727         125 :             drm_mode_is_420_only(&connector->display_info, mode))
    1728             :                 return MODE_NO_420;
    1729             : 
    1730             :         return MODE_OK;
    1731             : }
    1732             : EXPORT_SYMBOL(drm_mode_validate_ycbcr420);
    1733             : 
    1734             : #define MODE_STATUS(status) [MODE_ ## status + 3] = #status
    1735             : 
    1736             : static const char * const drm_mode_status_names[] = {
    1737             :         MODE_STATUS(OK),
    1738             :         MODE_STATUS(HSYNC),
    1739             :         MODE_STATUS(VSYNC),
    1740             :         MODE_STATUS(H_ILLEGAL),
    1741             :         MODE_STATUS(V_ILLEGAL),
    1742             :         MODE_STATUS(BAD_WIDTH),
    1743             :         MODE_STATUS(NOMODE),
    1744             :         MODE_STATUS(NO_INTERLACE),
    1745             :         MODE_STATUS(NO_DBLESCAN),
    1746             :         MODE_STATUS(NO_VSCAN),
    1747             :         MODE_STATUS(MEM),
    1748             :         MODE_STATUS(VIRTUAL_X),
    1749             :         MODE_STATUS(VIRTUAL_Y),
    1750             :         MODE_STATUS(MEM_VIRT),
    1751             :         MODE_STATUS(NOCLOCK),
    1752             :         MODE_STATUS(CLOCK_HIGH),
    1753             :         MODE_STATUS(CLOCK_LOW),
    1754             :         MODE_STATUS(CLOCK_RANGE),
    1755             :         MODE_STATUS(BAD_HVALUE),
    1756             :         MODE_STATUS(BAD_VVALUE),
    1757             :         MODE_STATUS(BAD_VSCAN),
    1758             :         MODE_STATUS(HSYNC_NARROW),
    1759             :         MODE_STATUS(HSYNC_WIDE),
    1760             :         MODE_STATUS(HBLANK_NARROW),
    1761             :         MODE_STATUS(HBLANK_WIDE),
    1762             :         MODE_STATUS(VSYNC_NARROW),
    1763             :         MODE_STATUS(VSYNC_WIDE),
    1764             :         MODE_STATUS(VBLANK_NARROW),
    1765             :         MODE_STATUS(VBLANK_WIDE),
    1766             :         MODE_STATUS(PANEL),
    1767             :         MODE_STATUS(INTERLACE_WIDTH),
    1768             :         MODE_STATUS(ONE_WIDTH),
    1769             :         MODE_STATUS(ONE_HEIGHT),
    1770             :         MODE_STATUS(ONE_SIZE),
    1771             :         MODE_STATUS(NO_REDUCED),
    1772             :         MODE_STATUS(NO_STEREO),
    1773             :         MODE_STATUS(NO_420),
    1774             :         MODE_STATUS(STALE),
    1775             :         MODE_STATUS(BAD),
    1776             :         MODE_STATUS(ERROR),
    1777             : };
    1778             : 
    1779             : #undef MODE_STATUS
    1780             : 
    1781          15 : const char *drm_get_mode_status_name(enum drm_mode_status status)
    1782             : {
    1783          15 :         int index = status + 3;
    1784             : 
    1785          15 :         if (WARN_ON(index < 0 || index >= ARRAY_SIZE(drm_mode_status_names)))
    1786             :                 return "";
    1787             : 
    1788          15 :         return drm_mode_status_names[index];
    1789             : }
    1790             : 
    1791             : /**
    1792             :  * drm_mode_prune_invalid - remove invalid modes from mode list
    1793             :  * @dev: DRM device
    1794             :  * @mode_list: list of modes to check
    1795             :  * @verbose: be verbose about it
    1796             :  *
    1797             :  * This helper function can be used to prune a display mode list after
    1798             :  * validation has been completed. All modes whose status is not MODE_OK will be
    1799             :  * removed from the list, and if @verbose the status code and mode name is also
    1800             :  * printed to dmesg.
    1801             :  */
    1802           5 : void drm_mode_prune_invalid(struct drm_device *dev,
    1803             :                             struct list_head *mode_list, bool verbose)
    1804             : {
    1805             :         struct drm_display_mode *mode, *t;
    1806             : 
    1807         145 :         list_for_each_entry_safe(mode, t, mode_list, head) {
    1808         140 :                 if (mode->status != MODE_OK) {
    1809          30 :                         list_del(&mode->head);
    1810          15 :                         if (mode->type & DRM_MODE_TYPE_USERDEF) {
    1811           0 :                                 drm_warn(dev, "User-defined mode not supported: "
    1812             :                                          DRM_MODE_FMT "\n", DRM_MODE_ARG(mode));
    1813             :                         }
    1814          15 :                         if (verbose) {
    1815          15 :                                 drm_mode_debug_printmodeline(mode);
    1816          15 :                                 DRM_DEBUG_KMS("Not using %s mode: %s\n",
    1817             :                                               mode->name,
    1818             :                                               drm_get_mode_status_name(mode->status));
    1819             :                         }
    1820             :                         drm_mode_destroy(dev, mode);
    1821             :                 }
    1822             :         }
    1823           5 : }
    1824             : EXPORT_SYMBOL(drm_mode_prune_invalid);
    1825             : 
    1826             : /**
    1827             :  * drm_mode_compare - compare modes for favorability
    1828             :  * @priv: unused
    1829             :  * @lh_a: list_head for first mode
    1830             :  * @lh_b: list_head for second mode
    1831             :  *
    1832             :  * Compare two modes, given by @lh_a and @lh_b, returning a value indicating
    1833             :  * which is better.
    1834             :  *
    1835             :  * Returns:
    1836             :  * Negative if @lh_a is better than @lh_b, zero if they're equivalent, or
    1837             :  * positive if @lh_b is better than @lh_a.
    1838             :  */
    1839         395 : static int drm_mode_compare(void *priv, const struct list_head *lh_a,
    1840             :                             const struct list_head *lh_b)
    1841             : {
    1842         395 :         struct drm_display_mode *a = list_entry(lh_a, struct drm_display_mode, head);
    1843         395 :         struct drm_display_mode *b = list_entry(lh_b, struct drm_display_mode, head);
    1844             :         int diff;
    1845             : 
    1846         790 :         diff = ((b->type & DRM_MODE_TYPE_PREFERRED) != 0) -
    1847         395 :                 ((a->type & DRM_MODE_TYPE_PREFERRED) != 0);
    1848         395 :         if (diff)
    1849             :                 return diff;
    1850         395 :         diff = b->hdisplay * b->vdisplay - a->hdisplay * a->vdisplay;
    1851         395 :         if (diff)
    1852             :                 return diff;
    1853             : 
    1854          35 :         diff = drm_mode_vrefresh(b) - drm_mode_vrefresh(a);
    1855          35 :         if (diff)
    1856             :                 return diff;
    1857             : 
    1858          30 :         diff = b->clock - a->clock;
    1859          30 :         return diff;
    1860             : }
    1861             : 
    1862             : /**
    1863             :  * drm_mode_sort - sort mode list
    1864             :  * @mode_list: list of drm_display_mode structures to sort
    1865             :  *
    1866             :  * Sort @mode_list by favorability, moving good modes to the head of the list.
    1867             :  */
    1868           5 : void drm_mode_sort(struct list_head *mode_list)
    1869             : {
    1870           5 :         list_sort(NULL, mode_list, drm_mode_compare);
    1871           5 : }
    1872             : EXPORT_SYMBOL(drm_mode_sort);
    1873             : 
    1874             : /**
    1875             :  * drm_connector_list_update - update the mode list for the connector
    1876             :  * @connector: the connector to update
    1877             :  *
    1878             :  * This moves the modes from the @connector probed_modes list
    1879             :  * to the actual mode list. It compares the probed mode against the current
    1880             :  * list and only adds different/new modes.
    1881             :  *
    1882             :  * This is just a helper functions doesn't validate any modes itself and also
    1883             :  * doesn't prune any invalid modes. Callers need to do that themselves.
    1884             :  */
    1885           5 : void drm_connector_list_update(struct drm_connector *connector)
    1886             : {
    1887             :         struct drm_display_mode *pmode, *pt;
    1888             : 
    1889           5 :         WARN_ON(!mutex_is_locked(&connector->dev->mode_config.mutex));
    1890             : 
    1891         145 :         list_for_each_entry_safe(pmode, pt, &connector->probed_modes, head) {
    1892             :                 struct drm_display_mode *mode;
    1893         140 :                 bool found_it = false;
    1894             : 
    1895             :                 /* go through current modes checking for the new probed mode */
    1896        4060 :                 list_for_each_entry(mode, &connector->modes, head) {
    1897        1890 :                         if (!drm_mode_equal(pmode, mode))
    1898        1890 :                                 continue;
    1899             : 
    1900           0 :                         found_it = true;
    1901             : 
    1902             :                         /*
    1903             :                          * If the old matching mode is stale (ie. left over
    1904             :                          * from a previous probe) just replace it outright.
    1905             :                          * Otherwise just merge the type bits between all
    1906             :                          * equal probed modes.
    1907             :                          *
    1908             :                          * If two probed modes are considered equal, pick the
    1909             :                          * actual timings from the one that's marked as
    1910             :                          * preferred (in case the match isn't 100%). If
    1911             :                          * multiple or zero preferred modes are present, favor
    1912             :                          * the mode added to the probed_modes list first.
    1913             :                          */
    1914           0 :                         if (mode->status == MODE_STALE) {
    1915             :                                 drm_mode_copy(mode, pmode);
    1916           0 :                         } else if ((mode->type & DRM_MODE_TYPE_PREFERRED) == 0 &&
    1917           0 :                                    (pmode->type & DRM_MODE_TYPE_PREFERRED) != 0) {
    1918           0 :                                 pmode->type |= mode->type;
    1919             :                                 drm_mode_copy(mode, pmode);
    1920             :                         } else {
    1921           0 :                                 mode->type |= pmode->type;
    1922             :                         }
    1923             : 
    1924           0 :                         list_del(&pmode->head);
    1925           0 :                         drm_mode_destroy(connector->dev, pmode);
    1926             :                         break;
    1927             :                 }
    1928             : 
    1929         140 :                 if (!found_it) {
    1930         140 :                         list_move_tail(&pmode->head, &connector->modes);
    1931             :                 }
    1932             :         }
    1933           5 : }
    1934             : EXPORT_SYMBOL(drm_connector_list_update);
    1935             : 
    1936             : static int drm_mode_parse_cmdline_bpp(const char *str, char **end_ptr,
    1937             :                                       struct drm_cmdline_mode *mode)
    1938             : {
    1939             :         unsigned int bpp;
    1940             : 
    1941          13 :         if (str[0] != '-')
    1942             :                 return -EINVAL;
    1943             : 
    1944          13 :         str++;
    1945          13 :         bpp = simple_strtol(str, end_ptr, 10);
    1946          13 :         if (*end_ptr == str)
    1947             :                 return -EINVAL;
    1948             : 
    1949          13 :         mode->bpp = bpp;
    1950          13 :         mode->bpp_specified = true;
    1951             : 
    1952             :         return 0;
    1953             : }
    1954             : 
    1955             : static int drm_mode_parse_cmdline_refresh(const char *str, char **end_ptr,
    1956             :                                           struct drm_cmdline_mode *mode)
    1957             : {
    1958             :         unsigned int refresh;
    1959             : 
    1960          12 :         if (str[0] != '@')
    1961             :                 return -EINVAL;
    1962             : 
    1963          12 :         str++;
    1964          12 :         refresh = simple_strtol(str, end_ptr, 10);
    1965          12 :         if (*end_ptr == str)
    1966             :                 return -EINVAL;
    1967             : 
    1968          11 :         mode->refresh = refresh;
    1969          11 :         mode->refresh_specified = true;
    1970             : 
    1971             :         return 0;
    1972             : }
    1973             : 
    1974          36 : static int drm_mode_parse_cmdline_extra(const char *str, int length,
    1975             :                                         bool freestanding,
    1976             :                                         const struct drm_connector *connector,
    1977             :                                         struct drm_cmdline_mode *mode)
    1978             : {
    1979             :         int i;
    1980             : 
    1981          66 :         for (i = 0; i < length; i++) {
    1982          33 :                 switch (str[i]) {
    1983             :                 case 'i':
    1984          11 :                         if (freestanding)
    1985             :                                 return -EINVAL;
    1986             : 
    1987          11 :                         mode->interlace = true;
    1988          11 :                         break;
    1989             :                 case 'm':
    1990           4 :                         if (freestanding)
    1991             :                                 return -EINVAL;
    1992             : 
    1993           4 :                         mode->margins = true;
    1994           4 :                         break;
    1995             :                 case 'D':
    1996           5 :                         if (mode->force != DRM_FORCE_UNSPECIFIED)
    1997             :                                 return -EINVAL;
    1998             : 
    1999           5 :                         if ((connector->connector_type != DRM_MODE_CONNECTOR_DVII) &&
    2000             :                             (connector->connector_type != DRM_MODE_CONNECTOR_HDMIB))
    2001           2 :                                 mode->force = DRM_FORCE_ON;
    2002             :                         else
    2003           3 :                                 mode->force = DRM_FORCE_ON_DIGITAL;
    2004             :                         break;
    2005             :                 case 'd':
    2006           3 :                         if (mode->force != DRM_FORCE_UNSPECIFIED)
    2007             :                                 return -EINVAL;
    2008             : 
    2009           3 :                         mode->force = DRM_FORCE_OFF;
    2010           3 :                         break;
    2011             :                 case 'e':
    2012           8 :                         if (mode->force != DRM_FORCE_UNSPECIFIED)
    2013             :                                 return -EINVAL;
    2014             : 
    2015           7 :                         mode->force = DRM_FORCE_ON;
    2016           7 :                         break;
    2017             :                 default:
    2018             :                         return -EINVAL;
    2019             :                 }
    2020             :         }
    2021             : 
    2022             :         return 0;
    2023             : }
    2024             : 
    2025          48 : static int drm_mode_parse_cmdline_res_mode(const char *str, unsigned int length,
    2026             :                                            bool extras,
    2027             :                                            const struct drm_connector *connector,
    2028             :                                            struct drm_cmdline_mode *mode)
    2029             : {
    2030          48 :         const char *str_start = str;
    2031          48 :         bool rb = false, cvt = false;
    2032          48 :         int xres = 0, yres = 0;
    2033             :         int remaining, i;
    2034             :         char *end_ptr;
    2035             : 
    2036          48 :         xres = simple_strtol(str, &end_ptr, 10);
    2037          48 :         if (end_ptr == str)
    2038             :                 return -EINVAL;
    2039             : 
    2040          48 :         if (end_ptr[0] != 'x')
    2041             :                 return -EINVAL;
    2042          48 :         end_ptr++;
    2043             : 
    2044          48 :         str = end_ptr;
    2045          48 :         yres = simple_strtol(str, &end_ptr, 10);
    2046          48 :         if (end_ptr == str)
    2047             :                 return -EINVAL;
    2048             : 
    2049          46 :         remaining = length - (end_ptr - str_start);
    2050          46 :         if (remaining < 0)
    2051             :                 return -EINVAL;
    2052             : 
    2053          18 :         for (i = 0; i < remaining; i++) {
    2054          21 :                 switch (end_ptr[i]) {
    2055             :                 case 'M':
    2056             :                         cvt = true;
    2057             :                         break;
    2058             :                 case 'R':
    2059           2 :                         rb = true;
    2060           2 :                         break;
    2061             :                 default:
    2062             :                         /*
    2063             :                          * Try to pass that to our extras parsing
    2064             :                          * function to handle the case where the
    2065             :                          * extras are directly after the resolution
    2066             :                          */
    2067          16 :                         if (extras) {
    2068          15 :                                 int ret = drm_mode_parse_cmdline_extra(end_ptr + i,
    2069             :                                                                        1,
    2070             :                                                                        false,
    2071             :                                                                        connector,
    2072             :                                                                        mode);
    2073          15 :                                 if (ret)
    2074             :                                         return ret;
    2075             :                         } else {
    2076             :                                 return -EINVAL;
    2077             :                         }
    2078             :                 }
    2079             :         }
    2080             : 
    2081          42 :         mode->xres = xres;
    2082          42 :         mode->yres = yres;
    2083          42 :         mode->cvt = cvt;
    2084          42 :         mode->rb = rb;
    2085             : 
    2086          42 :         return 0;
    2087             : }
    2088             : 
    2089          25 : static int drm_mode_parse_cmdline_int(const char *delim, unsigned int *int_ret)
    2090             : {
    2091             :         const char *value;
    2092             :         char *endp;
    2093             : 
    2094             :         /*
    2095             :          * delim must point to the '=', otherwise it is a syntax error and
    2096             :          * if delim points to the terminating zero, then delim + 1 will point
    2097             :          * past the end of the string.
    2098             :          */
    2099          25 :         if (*delim != '=')
    2100             :                 return -EINVAL;
    2101             : 
    2102          25 :         value = delim + 1;
    2103          25 :         *int_ret = simple_strtol(value, &endp, 10);
    2104             : 
    2105             :         /* Make sure we have parsed something */
    2106          25 :         if (endp == value)
    2107             :                 return -EINVAL;
    2108             : 
    2109          24 :         return 0;
    2110             : }
    2111             : 
    2112           1 : static int drm_mode_parse_panel_orientation(const char *delim,
    2113             :                                             struct drm_cmdline_mode *mode)
    2114             : {
    2115             :         const char *value;
    2116             : 
    2117           1 :         if (*delim != '=')
    2118             :                 return -EINVAL;
    2119             : 
    2120           1 :         value = delim + 1;
    2121           1 :         delim = strchr(value, ',');
    2122           1 :         if (!delim)
    2123           1 :                 delim = value + strlen(value);
    2124             : 
    2125           1 :         if (!strncmp(value, "normal", delim - value))
    2126           0 :                 mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_NORMAL;
    2127           1 :         else if (!strncmp(value, "upside_down", delim - value))
    2128           1 :                 mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP;
    2129           0 :         else if (!strncmp(value, "left_side_up", delim - value))
    2130           0 :                 mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP;
    2131           0 :         else if (!strncmp(value, "right_side_up", delim - value))
    2132           0 :                 mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP;
    2133             :         else
    2134             :                 return -EINVAL;
    2135             : 
    2136             :         return 0;
    2137             : }
    2138             : 
    2139           9 : static int drm_mode_parse_tv_mode(const char *delim,
    2140             :                                   struct drm_cmdline_mode *mode)
    2141             : {
    2142             :         const char *value;
    2143             :         int ret;
    2144             : 
    2145           9 :         if (*delim != '=')
    2146             :                 return -EINVAL;
    2147             : 
    2148           9 :         value = delim + 1;
    2149           9 :         delim = strchr(value, ',');
    2150           9 :         if (!delim)
    2151           9 :                 delim = value + strlen(value);
    2152             : 
    2153           9 :         ret = drm_get_tv_mode_from_name(value, delim - value);
    2154           9 :         if (ret < 0)
    2155             :                 return ret;
    2156             : 
    2157           7 :         mode->tv_mode_specified = true;
    2158           7 :         mode->tv_mode = ret;
    2159             : 
    2160             :         return 0;
    2161             : }
    2162             : 
    2163          28 : static int drm_mode_parse_cmdline_options(const char *str,
    2164             :                                           bool freestanding,
    2165             :                                           const struct drm_connector *connector,
    2166             :                                           struct drm_cmdline_mode *mode)
    2167             : {
    2168          28 :         unsigned int deg, margin, rotation = 0;
    2169             :         const char *delim, *option, *sep;
    2170             : 
    2171          28 :         option = str;
    2172             :         do {
    2173          39 :                 delim = strchr(option, '=');
    2174          39 :                 if (!delim) {
    2175           3 :                         delim = strchr(option, ',');
    2176             : 
    2177           3 :                         if (!delim)
    2178           3 :                                 delim = option + strlen(option);
    2179             :                 }
    2180             : 
    2181          39 :                 if (!strncmp(option, "rotate", delim - option)) {
    2182          13 :                         if (drm_mode_parse_cmdline_int(delim, &deg))
    2183             :                                 return -EINVAL;
    2184             : 
    2185          12 :                         switch (deg) {
    2186             :                         case 0:
    2187           2 :                                 rotation |= DRM_MODE_ROTATE_0;
    2188           2 :                                 break;
    2189             : 
    2190             :                         case 90:
    2191           2 :                                 rotation |= DRM_MODE_ROTATE_90;
    2192           2 :                                 break;
    2193             : 
    2194             :                         case 180:
    2195           5 :                                 rotation |= DRM_MODE_ROTATE_180;
    2196           5 :                                 break;
    2197             : 
    2198             :                         case 270:
    2199           2 :                                 rotation |= DRM_MODE_ROTATE_270;
    2200           2 :                                 break;
    2201             : 
    2202             :                         default:
    2203             :                                 return -EINVAL;
    2204             :                         }
    2205          26 :                 } else if (!strncmp(option, "reflect_x", delim - option)) {
    2206           2 :                         rotation |= DRM_MODE_REFLECT_X;
    2207          24 :                 } else if (!strncmp(option, "reflect_y", delim - option)) {
    2208           1 :                         rotation |= DRM_MODE_REFLECT_Y;
    2209          23 :                 } else if (!strncmp(option, "margin_right", delim - option)) {
    2210           3 :                         if (drm_mode_parse_cmdline_int(delim, &margin))
    2211             :                                 return -EINVAL;
    2212             : 
    2213           3 :                         mode->tv_margins.right = margin;
    2214          20 :                 } else if (!strncmp(option, "margin_left", delim - option)) {
    2215           3 :                         if (drm_mode_parse_cmdline_int(delim, &margin))
    2216             :                                 return -EINVAL;
    2217             : 
    2218           3 :                         mode->tv_margins.left = margin;
    2219          17 :                 } else if (!strncmp(option, "margin_top", delim - option)) {
    2220           3 :                         if (drm_mode_parse_cmdline_int(delim, &margin))
    2221             :                                 return -EINVAL;
    2222             : 
    2223           3 :                         mode->tv_margins.top = margin;
    2224          14 :                 } else if (!strncmp(option, "margin_bottom", delim - option)) {
    2225           3 :                         if (drm_mode_parse_cmdline_int(delim, &margin))
    2226             :                                 return -EINVAL;
    2227             : 
    2228           3 :                         mode->tv_margins.bottom = margin;
    2229          11 :                 } else if (!strncmp(option, "panel_orientation", delim - option)) {
    2230           1 :                         if (drm_mode_parse_panel_orientation(delim, mode))
    2231             :                                 return -EINVAL;
    2232          10 :                 } else if (!strncmp(option, "tv_mode", delim - option)) {
    2233           9 :                         if (drm_mode_parse_tv_mode(delim, mode))
    2234             :                                 return -EINVAL;
    2235             :                 } else {
    2236             :                         return -EINVAL;
    2237             :                 }
    2238          34 :                 sep = strchr(delim, ',');
    2239          34 :                 option = sep + 1;
    2240          34 :         } while (sep);
    2241             : 
    2242          23 :         if (rotation && freestanding)
    2243             :                 return -EINVAL;
    2244             : 
    2245          23 :         if (!(rotation & DRM_MODE_ROTATE_MASK))
    2246          13 :                 rotation |= DRM_MODE_ROTATE_0;
    2247             : 
    2248             :         /* Make sure there is exactly one rotation defined */
    2249          46 :         if (!is_power_of_2(rotation & DRM_MODE_ROTATE_MASK))
    2250             :                 return -EINVAL;
    2251             : 
    2252          22 :         mode->rotation_reflection = rotation;
    2253             : 
    2254          22 :         return 0;
    2255             : }
    2256             : 
    2257             : struct drm_named_mode {
    2258             :         const char *name;
    2259             :         unsigned int pixel_clock_khz;
    2260             :         unsigned int xres;
    2261             :         unsigned int yres;
    2262             :         unsigned int flags;
    2263             :         unsigned int tv_mode;
    2264             : };
    2265             : 
    2266             : #define NAMED_MODE(_name, _pclk, _x, _y, _flags, _mode) \
    2267             :         {                                               \
    2268             :                 .name = _name,                          \
    2269             :                 .pixel_clock_khz = _pclk,               \
    2270             :                 .xres = _x,                             \
    2271             :                 .yres = _y,                             \
    2272             :                 .flags = _flags,                        \
    2273             :                 .tv_mode = _mode,                       \
    2274             :         }
    2275             : 
    2276             : static const struct drm_named_mode drm_named_modes[] = {
    2277             :         NAMED_MODE("NTSC", 13500, 720, 480, DRM_MODE_FLAG_INTERLACE, DRM_MODE_TV_MODE_NTSC),
    2278             :         NAMED_MODE("NTSC-J", 13500, 720, 480, DRM_MODE_FLAG_INTERLACE, DRM_MODE_TV_MODE_NTSC_J),
    2279             :         NAMED_MODE("PAL", 13500, 720, 576, DRM_MODE_FLAG_INTERLACE, DRM_MODE_TV_MODE_PAL),
    2280             :         NAMED_MODE("PAL-M", 13500, 720, 480, DRM_MODE_FLAG_INTERLACE, DRM_MODE_TV_MODE_PAL_M),
    2281             : };
    2282             : 
    2283          71 : static int drm_mode_parse_cmdline_named_mode(const char *name,
    2284             :                                              unsigned int name_end,
    2285             :                                              struct drm_cmdline_mode *cmdline_mode)
    2286             : {
    2287             :         unsigned int i;
    2288             : 
    2289          71 :         if (!name_end)
    2290             :                 return 0;
    2291             : 
    2292             :         /* If the name starts with a digit, it's not a named mode */
    2293         142 :         if (isdigit(name[0]))
    2294             :                 return 0;
    2295             : 
    2296             :         /*
    2297             :          * If there's an equal sign in the name, the command-line
    2298             :          * contains only an option and no mode.
    2299             :          */
    2300          23 :         if (strnchr(name, name_end, '='))
    2301             :                 return 0;
    2302             : 
    2303             :         /* The connection status extras can be set without a mode. */
    2304          29 :         if (name_end == 1 &&
    2305          12 :             (name[0] == 'd' || name[0] == 'D' || name[0] == 'e'))
    2306             :                 return 0;
    2307             : 
    2308             :         /*
    2309             :          * We're sure we're a named mode at this point, iterate over the
    2310             :          * list of modes we're aware of.
    2311             :          */
    2312          51 :         for (i = 0; i < ARRAY_SIZE(drm_named_modes); i++) {
    2313          30 :                 const struct drm_named_mode *mode = &drm_named_modes[i];
    2314             :                 int ret;
    2315             : 
    2316          60 :                 ret = str_has_prefix(name, mode->name);
    2317          30 :                 if (ret != name_end)
    2318          18 :                         continue;
    2319             : 
    2320          12 :                 strscpy(cmdline_mode->name, mode->name, sizeof(cmdline_mode->name));
    2321          12 :                 cmdline_mode->pixel_clock = mode->pixel_clock_khz;
    2322          12 :                 cmdline_mode->xres = mode->xres;
    2323          12 :                 cmdline_mode->yres = mode->yres;
    2324          12 :                 cmdline_mode->interlace = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
    2325          12 :                 cmdline_mode->tv_mode = mode->tv_mode;
    2326          12 :                 cmdline_mode->tv_mode_specified = true;
    2327          12 :                 cmdline_mode->specified = true;
    2328             : 
    2329          12 :                 return 1;
    2330             :         }
    2331             : 
    2332             :         return -EINVAL;
    2333             : }
    2334             : 
    2335             : /**
    2336             :  * drm_mode_parse_command_line_for_connector - parse command line modeline for connector
    2337             :  * @mode_option: optional per connector mode option
    2338             :  * @connector: connector to parse modeline for
    2339             :  * @mode: preallocated drm_cmdline_mode structure to fill out
    2340             :  *
    2341             :  * This parses @mode_option command line modeline for modes and options to
    2342             :  * configure the connector.
    2343             :  *
    2344             :  * This uses the same parameters as the fb modedb.c, except for an extra
    2345             :  * force-enable, force-enable-digital and force-disable bit at the end::
    2346             :  *
    2347             :  *      <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m][eDd]
    2348             :  *
    2349             :  * Additionals options can be provided following the mode, using a comma to
    2350             :  * separate each option. Valid options can be found in
    2351             :  * Documentation/fb/modedb.rst.
    2352             :  *
    2353             :  * The intermediate drm_cmdline_mode structure is required to store additional
    2354             :  * options from the command line modline like the force-enable/disable flag.
    2355             :  *
    2356             :  * Returns:
    2357             :  * True if a valid modeline has been parsed, false otherwise.
    2358             :  */
    2359          71 : bool drm_mode_parse_command_line_for_connector(const char *mode_option,
    2360             :                                                const struct drm_connector *connector,
    2361             :                                                struct drm_cmdline_mode *mode)
    2362             : {
    2363             :         const char *name;
    2364          71 :         bool freestanding = false, parse_extras = false;
    2365          71 :         unsigned int bpp_off = 0, refresh_off = 0, options_off = 0;
    2366          71 :         unsigned int mode_end = 0;
    2367          71 :         const char *bpp_ptr = NULL, *refresh_ptr = NULL, *extra_ptr = NULL;
    2368          71 :         const char *options_ptr = NULL;
    2369          71 :         char *bpp_end_ptr = NULL, *refresh_end_ptr = NULL;
    2370             :         int len, ret;
    2371             : 
    2372          71 :         memset(mode, 0, sizeof(*mode));
    2373          71 :         mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
    2374             : 
    2375          71 :         if (!mode_option)
    2376             :                 return false;
    2377             : 
    2378          71 :         name = mode_option;
    2379             : 
    2380             :         /* Locate the start of named options */
    2381          71 :         options_ptr = strchr(name, ',');
    2382          71 :         if (options_ptr)
    2383          27 :                 options_off = options_ptr - name;
    2384             :         else
    2385          44 :                 options_off = strlen(name);
    2386             : 
    2387             :         /* Try to locate the bpp and refresh specifiers, if any */
    2388          71 :         bpp_ptr = strnchr(name, options_off, '-');
    2389         164 :         while (bpp_ptr && !isdigit(bpp_ptr[1]))
    2390           3 :                 bpp_ptr = strnchr(bpp_ptr + 1, options_off, '-');
    2391          71 :         if (bpp_ptr)
    2392          16 :                 bpp_off = bpp_ptr - name;
    2393             : 
    2394          71 :         refresh_ptr = strnchr(name, options_off, '@');
    2395          71 :         if (refresh_ptr)
    2396          16 :                 refresh_off = refresh_ptr - name;
    2397             : 
    2398             :         /* Locate the end of the name / resolution, and parse it */
    2399          71 :         if (bpp_ptr) {
    2400             :                 mode_end = bpp_off;
    2401          55 :         } else if (refresh_ptr) {
    2402             :                 mode_end = refresh_off;
    2403          49 :         } else if (options_ptr) {
    2404             :                 mode_end = options_off;
    2405             :                 parse_extras = true;
    2406             :         } else {
    2407          24 :                 mode_end = strlen(name);
    2408          24 :                 parse_extras = true;
    2409             :         }
    2410             : 
    2411          71 :         if (!mode_end)
    2412             :                 return false;
    2413             : 
    2414          71 :         ret = drm_mode_parse_cmdline_named_mode(name, mode_end, mode);
    2415          71 :         if (ret < 0)
    2416             :                 return false;
    2417             : 
    2418             :         /*
    2419             :          * Having a mode that starts by a letter (and thus is named) and
    2420             :          * an at-sign (used to specify a refresh rate) is disallowed.
    2421             :          */
    2422          68 :         if (ret && refresh_ptr)
    2423             :                 return false;
    2424             : 
    2425             :         /* No named mode? Check for a normal mode argument, e.g. 1024x768 */
    2426         120 :         if (!mode->specified && isdigit(name[0])) {
    2427          48 :                 ret = drm_mode_parse_cmdline_res_mode(name, mode_end,
    2428             :                                                       parse_extras,
    2429             :                                                       connector,
    2430             :                                                       mode);
    2431          48 :                 if (ret)
    2432             :                         return false;
    2433             : 
    2434          42 :                 mode->specified = true;
    2435             :         }
    2436             : 
    2437             :         /* No mode? Check for freestanding extras and/or options */
    2438          58 :         if (!mode->specified) {
    2439           8 :                 unsigned int len = strlen(mode_option);
    2440             : 
    2441           8 :                 if (bpp_ptr || refresh_ptr)
    2442             :                         return false; /* syntax error */
    2443             : 
    2444           8 :                 if (len == 1 || (len >= 2 && mode_option[1] == ','))
    2445             :                         extra_ptr = mode_option;
    2446             :                 else
    2447           2 :                         options_ptr = mode_option - 1;
    2448             : 
    2449             :                 freestanding = true;
    2450             :         }
    2451             : 
    2452          58 :         if (bpp_ptr) {
    2453          26 :                 ret = drm_mode_parse_cmdline_bpp(bpp_ptr, &bpp_end_ptr, mode);
    2454          13 :                 if (ret)
    2455             :                         return false;
    2456             : 
    2457          13 :                 mode->bpp_specified = true;
    2458             :         }
    2459             : 
    2460          58 :         if (refresh_ptr) {
    2461          24 :                 ret = drm_mode_parse_cmdline_refresh(refresh_ptr,
    2462             :                                                      &refresh_end_ptr, mode);
    2463          12 :                 if (ret)
    2464             :                         return false;
    2465             : 
    2466          11 :                 mode->refresh_specified = true;
    2467             :         }
    2468             : 
    2469             :         /*
    2470             :          * Locate the end of the bpp / refresh, and parse the extras
    2471             :          * if relevant
    2472             :          */
    2473          57 :         if (bpp_ptr && refresh_ptr)
    2474           9 :                 extra_ptr = max(bpp_end_ptr, refresh_end_ptr);
    2475          48 :         else if (bpp_ptr)
    2476           4 :                 extra_ptr = bpp_end_ptr;
    2477          44 :         else if (refresh_ptr)
    2478           2 :                 extra_ptr = refresh_end_ptr;
    2479             : 
    2480          57 :         if (extra_ptr) {
    2481          21 :                 if (options_ptr)
    2482           3 :                         len = options_ptr - extra_ptr;
    2483             :                 else
    2484          18 :                         len = strlen(extra_ptr);
    2485             : 
    2486          21 :                 ret = drm_mode_parse_cmdline_extra(extra_ptr, len, freestanding,
    2487             :                                                    connector, mode);
    2488          21 :                 if (ret)
    2489             :                         return false;
    2490             :         }
    2491             : 
    2492          56 :         if (options_ptr) {
    2493          28 :                 ret = drm_mode_parse_cmdline_options(options_ptr + 1,
    2494             :                                                      freestanding,
    2495             :                                                      connector, mode);
    2496          28 :                 if (ret)
    2497             :                         return false;
    2498             :         }
    2499             : 
    2500             :         return true;
    2501             : }
    2502             : EXPORT_SYMBOL(drm_mode_parse_command_line_for_connector);
    2503             : 
    2504           0 : static struct drm_display_mode *drm_named_mode(struct drm_device *dev,
    2505             :                                                struct drm_cmdline_mode *cmd)
    2506             : {
    2507             :         unsigned int i;
    2508             : 
    2509           0 :         for (i = 0; i < ARRAY_SIZE(drm_named_modes); i++) {
    2510           0 :                 const struct drm_named_mode *named_mode = &drm_named_modes[i];
    2511             : 
    2512           0 :                 if (strcmp(cmd->name, named_mode->name))
    2513           0 :                         continue;
    2514             : 
    2515           0 :                 if (!cmd->tv_mode_specified)
    2516           0 :                         continue;
    2517             : 
    2518           0 :                 return drm_analog_tv_mode(dev,
    2519           0 :                                           named_mode->tv_mode,
    2520           0 :                                           named_mode->pixel_clock_khz * 1000,
    2521             :                                           named_mode->xres,
    2522             :                                           named_mode->yres,
    2523           0 :                                           named_mode->flags & DRM_MODE_FLAG_INTERLACE);
    2524             :         }
    2525             : 
    2526             :         return NULL;
    2527             : }
    2528             : 
    2529             : /**
    2530             :  * drm_mode_create_from_cmdline_mode - convert a command line modeline into a DRM display mode
    2531             :  * @dev: DRM device to create the new mode for
    2532             :  * @cmd: input command line modeline
    2533             :  *
    2534             :  * Returns:
    2535             :  * Pointer to converted mode on success, NULL on error.
    2536             :  */
    2537             : struct drm_display_mode *
    2538           0 : drm_mode_create_from_cmdline_mode(struct drm_device *dev,
    2539             :                                   struct drm_cmdline_mode *cmd)
    2540             : {
    2541             :         struct drm_display_mode *mode;
    2542             : 
    2543           0 :         if (cmd->xres == 0 || cmd->yres == 0)
    2544             :                 return NULL;
    2545             : 
    2546           0 :         if (strlen(cmd->name))
    2547           0 :                 mode = drm_named_mode(dev, cmd);
    2548           0 :         else if (cmd->cvt)
    2549           0 :                 mode = drm_cvt_mode(dev,
    2550             :                                     cmd->xres, cmd->yres,
    2551           0 :                                     cmd->refresh_specified ? cmd->refresh : 60,
    2552           0 :                                     cmd->rb, cmd->interlace,
    2553           0 :                                     cmd->margins);
    2554             :         else
    2555           0 :                 mode = drm_gtf_mode(dev,
    2556             :                                     cmd->xres, cmd->yres,
    2557           0 :                                     cmd->refresh_specified ? cmd->refresh : 60,
    2558           0 :                                     cmd->interlace,
    2559           0 :                                     cmd->margins);
    2560           0 :         if (!mode)
    2561             :                 return NULL;
    2562             : 
    2563           0 :         mode->type |= DRM_MODE_TYPE_USERDEF;
    2564             :         /* fix up 1368x768: GFT/CVT can't express 1366 width due to alignment */
    2565           0 :         if (cmd->xres == 1366)
    2566           0 :                 drm_mode_fixup_1366x768(mode);
    2567           0 :         drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
    2568           0 :         return mode;
    2569             : }
    2570             : EXPORT_SYMBOL(drm_mode_create_from_cmdline_mode);
    2571             : 
    2572             : /**
    2573             :  * drm_mode_convert_to_umode - convert a drm_display_mode into a modeinfo
    2574             :  * @out: drm_mode_modeinfo struct to return to the user
    2575             :  * @in: drm_display_mode to use
    2576             :  *
    2577             :  * Convert a drm_display_mode into a drm_mode_modeinfo structure to return to
    2578             :  * the user.
    2579             :  */
    2580           0 : void drm_mode_convert_to_umode(struct drm_mode_modeinfo *out,
    2581             :                                const struct drm_display_mode *in)
    2582             : {
    2583           0 :         out->clock = in->clock;
    2584           0 :         out->hdisplay = in->hdisplay;
    2585           0 :         out->hsync_start = in->hsync_start;
    2586           0 :         out->hsync_end = in->hsync_end;
    2587           0 :         out->htotal = in->htotal;
    2588           0 :         out->hskew = in->hskew;
    2589           0 :         out->vdisplay = in->vdisplay;
    2590           0 :         out->vsync_start = in->vsync_start;
    2591           0 :         out->vsync_end = in->vsync_end;
    2592           0 :         out->vtotal = in->vtotal;
    2593           0 :         out->vscan = in->vscan;
    2594           0 :         out->vrefresh = drm_mode_vrefresh(in);
    2595           0 :         out->flags = in->flags;
    2596           0 :         out->type = in->type;
    2597             : 
    2598           0 :         switch (in->picture_aspect_ratio) {
    2599             :         case HDMI_PICTURE_ASPECT_4_3:
    2600           0 :                 out->flags |= DRM_MODE_FLAG_PIC_AR_4_3;
    2601           0 :                 break;
    2602             :         case HDMI_PICTURE_ASPECT_16_9:
    2603           0 :                 out->flags |= DRM_MODE_FLAG_PIC_AR_16_9;
    2604           0 :                 break;
    2605             :         case HDMI_PICTURE_ASPECT_64_27:
    2606           0 :                 out->flags |= DRM_MODE_FLAG_PIC_AR_64_27;
    2607           0 :                 break;
    2608             :         case HDMI_PICTURE_ASPECT_256_135:
    2609           0 :                 out->flags |= DRM_MODE_FLAG_PIC_AR_256_135;
    2610           0 :                 break;
    2611             :         default:
    2612           0 :                 WARN(1, "Invalid aspect ratio (0%x) on mode\n",
    2613             :                      in->picture_aspect_ratio);
    2614             :                 fallthrough;
    2615             :         case HDMI_PICTURE_ASPECT_NONE:
    2616             :                 out->flags |= DRM_MODE_FLAG_PIC_AR_NONE;
    2617           0 :                 break;
    2618             :         }
    2619             : 
    2620           0 :         strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN);
    2621           0 :         out->name[DRM_DISPLAY_MODE_LEN-1] = 0;
    2622           0 : }
    2623             : 
    2624             : /**
    2625             :  * drm_mode_convert_umode - convert a modeinfo into a drm_display_mode
    2626             :  * @dev: drm device
    2627             :  * @out: drm_display_mode to return to the user
    2628             :  * @in: drm_mode_modeinfo to use
    2629             :  *
    2630             :  * Convert a drm_mode_modeinfo into a drm_display_mode structure to return to
    2631             :  * the caller.
    2632             :  *
    2633             :  * Returns:
    2634             :  * Zero on success, negative errno on failure.
    2635             :  */
    2636           0 : int drm_mode_convert_umode(struct drm_device *dev,
    2637             :                            struct drm_display_mode *out,
    2638             :                            const struct drm_mode_modeinfo *in)
    2639             : {
    2640           0 :         if (in->clock > INT_MAX || in->vrefresh > INT_MAX)
    2641             :                 return -ERANGE;
    2642             : 
    2643           0 :         out->clock = in->clock;
    2644           0 :         out->hdisplay = in->hdisplay;
    2645           0 :         out->hsync_start = in->hsync_start;
    2646           0 :         out->hsync_end = in->hsync_end;
    2647           0 :         out->htotal = in->htotal;
    2648           0 :         out->hskew = in->hskew;
    2649           0 :         out->vdisplay = in->vdisplay;
    2650           0 :         out->vsync_start = in->vsync_start;
    2651           0 :         out->vsync_end = in->vsync_end;
    2652           0 :         out->vtotal = in->vtotal;
    2653           0 :         out->vscan = in->vscan;
    2654           0 :         out->flags = in->flags;
    2655             :         /*
    2656             :          * Old xf86-video-vmware (possibly others too) used to
    2657             :          * leave 'type' uninitialized. Just ignore any bits we
    2658             :          * don't like. It's a just hint after all, and more
    2659             :          * useful for the kernel->userspace direction anyway.
    2660             :          */
    2661           0 :         out->type = in->type & DRM_MODE_TYPE_ALL;
    2662           0 :         strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN);
    2663           0 :         out->name[DRM_DISPLAY_MODE_LEN-1] = 0;
    2664             : 
    2665             :         /* Clearing picture aspect ratio bits from out flags,
    2666             :          * as the aspect-ratio information is not stored in
    2667             :          * flags for kernel-mode, but in picture_aspect_ratio.
    2668             :          */
    2669           0 :         out->flags &= ~DRM_MODE_FLAG_PIC_AR_MASK;
    2670             : 
    2671           0 :         switch (in->flags & DRM_MODE_FLAG_PIC_AR_MASK) {
    2672             :         case DRM_MODE_FLAG_PIC_AR_4_3:
    2673           0 :                 out->picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3;
    2674           0 :                 break;
    2675             :         case DRM_MODE_FLAG_PIC_AR_16_9:
    2676           0 :                 out->picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9;
    2677           0 :                 break;
    2678             :         case DRM_MODE_FLAG_PIC_AR_64_27:
    2679           0 :                 out->picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27;
    2680           0 :                 break;
    2681             :         case DRM_MODE_FLAG_PIC_AR_256_135:
    2682           0 :                 out->picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135;
    2683           0 :                 break;
    2684             :         case DRM_MODE_FLAG_PIC_AR_NONE:
    2685           0 :                 out->picture_aspect_ratio = HDMI_PICTURE_ASPECT_NONE;
    2686           0 :                 break;
    2687             :         default:
    2688             :                 return -EINVAL;
    2689             :         }
    2690             : 
    2691           0 :         out->status = drm_mode_validate_driver(dev, out);
    2692           0 :         if (out->status != MODE_OK)
    2693             :                 return -EINVAL;
    2694             : 
    2695           0 :         drm_mode_set_crtcinfo(out, CRTC_INTERLACE_HALVE_V);
    2696             : 
    2697           0 :         return 0;
    2698             : }
    2699             : 
    2700             : /**
    2701             :  * drm_mode_is_420_only - if a given videomode can be only supported in YCBCR420
    2702             :  * output format
    2703             :  *
    2704             :  * @display: display under action
    2705             :  * @mode: video mode to be tested.
    2706             :  *
    2707             :  * Returns:
    2708             :  * true if the mode can be supported in YCBCR420 format
    2709             :  * false if not.
    2710             :  */
    2711         125 : bool drm_mode_is_420_only(const struct drm_display_info *display,
    2712             :                           const struct drm_display_mode *mode)
    2713             : {
    2714         125 :         u8 vic = drm_match_cea_mode(mode);
    2715             : 
    2716         250 :         return test_bit(vic, display->hdmi.y420_vdb_modes);
    2717             : }
    2718             : EXPORT_SYMBOL(drm_mode_is_420_only);
    2719             : 
    2720             : /**
    2721             :  * drm_mode_is_420_also - if a given videomode can be supported in YCBCR420
    2722             :  * output format also (along with RGB/YCBCR444/422)
    2723             :  *
    2724             :  * @display: display under action.
    2725             :  * @mode: video mode to be tested.
    2726             :  *
    2727             :  * Returns:
    2728             :  * true if the mode can be support YCBCR420 format
    2729             :  * false if not.
    2730             :  */
    2731           0 : bool drm_mode_is_420_also(const struct drm_display_info *display,
    2732             :                           const struct drm_display_mode *mode)
    2733             : {
    2734           0 :         u8 vic = drm_match_cea_mode(mode);
    2735             : 
    2736           0 :         return test_bit(vic, display->hdmi.y420_cmdb_modes);
    2737             : }
    2738             : EXPORT_SYMBOL(drm_mode_is_420_also);
    2739             : /**
    2740             :  * drm_mode_is_420 - if a given videomode can be supported in YCBCR420
    2741             :  * output format
    2742             :  *
    2743             :  * @display: display under action.
    2744             :  * @mode: video mode to be tested.
    2745             :  *
    2746             :  * Returns:
    2747             :  * true if the mode can be supported in YCBCR420 format
    2748             :  * false if not.
    2749             :  */
    2750           0 : bool drm_mode_is_420(const struct drm_display_info *display,
    2751             :                      const struct drm_display_mode *mode)
    2752             : {
    2753           0 :         return drm_mode_is_420_only(display, mode) ||
    2754           0 :                 drm_mode_is_420_also(display, mode);
    2755             : }
    2756             : EXPORT_SYMBOL(drm_mode_is_420);

Generated by: LCOV version 1.14