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