VirtualBox

source: vbox/trunk/src/VBox/Additions/x11/vboxvideo/edid.c

Last change on this file was 98103, checked in by vboxsync, 16 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.6 KB
Line 
1/* $Id: edid.c 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 *
4 * Linux Additions X11 graphics driver, EDID construction
5 */
6
7/*
8 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
9 * This file is based on drmmode_display.c from the X.Org xf86-video-intel
10 * driver with the following copyright notice:
11 *
12 * Copyright © 2007 Red Hat, Inc.
13 *
14 * Permission is hereby granted, free of charge, to any person obtaining a
15 * copy of this software and associated documentation files (the "Software"),
16 * to deal in the Software without restriction, including without limitation
17 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 * and/or sell copies of the Software, and to permit persons to whom the
19 * Software is furnished to do so, subject to the following conditions:
20 *
21 * The above copyright notice and this permission notice (including the next
22 * paragraph) shall be included in all copies or substantial portions of the
23 * Software.
24 *
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
28 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31 * SOFTWARE.
32 *
33 * Authors:
34 * Dave Airlie <airlied@redhat.com>
35 * Michael Thayer <michael.thayer@oracle.com>
36 */
37
38#include "misc.h"
39#include "xf86DDC.h"
40#include "xf86Crtc.h"
41#include "vboxvideo.h"
42
43enum { EDID_SIZE = 128 };
44
45const unsigned char g_acszEDIDBase[EDID_SIZE] =
46{
47 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, /* header */
48 0x58, 0x58, /* manufacturer (VBX) */
49 0x00, 0x00, /* product code */
50 0x00, 0x00,0x00, 0x00, /* serial number goes here */
51 0x01, /* week of manufacture */
52 0x00, /* year of manufacture */
53 0x01, 0x03, /* EDID version */
54 0x80, /* capabilities - digital */
55 0x00, /* horiz. res in cm, zero for projectors */
56 0x00, /* vert. res in cm */
57 0x78, /* display gamma (120 == 2.2). Should we ask the host for this? */
58 0xEE, /* features (standby, suspend, off, RGB, standard colour space,
59 * preferred timing mode) */
60 0xEE, 0x91, 0xA3, 0x54, 0x4C, 0x99, 0x26, 0x0F, 0x50, 0x54,
61 /* chromaticity for standard colour space - should we ask the host? */
62 0x00, 0x00, 0x00, /* no default timings */
63 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
64 0x01, 0x01, 0x01, 0x01, /* no standard timings */
65 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
66 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* descriptor block 1 goes here */
67 0x00, 0x00, 0x00, 0xFD, 0x00, /* descriptor block 2, monitor ranges */
68 0x00, 0xC8, 0x00, 0xC8, 0x64, 0x00, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20,
69 0x20, /* 0-200Hz vertical, 0-200KHz horizontal, 1000MHz pixel clock */
70 0x00, 0x00, 0x00, 0xFC, 0x00, /* descriptor block 3, monitor name */
71 'V', 'B', 'O', 'X', ' ', 'm', 'o', 'n', 'i', 't', 'o', 'r', '\n',
72 0x00, 0x00, 0x00, 0x10, 0x00, /* descriptor block 4: dummy data */
73 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
74 0x20,
75 0x00, /* number of extensions */
76 0x00 /* checksum goes here */
77};
78
79static void fillDescBlockTimings(unsigned char *pchDescBlock,
80 DisplayModePtr mode)
81{
82 struct detailed_timings timing;
83
84 timing.clock = mode->Clock * 1000;
85 timing.h_active = mode->HDisplay;
86 timing.h_blanking = mode->HTotal - mode->HDisplay;
87 timing.v_active = mode->VDisplay;
88 timing.v_blanking = mode->VTotal - mode->VDisplay;
89 timing.h_sync_off = mode->HSyncStart - mode->HDisplay;
90 timing.h_sync_width = mode->HSyncEnd - mode->HSyncStart;
91 timing.v_sync_off = mode->VSyncStart - mode->VDisplay;
92 timing.v_sync_width = mode->VSyncEnd - mode->VSyncStart;
93 pchDescBlock[0] = (timing.clock / 10000) & 0xff;
94 pchDescBlock[1] = (timing.clock / 10000) >> 8;
95 pchDescBlock[2] = timing.h_active & 0xff;
96 pchDescBlock[3] = timing.h_blanking & 0xff;
97 pchDescBlock[4] = (timing.h_active >> 4) & 0xf0;
98 pchDescBlock[4] |= (timing.h_blanking >> 8) & 0xf;
99 pchDescBlock[5] = timing.v_active & 0xff;
100 pchDescBlock[6] = timing.v_blanking & 0xff;
101 pchDescBlock[7] = (timing.v_active >> 4) & 0xf0;
102 pchDescBlock[7] |= (timing.v_blanking >> 8) & 0xf;
103 pchDescBlock[8] = timing.h_sync_off & 0xff;
104 pchDescBlock[9] = timing.h_sync_width & 0xff;
105 pchDescBlock[10] = (timing.v_sync_off << 4) & 0xf0;
106 pchDescBlock[10] |= timing.v_sync_width & 0xf;
107 pchDescBlock[11] = (timing.h_sync_off >> 2) & 0xC0;
108 pchDescBlock[11] |= (timing.h_sync_width >> 4) & 0x30;
109 pchDescBlock[11] |= (timing.v_sync_off >> 2) & 0xC;
110 pchDescBlock[11] |= (timing.v_sync_width >> 4) & 0x3;
111 pchDescBlock[12] = pchDescBlock[13] = pchDescBlock[14]
112 = pchDescBlock[15] = pchDescBlock[16]
113 = pchDescBlock[17] = 0;
114}
115
116
117static void setEDIDChecksum(unsigned char *pch)
118{
119 unsigned i, sum = 0;
120 for (i = 0; i < EDID_SIZE - 1; ++i)
121 sum += pch[i];
122 pch[EDID_SIZE - 1] = (0x100 - (sum & 0xFF)) & 0xFF;
123}
124
125
126/**
127 * Construct an EDID for an output given a preferred mode. The main reason for
128 * doing this is to confound gnome-settings-deamon which tries to reset the
129 * last mode configuration if the same monitors are plugged in again, which is
130 * a reasonable thing to do but not what we want in a VM. We evily store
131 * the (empty) raw EDID data at the end of the structure so that it gets
132 * freed automatically along with the structure.
133 */
134Bool VBOXEDIDSet(xf86OutputPtr output, DisplayModePtr pmode)
135{
136 unsigned char *pch, *pchEDID;
137 xf86MonPtr pEDIDMon;
138
139 pch = calloc(1, sizeof(xf86Monitor) + EDID_SIZE);
140 if (!pch)
141 {
142 xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
143 "Can't allocate memory for EDID structure.\n");
144 return FALSE;
145 }
146 pchEDID = pch + sizeof(xf86Monitor);
147 memcpy(pchEDID, g_acszEDIDBase, EDID_SIZE);
148 pchEDID[12] = pmode->HDisplay & 0xff;
149 pchEDID[13] = pmode->HDisplay >> 8;
150 pchEDID[14] = pmode->VDisplay & 0xff;
151 pchEDID[15] = pmode->VDisplay >> 8;
152 fillDescBlockTimings(pchEDID + 54, pmode);
153 setEDIDChecksum(pchEDID);
154 pEDIDMon = xf86InterpretEDID(output->scrn->scrnIndex, pchEDID);
155 if (!pEDIDMon)
156 {
157 free(pch);
158 return FALSE;
159 }
160 memcpy(pch, pEDIDMon, sizeof(xf86Monitor));
161 free(pEDIDMon);
162 pEDIDMon = (xf86MonPtr)pch;
163 xf86OutputSetEDID(output, pEDIDMon);
164 return TRUE;
165}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use