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
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:
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
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.
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).
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>
40 #include <video/of_display_timing.h>
41 #include <video/of_videomode.h>
42 #include <video/videomode.h>
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>
50 #include "drm_crtc_internal.h"
53 * drm_mode_debug_printmodeline - print a mode to dmesg
54 * @mode: mode to print
56 * Describe @mode using DRM_DEBUG.
58 void drm_mode_debug_printmodeline(const struct drm_display_mode
*mode
)
60 DRM_DEBUG_KMS("Modeline " DRM_MODE_FMT
"\n", DRM_MODE_ARG(mode
));
62 EXPORT_SYMBOL(drm_mode_debug_printmodeline
);
65 * drm_mode_create - create a new display mode
68 * Create a new, cleared drm_display_mode with kzalloc, allocate an ID for it
72 * Pointer to new mode on success, NULL on error.
74 struct drm_display_mode
*drm_mode_create(struct drm_device
*dev
)
76 struct drm_display_mode
*nmode
;
78 nmode
= kzalloc(sizeof(struct drm_display_mode
), GFP_KERNEL
);
84 EXPORT_SYMBOL(drm_mode_create
);
87 * drm_mode_destroy - remove a mode
89 * @mode: mode to remove
91 * Release @mode's unique ID, then free it @mode structure itself using kfree.
93 void drm_mode_destroy(struct drm_device
*dev
, struct drm_display_mode
*mode
)
100 EXPORT_SYMBOL(drm_mode_destroy
);
103 * drm_mode_probed_add - add a mode to a connector's probed_mode list
104 * @connector: connector the new mode
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.
111 void drm_mode_probed_add(struct drm_connector
*connector
,
112 struct drm_display_mode
*mode
)
114 WARN_ON(!mutex_is_locked(&connector
->dev
->mode_config
.mutex
));
116 list_add_tail(&mode
->head
, &connector
->probed_modes
);
118 EXPORT_SYMBOL(drm_mode_probed_add
);
120 enum drm_mode_analog
{
121 DRM_MODE_ANALOG_NTSC
, /* 525 lines, 60Hz */
122 DRM_MODE_ANALOG_PAL
, /* 625 lines, 50Hz */
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
131 #define NTSC_LINE_DURATION_NS 63556U
132 #define NTSC_LINES_NUMBER 525
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)
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)
142 #define NTSC_HFP_DURATION_TYP_NS 1500
143 #define NTSC_HFP_DURATION_MIN_NS 1270
144 #define NTSC_HFP_DURATION_MAX_NS 2220
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)
150 #define NTSC_HBP_DURATION_TYP_NS 4700
153 * I couldn't find the actual tolerance for the back porch, so let's
154 * just reuse the sync length ones.
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)
159 #define PAL_LINE_DURATION_NS 64000U
160 #define PAL_LINES_NUMBER 625
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)
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)
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)
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)
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)
182 struct analog_param_field
{
183 unsigned int even
, odd
;
186 #define PARAM_FIELD(_odd, _even) \
187 { .even = _even, .odd = _odd }
189 struct analog_param_range
{
190 unsigned int min
, typ
, max
;
193 #define PARAM_RANGE(_min, _typ, _max) \
194 { .min = _min, .typ = _typ, .max = _max }
196 struct analog_parameters
{
197 unsigned int num_lines
;
198 unsigned int line_duration_ns
;
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
;
206 unsigned int bt601_hfp
;
208 struct analog_param_field vfp_lines
;
209 struct analog_param_field vslen_lines
;
210 struct analog_param_field vbp_lines
;
213 #define TV_MODE_PARAMETER(_mode, _lines, _line_dur, _hact, _hfp, \
214 _hslen, _hbp, _hblk, _bt601_hfp, _vfp, \
217 .num_lines = _lines, \
218 .line_duration_ns = _line_dur, \
221 .hslen_ns = _hslen, \
224 .bt601_hfp = _bt601_hfp, \
226 .vslen_lines = _vslen, \
230 static const struct analog_parameters tv_modes_parameters
[] = {
231 TV_MODE_PARAMETER(DRM_MODE_ANALOG_NTSC
,
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
),
252 PARAM_FIELD(16, 17)),
253 TV_MODE_PARAMETER(DRM_MODE_ANALOG_PAL
,
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
),
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
280 * In progressive, we're supposed to use 6
281 * pulses, so we're fine there
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.
290 * In progressive, we're supposed to use 5
291 * pulses, so we're off by half
294 * In interlace, we're now off by half a line
295 * for the even field and one line for the odd
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.
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.
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.
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
322 PARAM_FIELD(19, 20)),
325 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
,
333 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
;
349 "Generating a %ux%u%c, %u-line mode with a %lu kHz clock\n",
351 interlace
? 'i' : 'p',
353 pixel_clock_hz
/ 1000);
355 max_hact
= params
->hact_ns
.max
/ pixel_duration_ns
;
356 if (pixel_clock_hz
== 13500000 && hactive
> max_hact
&& hactive
<= 720) {
357 drm_dbg_kms(dev
, "Trying to generate a BT.601 mode. Disabling checks.\n");
362 * Our pixel duration is going to be round down by the division,
363 * so rounding up is probably going to introduce even more
366 result
= (u64
)params
->line_duration_ns
* pixel_clock_hz
;
367 do_div(result
, NSEC_PER_SEC
);
370 drm_dbg_kms(dev
, "Total Horizontal Number of Pixels: %u\n", htotal
);
372 hact_duration_ns
= hactive
* pixel_duration_ns
;
374 (hact_duration_ns
< params
->hact_ns
.min
||
375 hact_duration_ns
> params
->hact_ns
.max
)) {
376 drm_err(dev
, "Invalid horizontal active area duration: %uns (min: %u, max %u)\n",
377 hact_duration_ns
, params
->hact_ns
.min
, params
->hact_ns
.max
);
381 hblk
= htotal
- hactive
;
382 drm_dbg_kms(dev
, "Horizontal Blanking Period: %u\n", hblk
);
384 hblk_duration_ns
= hblk
* pixel_duration_ns
;
386 (hblk_duration_ns
< params
->hblk_ns
.min
||
387 hblk_duration_ns
> params
->hblk_ns
.max
)) {
388 drm_err(dev
, "Invalid horizontal blanking duration: %uns (min: %u, max %u)\n",
389 hblk_duration_ns
, params
->hblk_ns
.min
, params
->hblk_ns
.max
);
393 hslen
= DIV_ROUND_UP(params
->hslen_ns
.typ
, pixel_duration_ns
);
394 drm_dbg_kms(dev
, "Horizontal Sync Period: %u\n", hslen
);
396 hslen_duration_ns
= hslen
* pixel_duration_ns
;
398 (hslen_duration_ns
< params
->hslen_ns
.min
||
399 hslen_duration_ns
> params
->hslen_ns
.max
)) {
400 drm_err(dev
, "Invalid horizontal sync duration: %uns (min: %u, max %u)\n",
401 hslen_duration_ns
, params
->hslen_ns
.min
, params
->hslen_ns
.max
);
405 porches
= hblk
- hslen
;
406 drm_dbg_kms(dev
, "Remaining horizontal pixels for both porches: %u\n", porches
);
408 porches_duration_ns
= porches
* pixel_duration_ns
;
410 (porches_duration_ns
> (params
->hfp_ns
.max
+ params
->hbp_ns
.max
) ||
411 porches_duration_ns
< (params
->hfp_ns
.min
+ params
->hbp_ns
.min
))) {
412 drm_err(dev
, "Invalid horizontal porches duration: %uns\n",
413 porches_duration_ns
);
418 hfp
= params
->bt601_hfp
;
420 unsigned int hfp_min
= DIV_ROUND_UP(params
->hfp_ns
.min
,
422 unsigned int hbp_min
= DIV_ROUND_UP(params
->hbp_ns
.min
,
424 int porches_rem
= porches
- hfp_min
- hbp_min
;
426 hfp
= hfp_min
+ DIV_ROUND_UP(porches_rem
, 2);
429 drm_dbg_kms(dev
, "Horizontal Front Porch: %u\n", hfp
);
431 hfp_duration_ns
= hfp
* pixel_duration_ns
;
433 (hfp_duration_ns
< params
->hfp_ns
.min
||
434 hfp_duration_ns
> params
->hfp_ns
.max
)) {
435 drm_err(dev
, "Invalid horizontal front porch duration: %uns (min: %u, max %u)\n",
436 hfp_duration_ns
, params
->hfp_ns
.min
, params
->hfp_ns
.max
);
441 drm_dbg_kms(dev
, "Horizontal Back Porch: %u\n", hbp
);
443 hbp_duration_ns
= hbp
* pixel_duration_ns
;
445 (hbp_duration_ns
< params
->hbp_ns
.min
||
446 hbp_duration_ns
> params
->hbp_ns
.max
)) {
447 drm_err(dev
, "Invalid horizontal back porch duration: %uns (min: %u, max %u)\n",
448 hbp_duration_ns
, params
->hbp_ns
.min
, params
->hbp_ns
.max
);
452 if (htotal
!= (hactive
+ hfp
+ hslen
+ hbp
))
455 mode
->clock
= pixel_clock_hz
/ 1000;
456 mode
->hdisplay
= hactive
;
457 mode
->hsync_start
= mode
->hdisplay
+ hfp
;
458 mode
->hsync_end
= mode
->hsync_start
+ hslen
;
459 mode
->htotal
= mode
->hsync_end
+ hbp
;
462 vfp_min
= params
->vfp_lines
.even
+ params
->vfp_lines
.odd
;
463 vbp_min
= params
->vbp_lines
.even
+ params
->vbp_lines
.odd
;
464 vslen
= params
->vslen_lines
.even
+ params
->vslen_lines
.odd
;
467 * By convention, NTSC (aka 525/60) systems start with
468 * the even field, but PAL (aka 625/50) systems start
471 * PAL systems also have asymmetric timings between the
472 * even and odd field, while NTSC is symmetric.
474 * Moreover, if we want to create a progressive mode for
475 * PAL, we need to use the odd field timings.
477 * Since odd == even for NTSC, we can just use the odd
478 * one all the time to simplify the code a bit.
480 vfp_min
= params
->vfp_lines
.odd
;
481 vbp_min
= params
->vbp_lines
.odd
;
482 vslen
= params
->vslen_lines
.odd
;
485 drm_dbg_kms(dev
, "Vertical Sync Period: %u\n", vslen
);
487 porches
= params
->num_lines
- vactive
- vslen
;
488 drm_dbg_kms(dev
, "Remaining vertical pixels for both porches: %u\n", porches
);
490 porches_rem
= porches
- vfp_min
- vbp_min
;
491 vfp
= vfp_min
+ (porches_rem
/ 2);
492 drm_dbg_kms(dev
, "Vertical Front Porch: %u\n", vfp
);
495 drm_dbg_kms(dev
, "Vertical Back Porch: %u\n", vbp
);
497 vtotal
= vactive
+ vfp
+ vslen
+ vbp
;
498 if (params
->num_lines
!= vtotal
) {
499 drm_err(dev
, "Invalid vertical total: %upx (expected %upx)\n",
500 vtotal
, params
->num_lines
);
504 mode
->vdisplay
= vactive
;
505 mode
->vsync_start
= mode
->vdisplay
+ vfp
;
506 mode
->vsync_end
= mode
->vsync_start
+ vslen
;
507 mode
->vtotal
= mode
->vsync_end
+ vbp
;
509 if (mode
->vtotal
!= params
->num_lines
)
512 mode
->type
= DRM_MODE_TYPE_DRIVER
;
513 mode
->flags
= DRM_MODE_FLAG_NVSYNC
| DRM_MODE_FLAG_NHSYNC
;
515 mode
->flags
|= DRM_MODE_FLAG_INTERLACE
;
517 drm_mode_set_name(mode
);
519 drm_dbg_kms(dev
, "Generated mode " DRM_MODE_FMT
"\n", DRM_MODE_ARG(mode
));
525 * drm_analog_tv_mode - create a display mode for an analog TV
527 * @tv_mode: TV Mode standard to create a mode for. See DRM_MODE_TV_MODE_*.
528 * @pixel_clock_hz: Pixel Clock Frequency, in Hertz
529 * @hdisplay: hdisplay size
530 * @vdisplay: vdisplay size
531 * @interlace: whether to compute an interlaced mode
533 * This function creates a struct drm_display_mode instance suited for
534 * an analog TV output, for one of the usual analog TV modes. Where
535 * this is DRM_MODE_TV_MODE_MONOCHROME, a 625-line mode will be created.
537 * Note that @hdisplay is larger than the usual constraints for the PAL
538 * and NTSC timings, and we'll choose to ignore most timings constraints
539 * to reach those resolutions.
542 * A pointer to the mode, allocated with drm_mode_create(). Returns NULL
545 struct drm_display_mode
*drm_analog_tv_mode(struct drm_device
*dev
,
546 enum drm_connector_tv_mode tv_mode
,
547 unsigned long pixel_clock_hz
,
548 unsigned int hdisplay
,
549 unsigned int vdisplay
,
552 struct drm_display_mode
*mode
;
553 enum drm_mode_analog analog
;
557 case DRM_MODE_TV_MODE_NTSC
:
559 case DRM_MODE_TV_MODE_NTSC_443
:
561 case DRM_MODE_TV_MODE_NTSC_J
:
563 case DRM_MODE_TV_MODE_PAL_M
:
564 analog
= DRM_MODE_ANALOG_NTSC
;
567 case DRM_MODE_TV_MODE_PAL
:
569 case DRM_MODE_TV_MODE_PAL_N
:
571 case DRM_MODE_TV_MODE_SECAM
:
573 case DRM_MODE_TV_MODE_MONOCHROME
:
574 analog
= DRM_MODE_ANALOG_PAL
;
581 mode
= drm_mode_create(dev
);
585 ret
= fill_analog_mode(dev
, mode
,
586 &tv_modes_parameters
[analog
],
587 pixel_clock_hz
, hdisplay
, vdisplay
, interlace
);
594 drm_mode_destroy(dev
, mode
);
597 EXPORT_SYMBOL(drm_analog_tv_mode
);
600 * drm_cvt_mode -create a modeline based on the CVT algorithm
602 * @hdisplay: hdisplay size
603 * @vdisplay: vdisplay size
604 * @vrefresh: vrefresh rate
605 * @reduced: whether to use reduced blanking
606 * @interlaced: whether to compute an interlaced mode
607 * @margins: whether to add margins (borders)
609 * This function is called to generate the modeline based on CVT algorithm
610 * according to the hdisplay, vdisplay, vrefresh.
611 * It is based from the VESA(TM) Coordinated Video Timing Generator by
612 * Graham Loveridge April 9, 2003 available at
613 * http://www.elo.utfsm.cl/~elo212/docs/CVTd6r1.xls
615 * And it is copied from xf86CVTmode in xserver/hw/xfree86/modes/xf86cvt.c.
616 * What I have done is to translate it by using integer calculation.
619 * The modeline based on the CVT algorithm stored in a drm_display_mode object.
620 * The display mode object is allocated with drm_mode_create(). Returns NULL
621 * when no mode could be allocated.
623 struct drm_display_mode
*drm_cvt_mode(struct drm_device
*dev
, int hdisplay
,
624 int vdisplay
, int vrefresh
,
625 bool reduced
, bool interlaced
, bool margins
)
627 #define HV_FACTOR 1000
628 /* 1) top/bottom margin size (% of height) - default: 1.8, */
629 #define CVT_MARGIN_PERCENTAGE 18
630 /* 2) character cell horizontal granularity (pixels) - default 8 */
631 #define CVT_H_GRANULARITY 8
632 /* 3) Minimum vertical porch (lines) - default 3 */
633 #define CVT_MIN_V_PORCH 3
634 /* 4) Minimum number of vertical back porch lines - default 6 */
635 #define CVT_MIN_V_BPORCH 6
636 /* Pixel Clock step (kHz) */
637 #define CVT_CLOCK_STEP 250
638 struct drm_display_mode
*drm_mode
;
639 unsigned int vfieldrate
, hperiod
;
640 int hdisplay_rnd
, hmargin
, vdisplay_rnd
, vmargin
, vsync
;
644 if (!hdisplay
|| !vdisplay
)
647 /* allocate the drm_display_mode structure. If failure, we will
650 drm_mode
= drm_mode_create(dev
);
654 /* the CVT default refresh rate is 60Hz */
658 /* the required field fresh rate */
660 vfieldrate
= vrefresh
* 2;
662 vfieldrate
= vrefresh
;
664 /* horizontal pixels */
665 hdisplay_rnd
= hdisplay
- (hdisplay
% CVT_H_GRANULARITY
);
667 /* determine the left&right borders */
670 hmargin
= hdisplay_rnd
* CVT_MARGIN_PERCENTAGE
/ 1000;
671 hmargin
-= hmargin
% CVT_H_GRANULARITY
;
673 /* find the total active pixels */
674 drm_mode
->hdisplay
= hdisplay_rnd
+ 2 * hmargin
;
676 /* find the number of lines per field */
678 vdisplay_rnd
= vdisplay
/ 2;
680 vdisplay_rnd
= vdisplay
;
682 /* find the top & bottom borders */
685 vmargin
= vdisplay_rnd
* CVT_MARGIN_PERCENTAGE
/ 1000;
687 drm_mode
->vdisplay
= vdisplay
+ 2 * vmargin
;
695 /* Determine VSync Width from aspect ratio */
696 if (!(vdisplay
% 3) && ((vdisplay
* 4 / 3) == hdisplay
))
698 else if (!(vdisplay
% 9) && ((vdisplay
* 16 / 9) == hdisplay
))
700 else if (!(vdisplay
% 10) && ((vdisplay
* 16 / 10) == hdisplay
))
702 else if (!(vdisplay
% 4) && ((vdisplay
* 5 / 4) == hdisplay
))
704 else if (!(vdisplay
% 9) && ((vdisplay
* 15 / 9) == hdisplay
))
710 /* simplify the GTF calculation */
711 /* 4) Minimum time of vertical sync + back porch interval (µs)
715 #define CVT_MIN_VSYNC_BP 550
716 /* 3) Nominal HSync width (% of line period) - default 8 */
717 #define CVT_HSYNC_PERCENTAGE 8
718 unsigned int hblank_percentage
;
719 int vsyncandback_porch
, __maybe_unused vback_porch
, hblank
;
721 /* estimated the horizontal period */
722 tmp1
= HV_FACTOR
* 1000000 -
723 CVT_MIN_VSYNC_BP
* HV_FACTOR
* vfieldrate
;
724 tmp2
= (vdisplay_rnd
+ 2 * vmargin
+ CVT_MIN_V_PORCH
) * 2 +
726 hperiod
= tmp1
* 2 / (tmp2
* vfieldrate
);
728 tmp1
= CVT_MIN_VSYNC_BP
* HV_FACTOR
/ hperiod
+ 1;
729 /* 9. Find number of lines in sync + backporch */
730 if (tmp1
< (vsync
+ CVT_MIN_V_PORCH
))
731 vsyncandback_porch
= vsync
+ CVT_MIN_V_PORCH
;
733 vsyncandback_porch
= tmp1
;
734 /* 10. Find number of lines in back porch */
735 vback_porch
= vsyncandback_porch
- vsync
;
736 drm_mode
->vtotal
= vdisplay_rnd
+ 2 * vmargin
+
737 vsyncandback_porch
+ CVT_MIN_V_PORCH
;
738 /* 5) Definition of Horizontal blanking time limitation */
739 /* Gradient (%/kHz) - default 600 */
740 #define CVT_M_FACTOR 600
741 /* Offset (%) - default 40 */
742 #define CVT_C_FACTOR 40
743 /* Blanking time scaling factor - default 128 */
744 #define CVT_K_FACTOR 128
745 /* Scaling factor weighting - default 20 */
746 #define CVT_J_FACTOR 20
747 #define CVT_M_PRIME (CVT_M_FACTOR * CVT_K_FACTOR / 256)
748 #define CVT_C_PRIME ((CVT_C_FACTOR - CVT_J_FACTOR) * CVT_K_FACTOR / 256 + \
750 /* 12. Find ideal blanking duty cycle from formula */
751 hblank_percentage
= CVT_C_PRIME
* HV_FACTOR
- CVT_M_PRIME
*
753 /* 13. Blanking time */
754 if (hblank_percentage
< 20 * HV_FACTOR
)
755 hblank_percentage
= 20 * HV_FACTOR
;
756 hblank
= drm_mode
->hdisplay
* hblank_percentage
/
757 (100 * HV_FACTOR
- hblank_percentage
);
758 hblank
-= hblank
% (2 * CVT_H_GRANULARITY
);
759 /* 14. find the total pixels per line */
760 drm_mode
->htotal
= drm_mode
->hdisplay
+ hblank
;
761 drm_mode
->hsync_end
= drm_mode
->hdisplay
+ hblank
/ 2;
762 drm_mode
->hsync_start
= drm_mode
->hsync_end
-
763 (drm_mode
->htotal
* CVT_HSYNC_PERCENTAGE
) / 100;
764 drm_mode
->hsync_start
+= CVT_H_GRANULARITY
-
765 drm_mode
->hsync_start
% CVT_H_GRANULARITY
;
766 /* fill the Vsync values */
767 drm_mode
->vsync_start
= drm_mode
->vdisplay
+ CVT_MIN_V_PORCH
;
768 drm_mode
->vsync_end
= drm_mode
->vsync_start
+ vsync
;
770 /* Reduced blanking */
771 /* Minimum vertical blanking interval time (µs)- default 460 */
772 #define CVT_RB_MIN_VBLANK 460
773 /* Fixed number of clocks for horizontal sync */
774 #define CVT_RB_H_SYNC 32
775 /* Fixed number of clocks for horizontal blanking */
776 #define CVT_RB_H_BLANK 160
777 /* Fixed number of lines for vertical front porch - default 3*/
778 #define CVT_RB_VFPORCH 3
781 /* 8. Estimate Horizontal period. */
782 tmp1
= HV_FACTOR
* 1000000 -
783 CVT_RB_MIN_VBLANK
* HV_FACTOR
* vfieldrate
;
784 tmp2
= vdisplay_rnd
+ 2 * vmargin
;
785 hperiod
= tmp1
/ (tmp2
* vfieldrate
);
786 /* 9. Find number of lines in vertical blanking */
787 vbilines
= CVT_RB_MIN_VBLANK
* HV_FACTOR
/ hperiod
+ 1;
788 /* 10. Check if vertical blanking is sufficient */
789 if (vbilines
< (CVT_RB_VFPORCH
+ vsync
+ CVT_MIN_V_BPORCH
))
790 vbilines
= CVT_RB_VFPORCH
+ vsync
+ CVT_MIN_V_BPORCH
;
791 /* 11. Find total number of lines in vertical field */
792 drm_mode
->vtotal
= vdisplay_rnd
+ 2 * vmargin
+ vbilines
;
793 /* 12. Find total number of pixels in a line */
794 drm_mode
->htotal
= drm_mode
->hdisplay
+ CVT_RB_H_BLANK
;
795 /* Fill in HSync values */
796 drm_mode
->hsync_end
= drm_mode
->hdisplay
+ CVT_RB_H_BLANK
/ 2;
797 drm_mode
->hsync_start
= drm_mode
->hsync_end
- CVT_RB_H_SYNC
;
798 /* Fill in VSync values */
799 drm_mode
->vsync_start
= drm_mode
->vdisplay
+ CVT_RB_VFPORCH
;
800 drm_mode
->vsync_end
= drm_mode
->vsync_start
+ vsync
;
802 /* 15/13. Find pixel clock frequency (kHz for xf86) */
803 tmp
= drm_mode
->htotal
; /* perform intermediate calcs in u64 */
804 tmp
*= HV_FACTOR
* 1000;
805 do_div(tmp
, hperiod
);
806 tmp
-= drm_mode
->clock
% CVT_CLOCK_STEP
;
807 drm_mode
->clock
= tmp
;
808 /* 18/16. Find actual vertical frame frequency */
809 /* ignore - just set the mode flag for interlaced */
811 drm_mode
->vtotal
*= 2;
812 drm_mode
->flags
|= DRM_MODE_FLAG_INTERLACE
;
814 /* Fill the mode line name */
815 drm_mode_set_name(drm_mode
);
817 drm_mode
->flags
|= (DRM_MODE_FLAG_PHSYNC
|
818 DRM_MODE_FLAG_NVSYNC
);
820 drm_mode
->flags
|= (DRM_MODE_FLAG_PVSYNC
|
821 DRM_MODE_FLAG_NHSYNC
);
825 EXPORT_SYMBOL(drm_cvt_mode
);
828 * drm_gtf_mode_complex - create the modeline based on the full GTF algorithm
830 * @hdisplay: hdisplay size
831 * @vdisplay: vdisplay size
832 * @vrefresh: vrefresh rate.
833 * @interlaced: whether to compute an interlaced mode
834 * @margins: desired margin (borders) size
835 * @GTF_M: extended GTF formula parameters
836 * @GTF_2C: extended GTF formula parameters
837 * @GTF_K: extended GTF formula parameters
838 * @GTF_2J: extended GTF formula parameters
840 * GTF feature blocks specify C and J in multiples of 0.5, so we pass them
841 * in here multiplied by two. For a C of 40, pass in 80.
844 * The modeline based on the full GTF algorithm stored in a drm_display_mode object.
845 * The display mode object is allocated with drm_mode_create(). Returns NULL
846 * when no mode could be allocated.
848 struct drm_display_mode
*
849 drm_gtf_mode_complex(struct drm_device
*dev
, int hdisplay
, int vdisplay
,
850 int vrefresh
, bool interlaced
, int margins
,
851 int GTF_M
, int GTF_2C
, int GTF_K
, int GTF_2J
)
852 { /* 1) top/bottom margin size (% of height) - default: 1.8, */
853 #define GTF_MARGIN_PERCENTAGE 18
854 /* 2) character cell horizontal granularity (pixels) - default 8 */
855 #define GTF_CELL_GRAN 8
856 /* 3) Minimum vertical porch (lines) - default 3 */
857 #define GTF_MIN_V_PORCH 1
858 /* width of vsync in lines */
860 /* width of hsync as % of total line */
861 #define H_SYNC_PERCENT 8
862 /* min time of vsync + back porch (microsec) */
863 #define MIN_VSYNC_PLUS_BP 550
864 /* C' and M' are part of the Blanking Duty Cycle computation */
865 #define GTF_C_PRIME ((((GTF_2C - GTF_2J) * GTF_K / 256) + GTF_2J) / 2)
866 #define GTF_M_PRIME (GTF_K * GTF_M / 256)
867 struct drm_display_mode
*drm_mode
;
868 unsigned int hdisplay_rnd
, vdisplay_rnd
, vfieldrate_rqd
;
869 int top_margin
, bottom_margin
;
871 unsigned int hfreq_est
;
872 int vsync_plus_bp
, __maybe_unused vback_porch
;
873 unsigned int vtotal_lines
, __maybe_unused vfieldrate_est
;
874 unsigned int __maybe_unused hperiod
;
875 unsigned int vfield_rate
, __maybe_unused vframe_rate
;
876 int left_margin
, right_margin
;
877 unsigned int total_active_pixels
, ideal_duty_cycle
;
878 unsigned int hblank
, total_pixels
, pixel_freq
;
879 int hsync
, hfront_porch
, vodd_front_porch_lines
;
880 unsigned int tmp1
, tmp2
;
882 if (!hdisplay
|| !vdisplay
)
885 drm_mode
= drm_mode_create(dev
);
889 /* 1. In order to give correct results, the number of horizontal
890 * pixels requested is first processed to ensure that it is divisible
891 * by the character size, by rounding it to the nearest character
894 hdisplay_rnd
= (hdisplay
+ GTF_CELL_GRAN
/ 2) / GTF_CELL_GRAN
;
895 hdisplay_rnd
= hdisplay_rnd
* GTF_CELL_GRAN
;
897 /* 2. If interlace is requested, the number of vertical lines assumed
898 * by the calculation must be halved, as the computation calculates
899 * the number of vertical lines per field.
902 vdisplay_rnd
= vdisplay
/ 2;
904 vdisplay_rnd
= vdisplay
;
906 /* 3. Find the frame rate required: */
908 vfieldrate_rqd
= vrefresh
* 2;
910 vfieldrate_rqd
= vrefresh
;
912 /* 4. Find number of lines in Top margin: */
915 top_margin
= (vdisplay_rnd
* GTF_MARGIN_PERCENTAGE
+ 500) /
917 /* 5. Find number of lines in bottom margin: */
918 bottom_margin
= top_margin
;
920 /* 6. If interlace is required, then set variable interlace: */
926 /* 7. Estimate the Horizontal frequency */
928 tmp1
= (1000000 - MIN_VSYNC_PLUS_BP
* vfieldrate_rqd
) / 500;
929 tmp2
= (vdisplay_rnd
+ 2 * top_margin
+ GTF_MIN_V_PORCH
) *
931 hfreq_est
= (tmp2
* 1000 * vfieldrate_rqd
) / tmp1
;
934 /* 8. Find the number of lines in V sync + back porch */
935 /* [V SYNC+BP] = RINT(([MIN VSYNC+BP] * hfreq_est / 1000000)) */
936 vsync_plus_bp
= MIN_VSYNC_PLUS_BP
* hfreq_est
/ 1000;
937 vsync_plus_bp
= (vsync_plus_bp
+ 500) / 1000;
938 /* 9. Find the number of lines in V back porch alone: */
939 vback_porch
= vsync_plus_bp
- V_SYNC_RQD
;
940 /* 10. Find the total number of lines in Vertical field period: */
941 vtotal_lines
= vdisplay_rnd
+ top_margin
+ bottom_margin
+
942 vsync_plus_bp
+ GTF_MIN_V_PORCH
;
943 /* 11. Estimate the Vertical field frequency: */
944 vfieldrate_est
= hfreq_est
/ vtotal_lines
;
945 /* 12. Find the actual horizontal period: */
946 hperiod
= 1000000 / (vfieldrate_rqd
* vtotal_lines
);
948 /* 13. Find the actual Vertical field frequency: */
949 vfield_rate
= hfreq_est
/ vtotal_lines
;
950 /* 14. Find the Vertical frame frequency: */
952 vframe_rate
= vfield_rate
/ 2;
954 vframe_rate
= vfield_rate
;
955 /* 15. Find number of pixels in left margin: */
957 left_margin
= (hdisplay_rnd
* GTF_MARGIN_PERCENTAGE
+ 500) /
962 /* 16.Find number of pixels in right margin: */
963 right_margin
= left_margin
;
964 /* 17.Find total number of active pixels in image and left and right */
965 total_active_pixels
= hdisplay_rnd
+ left_margin
+ right_margin
;
966 /* 18.Find the ideal blanking duty cycle from blanking duty cycle */
967 ideal_duty_cycle
= GTF_C_PRIME
* 1000 -
968 (GTF_M_PRIME
* 1000000 / hfreq_est
);
969 /* 19.Find the number of pixels in the blanking time to the nearest
970 * double character cell: */
971 hblank
= total_active_pixels
* ideal_duty_cycle
/
972 (100000 - ideal_duty_cycle
);
973 hblank
= (hblank
+ GTF_CELL_GRAN
) / (2 * GTF_CELL_GRAN
);
974 hblank
= hblank
* 2 * GTF_CELL_GRAN
;
975 /* 20.Find total number of pixels: */
976 total_pixels
= total_active_pixels
+ hblank
;
977 /* 21.Find pixel clock frequency: */
978 pixel_freq
= total_pixels
* hfreq_est
/ 1000;
979 /* Stage 1 computations are now complete; I should really pass
980 * the results to another function and do the Stage 2 computations,
981 * but I only need a few more values so I'll just append the
982 * computations here for now */
983 /* 17. Find the number of pixels in the horizontal sync period: */
984 hsync
= H_SYNC_PERCENT
* total_pixels
/ 100;
985 hsync
= (hsync
+ GTF_CELL_GRAN
/ 2) / GTF_CELL_GRAN
;
986 hsync
= hsync
* GTF_CELL_GRAN
;
987 /* 18. Find the number of pixels in horizontal front porch period */
988 hfront_porch
= hblank
/ 2 - hsync
;
989 /* 36. Find the number of lines in the odd front porch period: */
990 vodd_front_porch_lines
= GTF_MIN_V_PORCH
;
992 /* finally, pack the results in the mode struct */
993 drm_mode
->hdisplay
= hdisplay_rnd
;
994 drm_mode
->hsync_start
= hdisplay_rnd
+ hfront_porch
;
995 drm_mode
->hsync_end
= drm_mode
->hsync_start
+ hsync
;
996 drm_mode
->htotal
= total_pixels
;
997 drm_mode
->vdisplay
= vdisplay_rnd
;
998 drm_mode
->vsync_start
= vdisplay_rnd
+ vodd_front_porch_lines
;
999 drm_mode
->vsync_end
= drm_mode
->vsync_start
+ V_SYNC_RQD
;
1000 drm_mode
->vtotal
= vtotal_lines
;
1002 drm_mode
->clock
= pixel_freq
;
1005 drm_mode
->vtotal
*= 2;
1006 drm_mode
->flags
|= DRM_MODE_FLAG_INTERLACE
;
1009 drm_mode_set_name(drm_mode
);
1010 if (GTF_M
== 600 && GTF_2C
== 80 && GTF_K
== 128 && GTF_2J
== 40)
1011 drm_mode
->flags
= DRM_MODE_FLAG_NHSYNC
| DRM_MODE_FLAG_PVSYNC
;
1013 drm_mode
->flags
= DRM_MODE_FLAG_PHSYNC
| DRM_MODE_FLAG_NVSYNC
;
1017 EXPORT_SYMBOL(drm_gtf_mode_complex
);
1020 * drm_gtf_mode - create the modeline based on the GTF algorithm
1022 * @hdisplay: hdisplay size
1023 * @vdisplay: vdisplay size
1024 * @vrefresh: vrefresh rate.
1025 * @interlaced: whether to compute an interlaced mode
1026 * @margins: desired margin (borders) size
1028 * return the modeline based on GTF algorithm
1030 * This function is to create the modeline based on the GTF algorithm.
1031 * Generalized Timing Formula is derived from:
1033 * GTF Spreadsheet by Andy Morrish (1/5/97)
1034 * available at https://www.vesa.org
1036 * And it is copied from the file of xserver/hw/xfree86/modes/xf86gtf.c.
1037 * What I have done is to translate it by using integer calculation.
1038 * I also refer to the function of fb_get_mode in the file of
1039 * drivers/video/fbmon.c
1041 * Standard GTF parameters::
1049 * The modeline based on the GTF algorithm stored in a drm_display_mode object.
1050 * The display mode object is allocated with drm_mode_create(). Returns NULL
1051 * when no mode could be allocated.
1053 struct drm_display_mode
*
1054 drm_gtf_mode(struct drm_device
*dev
, int hdisplay
, int vdisplay
, int vrefresh
,
1055 bool interlaced
, int margins
)
1057 return drm_gtf_mode_complex(dev
, hdisplay
, vdisplay
, vrefresh
,
1058 interlaced
, margins
,
1059 600, 40 * 2, 128, 20 * 2);
1061 EXPORT_SYMBOL(drm_gtf_mode
);
1063 #ifdef CONFIG_VIDEOMODE_HELPERS
1065 * drm_display_mode_from_videomode - fill in @dmode using @vm,
1066 * @vm: videomode structure to use as source
1067 * @dmode: drm_display_mode structure to use as destination
1069 * Fills out @dmode using the display mode specified in @vm.
1071 void drm_display_mode_from_videomode(const struct videomode
*vm
,
1072 struct drm_display_mode
*dmode
)
1074 dmode
->hdisplay
= vm
->hactive
;
1075 dmode
->hsync_start
= dmode
->hdisplay
+ vm
->hfront_porch
;
1076 dmode
->hsync_end
= dmode
->hsync_start
+ vm
->hsync_len
;
1077 dmode
->htotal
= dmode
->hsync_end
+ vm
->hback_porch
;
1079 dmode
->vdisplay
= vm
->vactive
;
1080 dmode
->vsync_start
= dmode
->vdisplay
+ vm
->vfront_porch
;
1081 dmode
->vsync_end
= dmode
->vsync_start
+ vm
->vsync_len
;
1082 dmode
->vtotal
= dmode
->vsync_end
+ vm
->vback_porch
;
1084 dmode
->clock
= vm
->pixelclock
/ 1000;
1087 if (vm
->flags
& DISPLAY_FLAGS_HSYNC_HIGH
)
1088 dmode
->flags
|= DRM_MODE_FLAG_PHSYNC
;
1089 else if (vm
->flags
& DISPLAY_FLAGS_HSYNC_LOW
)
1090 dmode
->flags
|= DRM_MODE_FLAG_NHSYNC
;
1091 if (vm
->flags
& DISPLAY_FLAGS_VSYNC_HIGH
)
1092 dmode
->flags
|= DRM_MODE_FLAG_PVSYNC
;
1093 else if (vm
->flags
& DISPLAY_FLAGS_VSYNC_LOW
)
1094 dmode
->flags
|= DRM_MODE_FLAG_NVSYNC
;
1095 if (vm
->flags
& DISPLAY_FLAGS_INTERLACED
)
1096 dmode
->flags
|= DRM_MODE_FLAG_INTERLACE
;
1097 if (vm
->flags
& DISPLAY_FLAGS_DOUBLESCAN
)
1098 dmode
->flags
|= DRM_MODE_FLAG_DBLSCAN
;
1099 if (vm
->flags
& DISPLAY_FLAGS_DOUBLECLK
)
1100 dmode
->flags
|= DRM_MODE_FLAG_DBLCLK
;
1101 drm_mode_set_name(dmode
);
1103 EXPORT_SYMBOL_GPL(drm_display_mode_from_videomode
);
1106 * drm_display_mode_to_videomode - fill in @vm using @dmode,
1107 * @dmode: drm_display_mode structure to use as source
1108 * @vm: videomode structure to use as destination
1110 * Fills out @vm using the display mode specified in @dmode.
1112 void drm_display_mode_to_videomode(const struct drm_display_mode
*dmode
,
1113 struct videomode
*vm
)
1115 vm
->hactive
= dmode
->hdisplay
;
1116 vm
->hfront_porch
= dmode
->hsync_start
- dmode
->hdisplay
;
1117 vm
->hsync_len
= dmode
->hsync_end
- dmode
->hsync_start
;
1118 vm
->hback_porch
= dmode
->htotal
- dmode
->hsync_end
;
1120 vm
->vactive
= dmode
->vdisplay
;
1121 vm
->vfront_porch
= dmode
->vsync_start
- dmode
->vdisplay
;
1122 vm
->vsync_len
= dmode
->vsync_end
- dmode
->vsync_start
;
1123 vm
->vback_porch
= dmode
->vtotal
- dmode
->vsync_end
;
1125 vm
->pixelclock
= dmode
->clock
* 1000;
1128 if (dmode
->flags
& DRM_MODE_FLAG_PHSYNC
)
1129 vm
->flags
|= DISPLAY_FLAGS_HSYNC_HIGH
;
1130 else if (dmode
->flags
& DRM_MODE_FLAG_NHSYNC
)
1131 vm
->flags
|= DISPLAY_FLAGS_HSYNC_LOW
;
1132 if (dmode
->flags
& DRM_MODE_FLAG_PVSYNC
)
1133 vm
->flags
|= DISPLAY_FLAGS_VSYNC_HIGH
;
1134 else if (dmode
->flags
& DRM_MODE_FLAG_NVSYNC
)
1135 vm
->flags
|= DISPLAY_FLAGS_VSYNC_LOW
;
1136 if (dmode
->flags
& DRM_MODE_FLAG_INTERLACE
)
1137 vm
->flags
|= DISPLAY_FLAGS_INTERLACED
;
1138 if (dmode
->flags
& DRM_MODE_FLAG_DBLSCAN
)
1139 vm
->flags
|= DISPLAY_FLAGS_DOUBLESCAN
;
1140 if (dmode
->flags
& DRM_MODE_FLAG_DBLCLK
)
1141 vm
->flags
|= DISPLAY_FLAGS_DOUBLECLK
;
1143 EXPORT_SYMBOL_GPL(drm_display_mode_to_videomode
);
1146 * drm_bus_flags_from_videomode - extract information about pixelclk and
1147 * DE polarity from videomode and store it in a separate variable
1148 * @vm: videomode structure to use
1149 * @bus_flags: information about pixelclk, sync and DE polarity will be stored
1152 * Sets DRM_BUS_FLAG_DE_(LOW|HIGH), DRM_BUS_FLAG_PIXDATA_DRIVE_(POS|NEG)EDGE
1153 * and DISPLAY_FLAGS_SYNC_(POS|NEG)EDGE in @bus_flags according to DISPLAY_FLAGS
1156 void drm_bus_flags_from_videomode(const struct videomode
*vm
, u32
*bus_flags
)
1159 if (vm
->flags
& DISPLAY_FLAGS_PIXDATA_POSEDGE
)
1160 *bus_flags
|= DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE
;
1161 if (vm
->flags
& DISPLAY_FLAGS_PIXDATA_NEGEDGE
)
1162 *bus_flags
|= DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE
;
1164 if (vm
->flags
& DISPLAY_FLAGS_SYNC_POSEDGE
)
1165 *bus_flags
|= DRM_BUS_FLAG_SYNC_DRIVE_POSEDGE
;
1166 if (vm
->flags
& DISPLAY_FLAGS_SYNC_NEGEDGE
)
1167 *bus_flags
|= DRM_BUS_FLAG_SYNC_DRIVE_NEGEDGE
;
1169 if (vm
->flags
& DISPLAY_FLAGS_DE_LOW
)
1170 *bus_flags
|= DRM_BUS_FLAG_DE_LOW
;
1171 if (vm
->flags
& DISPLAY_FLAGS_DE_HIGH
)
1172 *bus_flags
|= DRM_BUS_FLAG_DE_HIGH
;
1174 EXPORT_SYMBOL_GPL(drm_bus_flags_from_videomode
);
1178 * of_get_drm_display_mode - get a drm_display_mode from devicetree
1179 * @np: device_node with the timing specification
1180 * @dmode: will be set to the return value
1181 * @bus_flags: information about pixelclk, sync and DE polarity
1182 * @index: index into the list of display timings in devicetree
1184 * This function is expensive and should only be used, if only one mode is to be
1185 * read from DT. To get multiple modes start with of_get_display_timings and
1186 * work with that instead.
1189 * 0 on success, a negative errno code when no of videomode node was found.
1191 int of_get_drm_display_mode(struct device_node
*np
,
1192 struct drm_display_mode
*dmode
, u32
*bus_flags
,
1195 struct videomode vm
;
1198 ret
= of_get_videomode(np
, &vm
, index
);
1202 drm_display_mode_from_videomode(&vm
, dmode
);
1204 drm_bus_flags_from_videomode(&vm
, bus_flags
);
1206 pr_debug("%pOF: got %dx%d display mode: " DRM_MODE_FMT
"\n",
1207 np
, vm
.hactive
, vm
.vactive
, DRM_MODE_ARG(dmode
));
1211 EXPORT_SYMBOL_GPL(of_get_drm_display_mode
);
1214 * of_get_drm_panel_display_mode - get a panel-timing drm_display_mode from devicetree
1215 * @np: device_node with the panel-timing specification
1216 * @dmode: will be set to the return value
1217 * @bus_flags: information about pixelclk, sync and DE polarity
1219 * The mandatory Device Tree properties width-mm and height-mm
1220 * are read and set on the display mode.
1223 * Zero on success, negative error code on failure.
1225 int of_get_drm_panel_display_mode(struct device_node
*np
,
1226 struct drm_display_mode
*dmode
, u32
*bus_flags
)
1228 u32 width_mm
= 0, height_mm
= 0;
1229 struct display_timing timing
;
1230 struct videomode vm
;
1233 ret
= of_get_display_timing(np
, "panel-timing", &timing
);
1237 videomode_from_timing(&timing
, &vm
);
1239 memset(dmode
, 0, sizeof(*dmode
));
1240 drm_display_mode_from_videomode(&vm
, dmode
);
1242 drm_bus_flags_from_videomode(&vm
, bus_flags
);
1244 ret
= of_property_read_u32(np
, "width-mm", &width_mm
);
1248 ret
= of_property_read_u32(np
, "height-mm", &height_mm
);
1252 dmode
->width_mm
= width_mm
;
1253 dmode
->height_mm
= height_mm
;
1255 pr_debug(DRM_MODE_FMT
"\n", DRM_MODE_ARG(dmode
));
1259 EXPORT_SYMBOL_GPL(of_get_drm_panel_display_mode
);
1260 #endif /* CONFIG_OF */
1261 #endif /* CONFIG_VIDEOMODE_HELPERS */
1264 * drm_mode_set_name - set the name on a mode
1265 * @mode: name will be set in this mode
1267 * Set the name of @mode to a standard format which is <hdisplay>x<vdisplay>
1268 * with an optional 'i' suffix for interlaced modes.
1270 void drm_mode_set_name(struct drm_display_mode
*mode
)
1272 bool interlaced
= !!(mode
->flags
& DRM_MODE_FLAG_INTERLACE
);
1274 snprintf(mode
->name
, DRM_DISPLAY_MODE_LEN
, "%dx%d%s",
1275 mode
->hdisplay
, mode
->vdisplay
,
1276 interlaced
? "i" : "");
1278 EXPORT_SYMBOL(drm_mode_set_name
);
1281 * drm_mode_vrefresh - get the vrefresh of a mode
1285 * @modes's vrefresh rate in Hz, rounded to the nearest integer. Calculates the
1286 * value first if it is not yet set.
1288 int drm_mode_vrefresh(const struct drm_display_mode
*mode
)
1290 unsigned int num
, den
;
1292 if (mode
->htotal
== 0 || mode
->vtotal
== 0)
1296 den
= mode
->htotal
* mode
->vtotal
;
1298 if (mode
->flags
& DRM_MODE_FLAG_INTERLACE
)
1300 if (mode
->flags
& DRM_MODE_FLAG_DBLSCAN
)
1302 if (mode
->vscan
> 1)
1305 return DIV_ROUND_CLOSEST_ULL(mul_u32_u32(num
, 1000), den
);
1307 EXPORT_SYMBOL(drm_mode_vrefresh
);
1310 * drm_mode_get_hv_timing - Fetches hdisplay/vdisplay for given mode
1311 * @mode: mode to query
1312 * @hdisplay: hdisplay value to fill in
1313 * @vdisplay: vdisplay value to fill in
1315 * The vdisplay value will be doubled if the specified mode is a stereo mode of
1316 * the appropriate layout.
1318 void drm_mode_get_hv_timing(const struct drm_display_mode
*mode
,
1319 int *hdisplay
, int *vdisplay
)
1321 struct drm_display_mode adjusted
;
1323 drm_mode_init(&adjusted
, mode
);
1325 drm_mode_set_crtcinfo(&adjusted
, CRTC_STEREO_DOUBLE_ONLY
);
1326 *hdisplay
= adjusted
.crtc_hdisplay
;
1327 *vdisplay
= adjusted
.crtc_vdisplay
;
1329 EXPORT_SYMBOL(drm_mode_get_hv_timing
);
1332 * drm_mode_set_crtcinfo - set CRTC modesetting timing parameters
1334 * @adjust_flags: a combination of adjustment flags
1336 * Setup the CRTC modesetting timing parameters for @p, adjusting if necessary.
1338 * - The CRTC_INTERLACE_HALVE_V flag can be used to halve vertical timings of
1340 * - The CRTC_STEREO_DOUBLE flag can be used to compute the timings for
1341 * buffers containing two eyes (only adjust the timings when needed, eg. for
1342 * "frame packing" or "side by side full").
1343 * - The CRTC_NO_DBLSCAN and CRTC_NO_VSCAN flags request that adjustment *not*
1344 * be performed for doublescan and vscan > 1 modes respectively.
1346 void drm_mode_set_crtcinfo(struct drm_display_mode
*p
, int adjust_flags
)
1351 p
->crtc_clock
= p
->clock
;
1352 p
->crtc_hdisplay
= p
->hdisplay
;
1353 p
->crtc_hsync_start
= p
->hsync_start
;
1354 p
->crtc_hsync_end
= p
->hsync_end
;
1355 p
->crtc_htotal
= p
->htotal
;
1356 p
->crtc_hskew
= p
->hskew
;
1357 p
->crtc_vdisplay
= p
->vdisplay
;
1358 p
->crtc_vsync_start
= p
->vsync_start
;
1359 p
->crtc_vsync_end
= p
->vsync_end
;
1360 p
->crtc_vtotal
= p
->vtotal
;
1362 if (p
->flags
& DRM_MODE_FLAG_INTERLACE
) {
1363 if (adjust_flags
& CRTC_INTERLACE_HALVE_V
) {
1364 p
->crtc_vdisplay
/= 2;
1365 p
->crtc_vsync_start
/= 2;
1366 p
->crtc_vsync_end
/= 2;
1367 p
->crtc_vtotal
/= 2;
1371 if (!(adjust_flags
& CRTC_NO_DBLSCAN
)) {
1372 if (p
->flags
& DRM_MODE_FLAG_DBLSCAN
) {
1373 p
->crtc_vdisplay
*= 2;
1374 p
->crtc_vsync_start
*= 2;
1375 p
->crtc_vsync_end
*= 2;
1376 p
->crtc_vtotal
*= 2;
1380 if (!(adjust_flags
& CRTC_NO_VSCAN
)) {
1382 p
->crtc_vdisplay
*= p
->vscan
;
1383 p
->crtc_vsync_start
*= p
->vscan
;
1384 p
->crtc_vsync_end
*= p
->vscan
;
1385 p
->crtc_vtotal
*= p
->vscan
;
1389 if (adjust_flags
& CRTC_STEREO_DOUBLE
) {
1390 unsigned int layout
= p
->flags
& DRM_MODE_FLAG_3D_MASK
;
1393 case DRM_MODE_FLAG_3D_FRAME_PACKING
:
1395 p
->crtc_vdisplay
+= p
->crtc_vtotal
;
1396 p
->crtc_vsync_start
+= p
->crtc_vtotal
;
1397 p
->crtc_vsync_end
+= p
->crtc_vtotal
;
1398 p
->crtc_vtotal
+= p
->crtc_vtotal
;
1403 p
->crtc_vblank_start
= min(p
->crtc_vsync_start
, p
->crtc_vdisplay
);
1404 p
->crtc_vblank_end
= max(p
->crtc_vsync_end
, p
->crtc_vtotal
);
1405 p
->crtc_hblank_start
= min(p
->crtc_hsync_start
, p
->crtc_hdisplay
);
1406 p
->crtc_hblank_end
= max(p
->crtc_hsync_end
, p
->crtc_htotal
);
1408 EXPORT_SYMBOL(drm_mode_set_crtcinfo
);
1411 * drm_mode_copy - copy the mode
1412 * @dst: mode to overwrite
1413 * @src: mode to copy
1415 * Copy an existing mode into another mode, preserving the
1416 * list head of the destination mode.
1418 void drm_mode_copy(struct drm_display_mode
*dst
, const struct drm_display_mode
*src
)
1420 struct list_head head
= dst
->head
;
1425 EXPORT_SYMBOL(drm_mode_copy
);
1428 * drm_mode_init - initialize the mode from another mode
1429 * @dst: mode to overwrite
1430 * @src: mode to copy
1432 * Copy an existing mode into another mode, zeroing the
1433 * list head of the destination mode. Typically used
1434 * to guarantee the list head is not left with stack
1435 * garbage in on-stack modes.
1437 void drm_mode_init(struct drm_display_mode
*dst
, const struct drm_display_mode
*src
)
1439 memset(dst
, 0, sizeof(*dst
));
1440 drm_mode_copy(dst
, src
);
1442 EXPORT_SYMBOL(drm_mode_init
);
1445 * drm_mode_duplicate - allocate and duplicate an existing mode
1446 * @dev: drm_device to allocate the duplicated mode for
1447 * @mode: mode to duplicate
1449 * Just allocate a new mode, copy the existing mode into it, and return
1450 * a pointer to it. Used to create new instances of established modes.
1453 * Pointer to duplicated mode on success, NULL on error.
1455 struct drm_display_mode
*drm_mode_duplicate(struct drm_device
*dev
,
1456 const struct drm_display_mode
*mode
)
1458 struct drm_display_mode
*nmode
;
1460 nmode
= drm_mode_create(dev
);
1464 drm_mode_copy(nmode
, mode
);
1468 EXPORT_SYMBOL(drm_mode_duplicate
);
1470 static bool drm_mode_match_timings(const struct drm_display_mode
*mode1
,
1471 const struct drm_display_mode
*mode2
)
1473 return mode1
->hdisplay
== mode2
->hdisplay
&&
1474 mode1
->hsync_start
== mode2
->hsync_start
&&
1475 mode1
->hsync_end
== mode2
->hsync_end
&&
1476 mode1
->htotal
== mode2
->htotal
&&
1477 mode1
->hskew
== mode2
->hskew
&&
1478 mode1
->vdisplay
== mode2
->vdisplay
&&
1479 mode1
->vsync_start
== mode2
->vsync_start
&&
1480 mode1
->vsync_end
== mode2
->vsync_end
&&
1481 mode1
->vtotal
== mode2
->vtotal
&&
1482 mode1
->vscan
== mode2
->vscan
;
1485 static bool drm_mode_match_clock(const struct drm_display_mode
*mode1
,
1486 const struct drm_display_mode
*mode2
)
1489 * do clock check convert to PICOS
1490 * so fb modes get matched the same
1492 if (mode1
->clock
&& mode2
->clock
)
1493 return KHZ2PICOS(mode1
->clock
) == KHZ2PICOS(mode2
->clock
);
1495 return mode1
->clock
== mode2
->clock
;
1498 static bool drm_mode_match_flags(const struct drm_display_mode
*mode1
,
1499 const struct drm_display_mode
*mode2
)
1501 return (mode1
->flags
& ~DRM_MODE_FLAG_3D_MASK
) ==
1502 (mode2
->flags
& ~DRM_MODE_FLAG_3D_MASK
);
1505 static bool drm_mode_match_3d_flags(const struct drm_display_mode
*mode1
,
1506 const struct drm_display_mode
*mode2
)
1508 return (mode1
->flags
& DRM_MODE_FLAG_3D_MASK
) ==
1509 (mode2
->flags
& DRM_MODE_FLAG_3D_MASK
);
1512 static bool drm_mode_match_aspect_ratio(const struct drm_display_mode
*mode1
,
1513 const struct drm_display_mode
*mode2
)
1515 return mode1
->picture_aspect_ratio
== mode2
->picture_aspect_ratio
;
1519 * drm_mode_match - test modes for (partial) equality
1520 * @mode1: first mode
1521 * @mode2: second mode
1522 * @match_flags: which parts need to match (DRM_MODE_MATCH_*)
1524 * Check to see if @mode1 and @mode2 are equivalent.
1527 * True if the modes are (partially) equal, false otherwise.
1529 bool drm_mode_match(const struct drm_display_mode
*mode1
,
1530 const struct drm_display_mode
*mode2
,
1531 unsigned int match_flags
)
1533 if (!mode1
&& !mode2
)
1536 if (!mode1
|| !mode2
)
1539 if (match_flags
& DRM_MODE_MATCH_TIMINGS
&&
1540 !drm_mode_match_timings(mode1
, mode2
))
1543 if (match_flags
& DRM_MODE_MATCH_CLOCK
&&
1544 !drm_mode_match_clock(mode1
, mode2
))
1547 if (match_flags
& DRM_MODE_MATCH_FLAGS
&&
1548 !drm_mode_match_flags(mode1
, mode2
))
1551 if (match_flags
& DRM_MODE_MATCH_3D_FLAGS
&&
1552 !drm_mode_match_3d_flags(mode1
, mode2
))
1555 if (match_flags
& DRM_MODE_MATCH_ASPECT_RATIO
&&
1556 !drm_mode_match_aspect_ratio(mode1
, mode2
))
1561 EXPORT_SYMBOL(drm_mode_match
);
1564 * drm_mode_equal - test modes for equality
1565 * @mode1: first mode
1566 * @mode2: second mode
1568 * Check to see if @mode1 and @mode2 are equivalent.
1571 * True if the modes are equal, false otherwise.
1573 bool drm_mode_equal(const struct drm_display_mode
*mode1
,
1574 const struct drm_display_mode
*mode2
)
1576 return drm_mode_match(mode1
, mode2
,
1577 DRM_MODE_MATCH_TIMINGS
|
1578 DRM_MODE_MATCH_CLOCK
|
1579 DRM_MODE_MATCH_FLAGS
|
1580 DRM_MODE_MATCH_3D_FLAGS
|
1581 DRM_MODE_MATCH_ASPECT_RATIO
);
1583 EXPORT_SYMBOL(drm_mode_equal
);
1586 * drm_mode_equal_no_clocks - test modes for equality
1587 * @mode1: first mode
1588 * @mode2: second mode
1590 * Check to see if @mode1 and @mode2 are equivalent, but
1591 * don't check the pixel clocks.
1594 * True if the modes are equal, false otherwise.
1596 bool drm_mode_equal_no_clocks(const struct drm_display_mode
*mode1
,
1597 const struct drm_display_mode
*mode2
)
1599 return drm_mode_match(mode1
, mode2
,
1600 DRM_MODE_MATCH_TIMINGS
|
1601 DRM_MODE_MATCH_FLAGS
|
1602 DRM_MODE_MATCH_3D_FLAGS
);
1604 EXPORT_SYMBOL(drm_mode_equal_no_clocks
);
1607 * drm_mode_equal_no_clocks_no_stereo - test modes for equality
1608 * @mode1: first mode
1609 * @mode2: second mode
1611 * Check to see if @mode1 and @mode2 are equivalent, but
1612 * don't check the pixel clocks nor the stereo layout.
1615 * True if the modes are equal, false otherwise.
1617 bool drm_mode_equal_no_clocks_no_stereo(const struct drm_display_mode
*mode1
,
1618 const struct drm_display_mode
*mode2
)
1620 return drm_mode_match(mode1
, mode2
,
1621 DRM_MODE_MATCH_TIMINGS
|
1622 DRM_MODE_MATCH_FLAGS
);
1624 EXPORT_SYMBOL(drm_mode_equal_no_clocks_no_stereo
);
1626 static enum drm_mode_status
1627 drm_mode_validate_basic(const struct drm_display_mode
*mode
)
1629 if (mode
->type
& ~DRM_MODE_TYPE_ALL
)
1632 if (mode
->flags
& ~DRM_MODE_FLAG_ALL
)
1635 if ((mode
->flags
& DRM_MODE_FLAG_3D_MASK
) > DRM_MODE_FLAG_3D_MAX
)
1638 if (mode
->clock
== 0)
1639 return MODE_CLOCK_LOW
;
1641 if (mode
->hdisplay
== 0 ||
1642 mode
->hsync_start
< mode
->hdisplay
||
1643 mode
->hsync_end
< mode
->hsync_start
||
1644 mode
->htotal
< mode
->hsync_end
)
1645 return MODE_H_ILLEGAL
;
1647 if (mode
->vdisplay
== 0 ||
1648 mode
->vsync_start
< mode
->vdisplay
||
1649 mode
->vsync_end
< mode
->vsync_start
||
1650 mode
->vtotal
< mode
->vsync_end
)
1651 return MODE_V_ILLEGAL
;
1657 * drm_mode_validate_driver - make sure the mode is somewhat sane
1659 * @mode: mode to check
1661 * First do basic validation on the mode, and then allow the driver
1662 * to check for device/driver specific limitations via the optional
1663 * &drm_mode_config_helper_funcs.mode_valid hook.
1668 enum drm_mode_status
1669 drm_mode_validate_driver(struct drm_device
*dev
,
1670 const struct drm_display_mode
*mode
)
1672 enum drm_mode_status status
;
1674 status
= drm_mode_validate_basic(mode
);
1675 if (status
!= MODE_OK
)
1678 if (dev
->mode_config
.funcs
->mode_valid
)
1679 return dev
->mode_config
.funcs
->mode_valid(dev
, mode
);
1683 EXPORT_SYMBOL(drm_mode_validate_driver
);
1686 * drm_mode_validate_size - make sure modes adhere to size constraints
1687 * @mode: mode to check
1688 * @maxX: maximum width
1689 * @maxY: maximum height
1691 * This function is a helper which can be used to validate modes against size
1692 * limitations of the DRM device/connector. If a mode is too big its status
1693 * member is updated with the appropriate validation failure code. The list
1694 * itself is not changed.
1699 enum drm_mode_status
1700 drm_mode_validate_size(const struct drm_display_mode
*mode
,
1703 if (maxX
> 0 && mode
->hdisplay
> maxX
)
1704 return MODE_VIRTUAL_X
;
1706 if (maxY
> 0 && mode
->vdisplay
> maxY
)
1707 return MODE_VIRTUAL_Y
;
1711 EXPORT_SYMBOL(drm_mode_validate_size
);
1714 * drm_mode_validate_ycbcr420 - add 'ycbcr420-only' modes only when allowed
1715 * @mode: mode to check
1716 * @connector: drm connector under action
1718 * This function is a helper which can be used to filter out any YCBCR420
1719 * only mode, when the source doesn't support it.
1724 enum drm_mode_status
1725 drm_mode_validate_ycbcr420(const struct drm_display_mode
*mode
,
1726 struct drm_connector
*connector
)
1728 if (!connector
->ycbcr_420_allowed
&&
1729 drm_mode_is_420_only(&connector
->display_info
, mode
))
1734 EXPORT_SYMBOL(drm_mode_validate_ycbcr420
);
1736 #define MODE_STATUS(status) [MODE_ ## status + 3] = #status
1738 static const char * const drm_mode_status_names
[] = {
1742 MODE_STATUS(H_ILLEGAL
),
1743 MODE_STATUS(V_ILLEGAL
),
1744 MODE_STATUS(BAD_WIDTH
),
1745 MODE_STATUS(NOMODE
),
1746 MODE_STATUS(NO_INTERLACE
),
1747 MODE_STATUS(NO_DBLESCAN
),
1748 MODE_STATUS(NO_VSCAN
),
1750 MODE_STATUS(VIRTUAL_X
),
1751 MODE_STATUS(VIRTUAL_Y
),
1752 MODE_STATUS(MEM_VIRT
),
1753 MODE_STATUS(NOCLOCK
),
1754 MODE_STATUS(CLOCK_HIGH
),
1755 MODE_STATUS(CLOCK_LOW
),
1756 MODE_STATUS(CLOCK_RANGE
),
1757 MODE_STATUS(BAD_HVALUE
),
1758 MODE_STATUS(BAD_VVALUE
),
1759 MODE_STATUS(BAD_VSCAN
),
1760 MODE_STATUS(HSYNC_NARROW
),
1761 MODE_STATUS(HSYNC_WIDE
),
1762 MODE_STATUS(HBLANK_NARROW
),
1763 MODE_STATUS(HBLANK_WIDE
),
1764 MODE_STATUS(VSYNC_NARROW
),
1765 MODE_STATUS(VSYNC_WIDE
),
1766 MODE_STATUS(VBLANK_NARROW
),
1767 MODE_STATUS(VBLANK_WIDE
),
1769 MODE_STATUS(INTERLACE_WIDTH
),
1770 MODE_STATUS(ONE_WIDTH
),
1771 MODE_STATUS(ONE_HEIGHT
),
1772 MODE_STATUS(ONE_SIZE
),
1773 MODE_STATUS(NO_REDUCED
),
1774 MODE_STATUS(NO_STEREO
),
1775 MODE_STATUS(NO_420
),
1783 const char *drm_get_mode_status_name(enum drm_mode_status status
)
1785 int index
= status
+ 3;
1787 if (WARN_ON(index
< 0 || index
>= ARRAY_SIZE(drm_mode_status_names
)))
1790 return drm_mode_status_names
[index
];
1794 * drm_mode_prune_invalid - remove invalid modes from mode list
1796 * @mode_list: list of modes to check
1797 * @verbose: be verbose about it
1799 * This helper function can be used to prune a display mode list after
1800 * validation has been completed. All modes whose status is not MODE_OK will be
1801 * removed from the list, and if @verbose the status code and mode name is also
1804 void drm_mode_prune_invalid(struct drm_device
*dev
,
1805 struct list_head
*mode_list
, bool verbose
)
1807 struct drm_display_mode
*mode
, *t
;
1809 list_for_each_entry_safe(mode
, t
, mode_list
, head
) {
1810 if (mode
->status
!= MODE_OK
) {
1811 list_del(&mode
->head
);
1812 if (mode
->type
& DRM_MODE_TYPE_USERDEF
) {
1813 drm_warn(dev
, "User-defined mode not supported: "
1814 DRM_MODE_FMT
"\n", DRM_MODE_ARG(mode
));
1817 drm_dbg_kms(dev
, "Rejected mode: " DRM_MODE_FMT
" (%s)\n",
1818 DRM_MODE_ARG(mode
), drm_get_mode_status_name(mode
->status
));
1820 drm_mode_destroy(dev
, mode
);
1824 EXPORT_SYMBOL(drm_mode_prune_invalid
);
1827 * drm_mode_compare - compare modes for favorability
1829 * @lh_a: list_head for first mode
1830 * @lh_b: list_head for second mode
1832 * Compare two modes, given by @lh_a and @lh_b, returning a value indicating
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.
1839 static int drm_mode_compare(void *priv
, const struct list_head
*lh_a
,
1840 const struct list_head
*lh_b
)
1842 struct drm_display_mode
*a
= list_entry(lh_a
, struct drm_display_mode
, head
);
1843 struct drm_display_mode
*b
= list_entry(lh_b
, struct drm_display_mode
, head
);
1846 diff
= ((b
->type
& DRM_MODE_TYPE_PREFERRED
) != 0) -
1847 ((a
->type
& DRM_MODE_TYPE_PREFERRED
) != 0);
1850 diff
= b
->hdisplay
* b
->vdisplay
- a
->hdisplay
* a
->vdisplay
;
1854 diff
= drm_mode_vrefresh(b
) - drm_mode_vrefresh(a
);
1858 diff
= b
->clock
- a
->clock
;
1863 * drm_mode_sort - sort mode list
1864 * @mode_list: list of drm_display_mode structures to sort
1866 * Sort @mode_list by favorability, moving good modes to the head of the list.
1868 void drm_mode_sort(struct list_head
*mode_list
)
1870 list_sort(NULL
, mode_list
, drm_mode_compare
);
1872 EXPORT_SYMBOL(drm_mode_sort
);
1875 * drm_connector_list_update - update the mode list for the connector
1876 * @connector: the connector to update
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.
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.
1885 void drm_connector_list_update(struct drm_connector
*connector
)
1887 struct drm_display_mode
*pmode
, *pt
;
1889 WARN_ON(!mutex_is_locked(&connector
->dev
->mode_config
.mutex
));
1891 list_for_each_entry_safe(pmode
, pt
, &connector
->probed_modes
, head
) {
1892 struct drm_display_mode
*mode
;
1893 bool found_it
= false;
1895 /* go through current modes checking for the new probed mode */
1896 list_for_each_entry(mode
, &connector
->modes
, head
) {
1897 if (!drm_mode_equal(pmode
, mode
))
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.
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.
1914 if (mode
->status
== MODE_STALE
) {
1915 drm_mode_copy(mode
, pmode
);
1916 } else if ((mode
->type
& DRM_MODE_TYPE_PREFERRED
) == 0 &&
1917 (pmode
->type
& DRM_MODE_TYPE_PREFERRED
) != 0) {
1918 pmode
->type
|= mode
->type
;
1919 drm_mode_copy(mode
, pmode
);
1921 mode
->type
|= pmode
->type
;
1924 list_del(&pmode
->head
);
1925 drm_mode_destroy(connector
->dev
, pmode
);
1930 list_move_tail(&pmode
->head
, &connector
->modes
);
1934 EXPORT_SYMBOL(drm_connector_list_update
);
1936 static int drm_mode_parse_cmdline_bpp(const char *str
, char **end_ptr
,
1937 struct drm_cmdline_mode
*mode
)
1945 bpp
= simple_strtol(str
, end_ptr
, 10);
1946 if (*end_ptr
== str
)
1950 mode
->bpp_specified
= true;
1955 static int drm_mode_parse_cmdline_refresh(const char *str
, char **end_ptr
,
1956 struct drm_cmdline_mode
*mode
)
1958 unsigned int refresh
;
1964 refresh
= simple_strtol(str
, end_ptr
, 10);
1965 if (*end_ptr
== str
)
1968 mode
->refresh
= refresh
;
1969 mode
->refresh_specified
= true;
1974 static int drm_mode_parse_cmdline_extra(const char *str
, int length
,
1976 const struct drm_connector
*connector
,
1977 struct drm_cmdline_mode
*mode
)
1981 for (i
= 0; i
< length
; i
++) {
1987 mode
->interlace
= true;
1993 mode
->margins
= true;
1996 if (mode
->force
!= DRM_FORCE_UNSPECIFIED
)
1999 if ((connector
->connector_type
!= DRM_MODE_CONNECTOR_DVII
) &&
2000 (connector
->connector_type
!= DRM_MODE_CONNECTOR_HDMIB
))
2001 mode
->force
= DRM_FORCE_ON
;
2003 mode
->force
= DRM_FORCE_ON_DIGITAL
;
2006 if (mode
->force
!= DRM_FORCE_UNSPECIFIED
)
2009 mode
->force
= DRM_FORCE_OFF
;
2012 if (mode
->force
!= DRM_FORCE_UNSPECIFIED
)
2015 mode
->force
= DRM_FORCE_ON
;
2025 static int drm_mode_parse_cmdline_res_mode(const char *str
, unsigned int length
,
2027 const struct drm_connector
*connector
,
2028 struct drm_cmdline_mode
*mode
)
2030 const char *str_start
= str
;
2031 bool rb
= false, cvt
= false;
2032 int xres
= 0, yres
= 0;
2036 xres
= simple_strtol(str
, &end_ptr
, 10);
2040 if (end_ptr
[0] != 'x')
2045 yres
= simple_strtol(str
, &end_ptr
, 10);
2049 remaining
= length
- (end_ptr
- str_start
);
2053 for (i
= 0; i
< remaining
; i
++) {
2054 switch (end_ptr
[i
]) {
2063 * Try to pass that to our extras parsing
2064 * function to handle the case where the
2065 * extras are directly after the resolution
2068 int ret
= drm_mode_parse_cmdline_extra(end_ptr
+ i
,
2089 static int drm_mode_parse_cmdline_int(const char *delim
, unsigned int *int_ret
)
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.
2103 *int_ret
= simple_strtol(value
, &endp
, 10);
2105 /* Make sure we have parsed something */
2112 static int drm_mode_parse_panel_orientation(const char *delim
,
2113 struct drm_cmdline_mode
*mode
)
2121 delim
= strchr(value
, ',');
2123 delim
= value
+ strlen(value
);
2125 if (!strncmp(value
, "normal", delim
- value
))
2126 mode
->panel_orientation
= DRM_MODE_PANEL_ORIENTATION_NORMAL
;
2127 else if (!strncmp(value
, "upside_down", delim
- value
))
2128 mode
->panel_orientation
= DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP
;
2129 else if (!strncmp(value
, "left_side_up", delim
- value
))
2130 mode
->panel_orientation
= DRM_MODE_PANEL_ORIENTATION_LEFT_UP
;
2131 else if (!strncmp(value
, "right_side_up", delim
- value
))
2132 mode
->panel_orientation
= DRM_MODE_PANEL_ORIENTATION_RIGHT_UP
;
2139 static int drm_mode_parse_tv_mode(const char *delim
,
2140 struct drm_cmdline_mode
*mode
)
2149 delim
= strchr(value
, ',');
2151 delim
= value
+ strlen(value
);
2153 ret
= drm_get_tv_mode_from_name(value
, delim
- value
);
2157 mode
->tv_mode_specified
= true;
2158 mode
->tv_mode
= ret
;
2163 static int drm_mode_parse_cmdline_options(const char *str
,
2165 const struct drm_connector
*connector
,
2166 struct drm_cmdline_mode
*mode
)
2168 unsigned int deg
, margin
, rotation
= 0;
2169 const char *delim
, *option
, *sep
;
2173 delim
= strchr(option
, '=');
2175 delim
= strchr(option
, ',');
2178 delim
= option
+ strlen(option
);
2181 if (!strncmp(option
, "rotate", delim
- option
)) {
2182 if (drm_mode_parse_cmdline_int(delim
, °
))
2187 rotation
|= DRM_MODE_ROTATE_0
;
2191 rotation
|= DRM_MODE_ROTATE_90
;
2195 rotation
|= DRM_MODE_ROTATE_180
;
2199 rotation
|= DRM_MODE_ROTATE_270
;
2205 } else if (!strncmp(option
, "reflect_x", delim
- option
)) {
2206 rotation
|= DRM_MODE_REFLECT_X
;
2207 } else if (!strncmp(option
, "reflect_y", delim
- option
)) {
2208 rotation
|= DRM_MODE_REFLECT_Y
;
2209 } else if (!strncmp(option
, "margin_right", delim
- option
)) {
2210 if (drm_mode_parse_cmdline_int(delim
, &margin
))
2213 mode
->tv_margins
.right
= margin
;
2214 } else if (!strncmp(option
, "margin_left", delim
- option
)) {
2215 if (drm_mode_parse_cmdline_int(delim
, &margin
))
2218 mode
->tv_margins
.left
= margin
;
2219 } else if (!strncmp(option
, "margin_top", delim
- option
)) {
2220 if (drm_mode_parse_cmdline_int(delim
, &margin
))
2223 mode
->tv_margins
.top
= margin
;
2224 } else if (!strncmp(option
, "margin_bottom", delim
- option
)) {
2225 if (drm_mode_parse_cmdline_int(delim
, &margin
))
2228 mode
->tv_margins
.bottom
= margin
;
2229 } else if (!strncmp(option
, "panel_orientation", delim
- option
)) {
2230 if (drm_mode_parse_panel_orientation(delim
, mode
))
2232 } else if (!strncmp(option
, "tv_mode", delim
- option
)) {
2233 if (drm_mode_parse_tv_mode(delim
, mode
))
2238 sep
= strchr(delim
, ',');
2242 if (rotation
&& freestanding
)
2245 if (!(rotation
& DRM_MODE_ROTATE_MASK
))
2246 rotation
|= DRM_MODE_ROTATE_0
;
2248 /* Make sure there is exactly one rotation defined */
2249 if (!is_power_of_2(rotation
& DRM_MODE_ROTATE_MASK
))
2252 mode
->rotation_reflection
= rotation
;
2257 struct drm_named_mode
{
2259 unsigned int pixel_clock_khz
;
2263 unsigned int tv_mode
;
2266 #define NAMED_MODE(_name, _pclk, _x, _y, _flags, _mode) \
2269 .pixel_clock_khz = _pclk, \
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
),
2283 static int drm_mode_parse_cmdline_named_mode(const char *name
,
2284 unsigned int name_end
,
2285 struct drm_cmdline_mode
*cmdline_mode
)
2292 /* If the name starts with a digit, it's not a named mode */
2293 if (isdigit(name
[0]))
2297 * If there's an equal sign in the name, the command-line
2298 * contains only an option and no mode.
2300 if (strnchr(name
, name_end
, '='))
2303 /* The connection status extras can be set without a mode. */
2304 if (name_end
== 1 &&
2305 (name
[0] == 'd' || name
[0] == 'D' || name
[0] == 'e'))
2309 * We're sure we're a named mode at this point, iterate over the
2310 * list of modes we're aware of.
2312 for (i
= 0; i
< ARRAY_SIZE(drm_named_modes
); i
++) {
2313 const struct drm_named_mode
*mode
= &drm_named_modes
[i
];
2316 ret
= str_has_prefix(name
, mode
->name
);
2317 if (ret
!= name_end
)
2320 strscpy(cmdline_mode
->name
, mode
->name
, sizeof(cmdline_mode
->name
));
2321 cmdline_mode
->pixel_clock
= mode
->pixel_clock_khz
;
2322 cmdline_mode
->xres
= mode
->xres
;
2323 cmdline_mode
->yres
= mode
->yres
;
2324 cmdline_mode
->interlace
= !!(mode
->flags
& DRM_MODE_FLAG_INTERLACE
);
2325 cmdline_mode
->tv_mode
= mode
->tv_mode
;
2326 cmdline_mode
->tv_mode_specified
= true;
2327 cmdline_mode
->specified
= true;
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
2341 * This parses @mode_option command line modeline for modes and options to
2342 * configure the connector.
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::
2347 * <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m][eDd]
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.
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.
2357 * True if a valid modeline has been parsed, false otherwise.
2359 bool drm_mode_parse_command_line_for_connector(const char *mode_option
,
2360 const struct drm_connector
*connector
,
2361 struct drm_cmdline_mode
*mode
)
2364 bool freestanding
= false, parse_extras
= false;
2365 unsigned int bpp_off
= 0, refresh_off
= 0, options_off
= 0;
2366 unsigned int mode_end
= 0;
2367 const char *bpp_ptr
= NULL
, *refresh_ptr
= NULL
, *extra_ptr
= NULL
;
2368 const char *options_ptr
= NULL
;
2369 char *bpp_end_ptr
= NULL
, *refresh_end_ptr
= NULL
;
2372 memset(mode
, 0, sizeof(*mode
));
2373 mode
->panel_orientation
= DRM_MODE_PANEL_ORIENTATION_UNKNOWN
;
2380 /* Locate the start of named options */
2381 options_ptr
= strchr(name
, ',');
2383 options_off
= options_ptr
- name
;
2385 options_off
= strlen(name
);
2387 /* Try to locate the bpp and refresh specifiers, if any */
2388 bpp_ptr
= strnchr(name
, options_off
, '-');
2389 while (bpp_ptr
&& !isdigit(bpp_ptr
[1]))
2390 bpp_ptr
= strnchr(bpp_ptr
+ 1, options_off
, '-');
2392 bpp_off
= bpp_ptr
- name
;
2394 refresh_ptr
= strnchr(name
, options_off
, '@');
2396 refresh_off
= refresh_ptr
- name
;
2398 /* Locate the end of the name / resolution, and parse it */
2401 } else if (refresh_ptr
) {
2402 mode_end
= refresh_off
;
2403 } else if (options_ptr
) {
2404 mode_end
= options_off
;
2405 parse_extras
= true;
2407 mode_end
= strlen(name
);
2408 parse_extras
= true;
2414 ret
= drm_mode_parse_cmdline_named_mode(name
, mode_end
, mode
);
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.
2422 if (ret
&& refresh_ptr
)
2425 /* No named mode? Check for a normal mode argument, e.g. 1024x768 */
2426 if (!mode
->specified
&& isdigit(name
[0])) {
2427 ret
= drm_mode_parse_cmdline_res_mode(name
, mode_end
,
2434 mode
->specified
= true;
2437 /* No mode? Check for freestanding extras and/or options */
2438 if (!mode
->specified
) {
2439 unsigned int len
= strlen(mode_option
);
2441 if (bpp_ptr
|| refresh_ptr
)
2442 return false; /* syntax error */
2444 if (len
== 1 || (len
>= 2 && mode_option
[1] == ','))
2445 extra_ptr
= mode_option
;
2447 options_ptr
= mode_option
- 1;
2449 freestanding
= true;
2453 ret
= drm_mode_parse_cmdline_bpp(bpp_ptr
, &bpp_end_ptr
, mode
);
2457 mode
->bpp_specified
= true;
2461 ret
= drm_mode_parse_cmdline_refresh(refresh_ptr
,
2462 &refresh_end_ptr
, mode
);
2466 mode
->refresh_specified
= true;
2470 * Locate the end of the bpp / refresh, and parse the extras
2473 if (bpp_ptr
&& refresh_ptr
)
2474 extra_ptr
= max(bpp_end_ptr
, refresh_end_ptr
);
2476 extra_ptr
= bpp_end_ptr
;
2477 else if (refresh_ptr
)
2478 extra_ptr
= refresh_end_ptr
;
2482 len
= options_ptr
- extra_ptr
;
2484 len
= strlen(extra_ptr
);
2486 ret
= drm_mode_parse_cmdline_extra(extra_ptr
, len
, freestanding
,
2493 ret
= drm_mode_parse_cmdline_options(options_ptr
+ 1,
2502 EXPORT_SYMBOL(drm_mode_parse_command_line_for_connector
);
2504 static struct drm_display_mode
*drm_named_mode(struct drm_device
*dev
,
2505 struct drm_cmdline_mode
*cmd
)
2509 for (i
= 0; i
< ARRAY_SIZE(drm_named_modes
); i
++) {
2510 const struct drm_named_mode
*named_mode
= &drm_named_modes
[i
];
2512 if (strcmp(cmd
->name
, named_mode
->name
))
2515 if (!cmd
->tv_mode_specified
)
2518 return drm_analog_tv_mode(dev
,
2519 named_mode
->tv_mode
,
2520 named_mode
->pixel_clock_khz
* 1000,
2523 named_mode
->flags
& DRM_MODE_FLAG_INTERLACE
);
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
2535 * Pointer to converted mode on success, NULL on error.
2537 struct drm_display_mode
*
2538 drm_mode_create_from_cmdline_mode(struct drm_device
*dev
,
2539 struct drm_cmdline_mode
*cmd
)
2541 struct drm_display_mode
*mode
;
2543 if (cmd
->xres
== 0 || cmd
->yres
== 0)
2546 if (strlen(cmd
->name
))
2547 mode
= drm_named_mode(dev
, cmd
);
2549 mode
= drm_cvt_mode(dev
,
2550 cmd
->xres
, cmd
->yres
,
2551 cmd
->refresh_specified
? cmd
->refresh
: 60,
2552 cmd
->rb
, cmd
->interlace
,
2555 mode
= drm_gtf_mode(dev
,
2556 cmd
->xres
, cmd
->yres
,
2557 cmd
->refresh_specified
? cmd
->refresh
: 60,
2563 mode
->type
|= DRM_MODE_TYPE_USERDEF
;
2564 /* fix up 1368x768: GFT/CVT can't express 1366 width due to alignment */
2565 if (cmd
->xres
== 1366)
2566 drm_mode_fixup_1366x768(mode
);
2567 drm_mode_set_crtcinfo(mode
, CRTC_INTERLACE_HALVE_V
);
2570 EXPORT_SYMBOL(drm_mode_create_from_cmdline_mode
);
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
2577 * Convert a drm_display_mode into a drm_mode_modeinfo structure to return to
2580 void drm_mode_convert_to_umode(struct drm_mode_modeinfo
*out
,
2581 const struct drm_display_mode
*in
)
2583 out
->clock
= in
->clock
;
2584 out
->hdisplay
= in
->hdisplay
;
2585 out
->hsync_start
= in
->hsync_start
;
2586 out
->hsync_end
= in
->hsync_end
;
2587 out
->htotal
= in
->htotal
;
2588 out
->hskew
= in
->hskew
;
2589 out
->vdisplay
= in
->vdisplay
;
2590 out
->vsync_start
= in
->vsync_start
;
2591 out
->vsync_end
= in
->vsync_end
;
2592 out
->vtotal
= in
->vtotal
;
2593 out
->vscan
= in
->vscan
;
2594 out
->vrefresh
= drm_mode_vrefresh(in
);
2595 out
->flags
= in
->flags
;
2596 out
->type
= in
->type
;
2598 switch (in
->picture_aspect_ratio
) {
2599 case HDMI_PICTURE_ASPECT_4_3
:
2600 out
->flags
|= DRM_MODE_FLAG_PIC_AR_4_3
;
2602 case HDMI_PICTURE_ASPECT_16_9
:
2603 out
->flags
|= DRM_MODE_FLAG_PIC_AR_16_9
;
2605 case HDMI_PICTURE_ASPECT_64_27
:
2606 out
->flags
|= DRM_MODE_FLAG_PIC_AR_64_27
;
2608 case HDMI_PICTURE_ASPECT_256_135
:
2609 out
->flags
|= DRM_MODE_FLAG_PIC_AR_256_135
;
2612 WARN(1, "Invalid aspect ratio (0%x) on mode\n",
2613 in
->picture_aspect_ratio
);
2615 case HDMI_PICTURE_ASPECT_NONE
:
2616 out
->flags
|= DRM_MODE_FLAG_PIC_AR_NONE
;
2620 strscpy_pad(out
->name
, in
->name
, sizeof(out
->name
));
2624 * drm_mode_convert_umode - convert a modeinfo into a drm_display_mode
2626 * @out: drm_display_mode to return to the user
2627 * @in: drm_mode_modeinfo to use
2629 * Convert a drm_mode_modeinfo into a drm_display_mode structure to return to
2633 * Zero on success, negative errno on failure.
2635 int drm_mode_convert_umode(struct drm_device
*dev
,
2636 struct drm_display_mode
*out
,
2637 const struct drm_mode_modeinfo
*in
)
2639 if (in
->clock
> INT_MAX
|| in
->vrefresh
> INT_MAX
)
2642 out
->clock
= in
->clock
;
2643 out
->hdisplay
= in
->hdisplay
;
2644 out
->hsync_start
= in
->hsync_start
;
2645 out
->hsync_end
= in
->hsync_end
;
2646 out
->htotal
= in
->htotal
;
2647 out
->hskew
= in
->hskew
;
2648 out
->vdisplay
= in
->vdisplay
;
2649 out
->vsync_start
= in
->vsync_start
;
2650 out
->vsync_end
= in
->vsync_end
;
2651 out
->vtotal
= in
->vtotal
;
2652 out
->vscan
= in
->vscan
;
2653 out
->flags
= in
->flags
;
2655 * Old xf86-video-vmware (possibly others too) used to
2656 * leave 'type' uninitialized. Just ignore any bits we
2657 * don't like. It's a just hint after all, and more
2658 * useful for the kernel->userspace direction anyway.
2660 out
->type
= in
->type
& DRM_MODE_TYPE_ALL
;
2661 strscpy_pad(out
->name
, in
->name
, sizeof(out
->name
));
2663 /* Clearing picture aspect ratio bits from out flags,
2664 * as the aspect-ratio information is not stored in
2665 * flags for kernel-mode, but in picture_aspect_ratio.
2667 out
->flags
&= ~DRM_MODE_FLAG_PIC_AR_MASK
;
2669 switch (in
->flags
& DRM_MODE_FLAG_PIC_AR_MASK
) {
2670 case DRM_MODE_FLAG_PIC_AR_4_3
:
2671 out
->picture_aspect_ratio
= HDMI_PICTURE_ASPECT_4_3
;
2673 case DRM_MODE_FLAG_PIC_AR_16_9
:
2674 out
->picture_aspect_ratio
= HDMI_PICTURE_ASPECT_16_9
;
2676 case DRM_MODE_FLAG_PIC_AR_64_27
:
2677 out
->picture_aspect_ratio
= HDMI_PICTURE_ASPECT_64_27
;
2679 case DRM_MODE_FLAG_PIC_AR_256_135
:
2680 out
->picture_aspect_ratio
= HDMI_PICTURE_ASPECT_256_135
;
2682 case DRM_MODE_FLAG_PIC_AR_NONE
:
2683 out
->picture_aspect_ratio
= HDMI_PICTURE_ASPECT_NONE
;
2689 out
->status
= drm_mode_validate_driver(dev
, out
);
2690 if (out
->status
!= MODE_OK
)
2693 drm_mode_set_crtcinfo(out
, CRTC_INTERLACE_HALVE_V
);
2699 * drm_mode_is_420_only - if a given videomode can be only supported in YCBCR420
2702 * @display: display under action
2703 * @mode: video mode to be tested.
2706 * true if the mode can be supported in YCBCR420 format
2709 bool drm_mode_is_420_only(const struct drm_display_info
*display
,
2710 const struct drm_display_mode
*mode
)
2712 u8 vic
= drm_match_cea_mode(mode
);
2714 return test_bit(vic
, display
->hdmi
.y420_vdb_modes
);
2716 EXPORT_SYMBOL(drm_mode_is_420_only
);
2719 * drm_mode_is_420_also - if a given videomode can be supported in YCBCR420
2720 * output format also (along with RGB/YCBCR444/422)
2722 * @display: display under action.
2723 * @mode: video mode to be tested.
2726 * true if the mode can be support YCBCR420 format
2729 bool drm_mode_is_420_also(const struct drm_display_info
*display
,
2730 const struct drm_display_mode
*mode
)
2732 u8 vic
= drm_match_cea_mode(mode
);
2734 return test_bit(vic
, display
->hdmi
.y420_cmdb_modes
);
2736 EXPORT_SYMBOL(drm_mode_is_420_also
);
2738 * drm_mode_is_420 - if a given videomode can be supported in YCBCR420
2741 * @display: display under action.
2742 * @mode: video mode to be tested.
2745 * true if the mode can be supported in YCBCR420 format
2748 bool drm_mode_is_420(const struct drm_display_info
*display
,
2749 const struct drm_display_mode
*mode
)
2751 return drm_mode_is_420_only(display
, mode
) ||
2752 drm_mode_is_420_also(display
, mode
);
2754 EXPORT_SYMBOL(drm_mode_is_420
);
2757 * drm_set_preferred_mode - Sets the preferred mode of a connector
2758 * @connector: connector whose mode list should be processed
2759 * @hpref: horizontal resolution of preferred mode
2760 * @vpref: vertical resolution of preferred mode
2762 * Marks a mode as preferred if it matches the resolution specified by @hpref
2765 void drm_set_preferred_mode(struct drm_connector
*connector
,
2766 int hpref
, int vpref
)
2768 struct drm_display_mode
*mode
;
2770 list_for_each_entry(mode
, &connector
->probed_modes
, head
) {
2771 if (mode
->hdisplay
== hpref
&&
2772 mode
->vdisplay
== vpref
)
2773 mode
->type
|= DRM_MODE_TYPE_PREFERRED
;
2776 EXPORT_SYMBOL(drm_set_preferred_mode
);