vmwaremodes.c revision 3bfa90b6
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 = dispModeList - pScrn->display->modes;
106	}
107
108	dispModeList = xnfcalloc(dispModeCount + 2, sizeof(*dispModeList));
109	if (!dispModeList)
110	    goto out_err;
111
112	memcpy(dispModeList, pScrn->display->modes,
113	       dispModeCount * sizeof(*dispModeList));
114	dispModeList[dispModeCount] = dynModeName;
115	pScrn->display->modes = dispModeList;
116
117	/* Then, add the default mode itself.
118	 */
119
120	dynamic.name = name;
121	dynamic.HDisplay = dwidth;
122	dynamic.HSyncStart = dynamic.HDisplay + 1;
123	dynamic.HSyncEnd = dynamic.HSyncStart + 1;
124	dynamic.HTotal = dynamic.HSyncEnd * 5 / 4;
125	dynamic.VDisplay = dheight;
126	dynamic.VSyncStart = dynamic.VDisplay + 1;
127	dynamic.VSyncEnd = dynamic.VSyncStart + 1;
128	dynamic.VTotal = dynamic.VSyncEnd + 1;
129	if (monitor->nVrefresh > 0)
130	    dynamic.VRefresh = monitor->vrefresh[0].lo;
131	else
132	    dynamic.VRefresh = 60;
133	dynamic.Clock = dynamic.VRefresh * dynamic.VTotal *
134	    dynamic.HTotal / 1000;
135	mode = xf86DuplicateMode(&dynamic);
136	modes = xf86ModesAdd(modes, mode);
137
138	if (dispModeCount == 0) {
139
140	    /*
141	     * Set up a large virtual size, so that we allow also
142	     * setting modes larger than the initial mode.
143	     *
144	     * We might also want to consider the case where
145	     * dispModeCount != 0, but the requested display modes
146	     * are not available. This is sufficient for now.
147	     */
148
149	    if (pScrn->display->virtualX == 0)
150		pScrn->display->virtualX = pVMWARE->maxWidth;
151	    if (pScrn->display->virtualY == 0)
152		pScrn->display->virtualY = pVMWARE->maxHeight;
153	}
154    }
155
156    *monitorModes = xf86ModesAdd(*monitorModes, modes);
157#else
158    (void) modes;
159#endif
160    return;
161  out_err:
162    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to add default mode.");
163}
164