xref: /rk3399_rockchip-uboot/drivers/video/drm/drm_modes.c (revision 2cb5133363e2b327b3561dadef1f7aa0d0972d49)
1e022625eSWyon Bi // SPDX-License-Identifier: GPL-2.0+
2e022625eSWyon Bi /*
3e022625eSWyon Bi  * Copyright © 1997-2003 by The XFree86 Project, Inc.
4e022625eSWyon Bi  * Copyright © 2007 Dave Airlie
5e022625eSWyon Bi  * Copyright © 2007-2008 Intel Corporation
6e022625eSWyon Bi  *   Jesse Barnes <jesse.barnes@intel.com>
7e022625eSWyon Bi  * Copyright 2005-2006 Luc Verhaegen
8e022625eSWyon Bi  * Copyright (c) 2001, Andy Ritger  aritger@nvidia.com
9e022625eSWyon Bi  *
10e022625eSWyon Bi  * Permission is hereby granted, free of charge, to any person obtaining a
11e022625eSWyon Bi  * copy of this software and associated documentation files (the "Software"),
12e022625eSWyon Bi  * to deal in the Software without restriction, including without limitation
13e022625eSWyon Bi  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14e022625eSWyon Bi  * and/or sell copies of the Software, and to permit persons to whom the
15e022625eSWyon Bi  * Software is furnished to do so, subject to the following conditions:
16e022625eSWyon Bi  *
17e022625eSWyon Bi  * The above copyright notice and this permission notice shall be included in
18e022625eSWyon Bi  * all copies or substantial portions of the Software.
19e022625eSWyon Bi  *
20e022625eSWyon Bi  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21e022625eSWyon Bi  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22e022625eSWyon Bi  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
23e022625eSWyon Bi  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
24e022625eSWyon Bi  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
25e022625eSWyon Bi  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
26e022625eSWyon Bi  * OTHER DEALINGS IN THE SOFTWARE.
27e022625eSWyon Bi  *
28e022625eSWyon Bi  * Except as contained in this notice, the name of the copyright holder(s)
29e022625eSWyon Bi  * and author(s) shall not be used in advertising or otherwise to promote
30e022625eSWyon Bi  * the sale, use or other dealings in this Software without prior written
31e022625eSWyon Bi  * authorization from the copyright holder(s) and author(s).
32e022625eSWyon Bi  */
33e022625eSWyon Bi 
34e022625eSWyon Bi #include <common.h>
35e022625eSWyon Bi #include <drm_modes.h>
36e022625eSWyon Bi #include <linux/compat.h>
37e022625eSWyon Bi #include <malloc.h>
38e022625eSWyon Bi 
39e022625eSWyon Bi #define PICOS2KHZ(a)	(1000000000UL / (a))
40e022625eSWyon Bi #define KHZ2PICOS(a)	(1000000000UL / (a))
41e022625eSWyon Bi 
42e022625eSWyon Bi /**
43e022625eSWyon Bi  * drm_mode_create - create a new display mode
44e022625eSWyon Bi  *
45e022625eSWyon Bi  * Create a new, cleared drm_display_mode.
46e022625eSWyon Bi  *
47e022625eSWyon Bi  * Returns:
48e022625eSWyon Bi  * Pointer to new mode on success, NULL on error.
49e022625eSWyon Bi  */
50e022625eSWyon Bi struct drm_display_mode *drm_mode_create(void)
51e022625eSWyon Bi {
52e022625eSWyon Bi 	struct drm_display_mode *nmode;
53e022625eSWyon Bi 
54e022625eSWyon Bi 	nmode = malloc(sizeof(struct drm_display_mode));
55e022625eSWyon Bi 	memset(nmode, 0, sizeof(struct drm_display_mode));
56e022625eSWyon Bi 	if (!nmode)
57e022625eSWyon Bi 		return NULL;
58e022625eSWyon Bi 
59e022625eSWyon Bi 	return nmode;
60e022625eSWyon Bi }
61e022625eSWyon Bi 
62e022625eSWyon Bi /**
63e022625eSWyon Bi  * drm_mode_destroy - remove a mode
64e022625eSWyon Bi  * @mode: mode to remove
65e022625eSWyon Bi  */
66e022625eSWyon Bi void drm_mode_destroy(struct drm_display_mode *mode)
67e022625eSWyon Bi {
68e022625eSWyon Bi 	if (!mode)
69e022625eSWyon Bi 		return;
70e022625eSWyon Bi 
71e022625eSWyon Bi 	kfree(mode);
72e022625eSWyon Bi }
73e022625eSWyon Bi 
74e022625eSWyon Bi static bool drm_mode_match_timings(const struct drm_display_mode *mode1,
75e022625eSWyon Bi 				   const struct drm_display_mode *mode2)
76e022625eSWyon Bi {
77e022625eSWyon Bi 	return mode1->hdisplay == mode2->hdisplay &&
78e022625eSWyon Bi 	       mode1->hsync_start == mode2->hsync_start &&
79e022625eSWyon Bi 	       mode1->hsync_end == mode2->hsync_end &&
80e022625eSWyon Bi 	       mode1->htotal == mode2->htotal &&
81e022625eSWyon Bi 	       mode1->hskew == mode2->hskew &&
82e022625eSWyon Bi 	       mode1->vdisplay == mode2->vdisplay &&
83e022625eSWyon Bi 	       mode1->vsync_start == mode2->vsync_start &&
84e022625eSWyon Bi 	       mode1->vsync_end == mode2->vsync_end &&
85e022625eSWyon Bi 	       mode1->vtotal == mode2->vtotal &&
86e022625eSWyon Bi 	       mode1->vscan == mode2->vscan;
87e022625eSWyon Bi }
88e022625eSWyon Bi 
89e022625eSWyon Bi static bool drm_mode_match_clock(const struct drm_display_mode *mode1,
90e022625eSWyon Bi 				 const struct drm_display_mode *mode2)
91e022625eSWyon Bi {
92e022625eSWyon Bi 	/*
93e022625eSWyon Bi 	 * do clock check convert to PICOS
94e022625eSWyon Bi 	 * so fb modes get matched the same
95e022625eSWyon Bi 	 */
96e022625eSWyon Bi 	if (mode1->clock && mode2->clock)
97e022625eSWyon Bi 		return KHZ2PICOS(mode1->clock) == KHZ2PICOS(mode2->clock);
98e022625eSWyon Bi 	else
99e022625eSWyon Bi 		return mode1->clock == mode2->clock;
100e022625eSWyon Bi }
101e022625eSWyon Bi 
102e022625eSWyon Bi static bool drm_mode_match_flags(const struct drm_display_mode *mode1,
103e022625eSWyon Bi 				 const struct drm_display_mode *mode2)
104e022625eSWyon Bi {
105e022625eSWyon Bi 	return (mode1->flags & ~DRM_MODE_FLAG_3D_MASK) ==
106e022625eSWyon Bi 	       (mode2->flags & ~DRM_MODE_FLAG_3D_MASK);
107e022625eSWyon Bi }
108e022625eSWyon Bi 
109e022625eSWyon Bi static bool drm_mode_match_3d_flags(const struct drm_display_mode *mode1,
110e022625eSWyon Bi 				    const struct drm_display_mode *mode2)
111e022625eSWyon Bi {
112e022625eSWyon Bi 	return (mode1->flags & DRM_MODE_FLAG_3D_MASK) ==
113e022625eSWyon Bi 	       (mode2->flags & DRM_MODE_FLAG_3D_MASK);
114e022625eSWyon Bi }
115e022625eSWyon Bi 
116e022625eSWyon Bi static bool drm_mode_match_aspect_ratio(const struct drm_display_mode *mode1,
117e022625eSWyon Bi 					const struct drm_display_mode *mode2)
118e022625eSWyon Bi {
119e022625eSWyon Bi 	return mode1->picture_aspect_ratio == mode2->picture_aspect_ratio;
120e022625eSWyon Bi }
121e022625eSWyon Bi 
122e022625eSWyon Bi /**
123e022625eSWyon Bi  * drm_mode_match - test modes for (partial) equality
124e022625eSWyon Bi  * @mode1: first mode
125e022625eSWyon Bi  * @mode2: second mode
126e022625eSWyon Bi  * @match_flags: which parts need to match (DRM_MODE_MATCH_*)
127e022625eSWyon Bi  *
128e022625eSWyon Bi  * Check to see if @mode1 and @mode2 are equivalent.
129e022625eSWyon Bi  *
130e022625eSWyon Bi  * Returns:
131e022625eSWyon Bi  * True if the modes are (partially) equal, false otherwise.
132e022625eSWyon Bi  */
133e022625eSWyon Bi bool drm_mode_match(const struct drm_display_mode *mode1,
134e022625eSWyon Bi 		    const struct drm_display_mode *mode2,
135e022625eSWyon Bi 		    unsigned int match_flags)
136e022625eSWyon Bi {
137e022625eSWyon Bi 	if (!mode1 && !mode2)
138e022625eSWyon Bi 		return true;
139e022625eSWyon Bi 
140e022625eSWyon Bi 	if (!mode1 || !mode2)
141e022625eSWyon Bi 		return false;
142e022625eSWyon Bi 
143e022625eSWyon Bi 	if (match_flags & DRM_MODE_MATCH_TIMINGS &&
144e022625eSWyon Bi 	    !drm_mode_match_timings(mode1, mode2))
145e022625eSWyon Bi 		return false;
146e022625eSWyon Bi 
147e022625eSWyon Bi 	if (match_flags & DRM_MODE_MATCH_CLOCK &&
148e022625eSWyon Bi 	    !drm_mode_match_clock(mode1, mode2))
149e022625eSWyon Bi 		return false;
150e022625eSWyon Bi 
151e022625eSWyon Bi 	if (match_flags & DRM_MODE_MATCH_FLAGS &&
152e022625eSWyon Bi 	    !drm_mode_match_flags(mode1, mode2))
153e022625eSWyon Bi 		return false;
154e022625eSWyon Bi 
155e022625eSWyon Bi 	if (match_flags & DRM_MODE_MATCH_3D_FLAGS &&
156e022625eSWyon Bi 	    !drm_mode_match_3d_flags(mode1, mode2))
157e022625eSWyon Bi 		return false;
158e022625eSWyon Bi 
159e022625eSWyon Bi 	if (match_flags & DRM_MODE_MATCH_ASPECT_RATIO &&
160e022625eSWyon Bi 	    !drm_mode_match_aspect_ratio(mode1, mode2))
161e022625eSWyon Bi 		return false;
162e022625eSWyon Bi 
163e022625eSWyon Bi 	return true;
164e022625eSWyon Bi }
165e022625eSWyon Bi 
166e022625eSWyon Bi /**
167e022625eSWyon Bi  * drm_mode_equal - test modes for equality
168e022625eSWyon Bi  * @mode1: first mode
169e022625eSWyon Bi  * @mode2: second mode
170e022625eSWyon Bi  *
171e022625eSWyon Bi  * Check to see if @mode1 and @mode2 are equivalent.
172e022625eSWyon Bi  *
173e022625eSWyon Bi  * Returns:
174e022625eSWyon Bi  * True if the modes are equal, false otherwise.
175e022625eSWyon Bi  */
176e022625eSWyon Bi bool drm_mode_equal(const struct drm_display_mode *mode1,
177e022625eSWyon Bi 		    const struct drm_display_mode *mode2)
178e022625eSWyon Bi {
179e022625eSWyon Bi 	return drm_mode_match(mode1, mode2,
180e022625eSWyon Bi 			      DRM_MODE_MATCH_TIMINGS |
181e022625eSWyon Bi 			      DRM_MODE_MATCH_CLOCK |
182e022625eSWyon Bi 			      DRM_MODE_MATCH_FLAGS |
183e022625eSWyon Bi 			      DRM_MODE_MATCH_3D_FLAGS |
184e022625eSWyon Bi 			      DRM_MODE_MATCH_ASPECT_RATIO);
185e022625eSWyon Bi }
186*2cb51333SDamon Ding 
187*2cb51333SDamon Ding /**
188*2cb51333SDamon Ding  * drm_display_mode_to_videomode - fill in @vm using @dmode,
189*2cb51333SDamon Ding  * @dmode: drm_display_mode structure to use as source
190*2cb51333SDamon Ding  * @vm: videomode structure to use as destination
191*2cb51333SDamon Ding  *
192*2cb51333SDamon Ding  * Fills out @vm using the display mode specified in @dmode.
193*2cb51333SDamon Ding  */
194*2cb51333SDamon Ding void drm_display_mode_to_videomode(const struct drm_display_mode *dmode,
195*2cb51333SDamon Ding 				   struct videomode *vm)
196*2cb51333SDamon Ding {
197*2cb51333SDamon Ding 	vm->hactive = dmode->hdisplay;
198*2cb51333SDamon Ding 	vm->hfront_porch = dmode->hsync_start - dmode->hdisplay;
199*2cb51333SDamon Ding 	vm->hsync_len = dmode->hsync_end - dmode->hsync_start;
200*2cb51333SDamon Ding 	vm->hback_porch = dmode->htotal - dmode->hsync_end;
201*2cb51333SDamon Ding 
202*2cb51333SDamon Ding 	vm->vactive = dmode->vdisplay;
203*2cb51333SDamon Ding 	vm->vfront_porch = dmode->vsync_start - dmode->vdisplay;
204*2cb51333SDamon Ding 	vm->vsync_len = dmode->vsync_end - dmode->vsync_start;
205*2cb51333SDamon Ding 	vm->vback_porch = dmode->vtotal - dmode->vsync_end;
206*2cb51333SDamon Ding 
207*2cb51333SDamon Ding 	vm->pixelclock = dmode->clock * 1000;
208*2cb51333SDamon Ding 
209*2cb51333SDamon Ding 	vm->flags = 0;
210*2cb51333SDamon Ding 	if (dmode->flags & DRM_MODE_FLAG_PHSYNC)
211*2cb51333SDamon Ding 		vm->flags |= DISPLAY_FLAGS_HSYNC_HIGH;
212*2cb51333SDamon Ding 	else if (dmode->flags & DRM_MODE_FLAG_NHSYNC)
213*2cb51333SDamon Ding 		vm->flags |= DISPLAY_FLAGS_HSYNC_LOW;
214*2cb51333SDamon Ding 	if (dmode->flags & DRM_MODE_FLAG_PVSYNC)
215*2cb51333SDamon Ding 		vm->flags |= DISPLAY_FLAGS_VSYNC_HIGH;
216*2cb51333SDamon Ding 	else if (dmode->flags & DRM_MODE_FLAG_NVSYNC)
217*2cb51333SDamon Ding 		vm->flags |= DISPLAY_FLAGS_VSYNC_LOW;
218*2cb51333SDamon Ding 	if (dmode->flags & DRM_MODE_FLAG_INTERLACE)
219*2cb51333SDamon Ding 		vm->flags |= DISPLAY_FLAGS_INTERLACED;
220*2cb51333SDamon Ding 	if (dmode->flags & DRM_MODE_FLAG_DBLSCAN)
221*2cb51333SDamon Ding 		vm->flags |= DISPLAY_FLAGS_DOUBLESCAN;
222*2cb51333SDamon Ding 	if (dmode->flags & DRM_MODE_FLAG_DBLCLK)
223*2cb51333SDamon Ding 		vm->flags |= DISPLAY_FLAGS_DOUBLECLK;
224*2cb51333SDamon Ding }
225