vmwaremodes.c revision 0b7217d9
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#include "common_compat.h"
44
45#ifndef M_T_DRIVER
46# define M_T_DRIVER  0x40	/* Supplied by the driver (EDID, etc) */
47#endif
48
49#define MODEPREFIX NULL, NULL, NULL, 0, M_T_DRIVER
50#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
51
52#define VMW_DEFLT_MODE_NAME "vmwlegacy-default-%dx%d"
53
54/*
55 *-----------------------------------------------------------------------------
56 *
57 * vmwareAddDefaultMode --
58 *
59 *    Add a default mode with the current screen dimensions.
60 *
61 * Results:
62 *    The default mode.
63 *
64 * Side effects:
65 *    None.
66 *
67 *-----------------------------------------------------------------------------
68 */
69
70void
71vmwareAddDefaultMode(ScrnInfoPtr pScrn, uint32 dwidth, uint32 dheight)
72{
73    DisplayModePtr *monitorModes = &pScrn->monitor->Modes;
74    DisplayModePtr modes = NULL;
75
76    if (monitorModes == NULL || *monitorModes == NULL) {
77	goto out_err;
78    }
79
80#ifdef HAVE_XORG_SERVER_1_2_0
81    if (dwidth && dheight) {
82	MonPtr monitor = pScrn->monitor;
83	DisplayModePtr mode = NULL;
84	DisplayModeRec dynamic =
85	    { MODEPREFIX, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, MODESUFFIX };
86	unsigned dispModeCount = 0;
87	CONST_ABI_18_0 char **dispModeList;
88	char *dynModeName;
89	char name[80];
90	VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
91
92	/* First, add the default mode name to the display mode
93	 * requests.
94	 */
95
96	snprintf(name, sizeof(name), VMW_DEFLT_MODE_NAME, dwidth, dheight);
97
98	dynModeName = xnfstrdup(name);
99	if (!dynModeName || !pScrn->display)
100	    goto out_err;
101
102	if (pScrn->display->modes) {
103	    dispModeList = pScrn->display->modes;
104	    while(*dispModeList)
105		dispModeList++;
106	    dispModeCount = (unsigned)(((size_t)dispModeList -
107	                                (size_t)pScrn->display->modes) /
108	                               sizeof(*dispModeList));
109	}
110
111	dispModeList = xnfcalloc(dispModeCount + 2, sizeof(*dispModeList));
112	if (!dispModeList)
113	    goto out_err;
114
115	memcpy(dispModeList, pScrn->display->modes,
116	       dispModeCount * sizeof(*dispModeList));
117	dispModeList[dispModeCount] = dynModeName;
118	pScrn->display->modes = dispModeList;
119
120	/* Then, add the default mode itself.
121	 */
122
123	dynamic.name = name;
124	dynamic.HDisplay = dwidth;
125	dynamic.HSyncStart = dynamic.HDisplay + 1;
126	dynamic.HSyncEnd = dynamic.HSyncStart + 1;
127	dynamic.HTotal = dynamic.HSyncEnd * 5 / 4;
128	dynamic.VDisplay = dheight;
129	dynamic.VSyncStart = dynamic.VDisplay + 1;
130	dynamic.VSyncEnd = dynamic.VSyncStart + 1;
131	dynamic.VTotal = dynamic.VSyncEnd + 1;
132	if (monitor->nVrefresh > 0)
133	    dynamic.VRefresh = monitor->vrefresh[0].lo;
134	else
135	    dynamic.VRefresh = 60;
136	dynamic.Clock = dynamic.VRefresh * dynamic.VTotal *
137	    dynamic.HTotal / 1000;
138	mode = xf86DuplicateMode(&dynamic);
139	modes = xf86ModesAdd(modes, mode);
140
141	if (dispModeCount == 0) {
142
143	    /*
144	     * Set up a large virtual size, so that we allow also
145	     * setting modes larger than the initial mode.
146	     *
147	     * We might also want to consider the case where
148	     * dispModeCount != 0, but the requested display modes
149	     * are not available. This is sufficient for now.
150	     */
151
152	    if (pScrn->display->virtualX == 0)
153		pScrn->display->virtualX = pVMWARE->maxWidth;
154	    if (pScrn->display->virtualY == 0)
155		pScrn->display->virtualY = pVMWARE->maxHeight;
156	}
157    }
158
159    *monitorModes = xf86ModesAdd(*monitorModes, modes);
160#else
161    (void) modes;
162#endif
163    return;
164  out_err:
165    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to add default mode.");
166}
167