vmwaremodes.c revision 22f7e8e5
1/*
2 * Copyright 2007 by VMware, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Except as contained in this notice, the name of the copyright holder(s)
23 * and author(s) shall not be used in advertising or otherwise to promote
24 * the sale, use or other dealings in this Software without prior written
25 * authorization from the copyright holder(s) and author(s).
26 */
27
28/*
29 * vmwaremodes.c --
30 *
31 *      Provide additional modes for the driver.
32 */
33
34#ifdef HAVE_CONFIG_H
35#include "config.h"
36#endif
37#include "xf86.h"
38#ifdef HAVE_XORG_SERVER_1_2_0
39#include <xf86Modes.h>
40#endif
41#include "vm_basic_types.h"
42#include "vmware.h"
43
44#ifndef M_T_DRIVER
45# define M_T_DRIVER  0x40	/* Supplied by the driver (EDID, etc) */
46#endif
47
48#define MODEPREFIX NULL, NULL, NULL, 0, M_T_DRIVER
49#define MODESUFFIX 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,FALSE,FALSE,0,NULL,0,0.0,0.0
50
51#define VMW_DEFLT_MODE_NAME "vmwlegacy-default-%dx%d"
52
53/*
54 *-----------------------------------------------------------------------------
55 *
56 * vmwareAddDefaultMode --
57 *
58 *    Add a default mode with the current screen dimensions.
59 *
60 * Results:
61 *    The default mode.
62 *
63 * Side effects:
64 *    None.
65 *
66 *-----------------------------------------------------------------------------
67 */
68
69void
70vmwareAddDefaultMode(ScrnInfoPtr pScrn, uint32 dwidth, uint32 dheight)
71{
72    DisplayModePtr *monitorModes = &pScrn->monitor->Modes;
73    DisplayModePtr modes = NULL;
74
75    if (monitorModes == NULL || *monitorModes == NULL) {
76	goto out_err;
77    }
78
79#ifdef HAVE_XORG_SERVER_1_2_0
80    if (dwidth && dheight) {
81	MonPtr monitor = pScrn->monitor;
82	DisplayModePtr mode = NULL;
83	DisplayModeRec dynamic =
84	    { MODEPREFIX, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, MODESUFFIX };
85	unsigned dispModeCount = 0;
86	char **dispModeList;
87	char *dynModeName;
88	char name[80];
89	VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
90
91	/* First, add the default mode name to the display mode
92	 * requests.
93	 */
94
95	snprintf(name, sizeof(name), VMW_DEFLT_MODE_NAME, dwidth, dheight);
96
97	dynModeName = xnfstrdup(name);
98	if (!dynModeName || !pScrn->display)
99	    goto out_err;
100
101	if (pScrn->display->modes) {
102	    dispModeList = pScrn->display->modes;
103	    while(*dispModeList)
104		dispModeList++;
105	    dispModeCount = (unsigned)(((size_t)dispModeList -
106	                                (size_t)pScrn->display->modes) /
107	                               sizeof(*dispModeList));
108	}
109
110	dispModeList = xnfcalloc(dispModeCount + 2, sizeof(*dispModeList));
111	if (!dispModeList)
112	    goto out_err;
113
114	memcpy(dispModeList, pScrn->display->modes,
115	       dispModeCount * sizeof(*dispModeList));
116	dispModeList[dispModeCount] = dynModeName;
117	pScrn->display->modes = dispModeList;
118
119	/* Then, add the default mode itself.
120	 */
121
122	dynamic.name = name;
123	dynamic.HDisplay = dwidth;
124	dynamic.HSyncStart = dynamic.HDisplay + 1;
125	dynamic.HSyncEnd = dynamic.HSyncStart + 1;
126	dynamic.HTotal = dynamic.HSyncEnd * 5 / 4;
127	dynamic.VDisplay = dheight;
128	dynamic.VSyncStart = dynamic.VDisplay + 1;
129	dynamic.VSyncEnd = dynamic.VSyncStart + 1;
130	dynamic.VTotal = dynamic.VSyncEnd + 1;
131	if (monitor->nVrefresh > 0)
132	    dynamic.VRefresh = monitor->vrefresh[0].lo;
133	else
134	    dynamic.VRefresh = 60;
135	dynamic.Clock = dynamic.VRefresh * dynamic.VTotal *
136	    dynamic.HTotal / 1000;
137	mode = xf86DuplicateMode(&dynamic);
138	modes = xf86ModesAdd(modes, mode);
139
140	if (dispModeCount == 0) {
141
142	    /*
143	     * Set up a large virtual size, so that we allow also
144	     * setting modes larger than the initial mode.
145	     *
146	     * We might also want to consider the case where
147	     * dispModeCount != 0, but the requested display modes
148	     * are not available. This is sufficient for now.
149	     */
150
151	    if (pScrn->display->virtualX == 0)
152		pScrn->display->virtualX = pVMWARE->maxWidth;
153	    if (pScrn->display->virtualY == 0)
154		pScrn->display->virtualY = pVMWARE->maxHeight;
155	}
156    }
157
158    *monitorModes = xf86ModesAdd(*monitorModes, modes);
159#else
160    (void) modes;
161#endif
162    return;
163  out_err:
164    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to add default mode.");
165}
166