cachepc-linux

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

drm_modes.c (62128B)


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