1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright 2005-2006 Luc Verhaegen.
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Permission is hereby granted, free of charge, to any person obtaining a
5*4882a593Smuzhiyun * copy of this software and associated documentation files (the "Software"),
6*4882a593Smuzhiyun * to deal in the Software without restriction, including without limitation
7*4882a593Smuzhiyun * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*4882a593Smuzhiyun * and/or sell copies of the Software, and to permit persons to whom the
9*4882a593Smuzhiyun * Software is furnished to do so, subject to the following conditions:
10*4882a593Smuzhiyun *
11*4882a593Smuzhiyun * The above copyright notice and this permission notice shall be included in
12*4882a593Smuzhiyun * all copies or substantial portions of the Software.
13*4882a593Smuzhiyun *
14*4882a593Smuzhiyun * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15*4882a593Smuzhiyun * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16*4882a593Smuzhiyun * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17*4882a593Smuzhiyun * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18*4882a593Smuzhiyun * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19*4882a593Smuzhiyun * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20*4882a593Smuzhiyun * OTHER DEALINGS IN THE SOFTWARE.
21*4882a593Smuzhiyun *
22*4882a593Smuzhiyun */
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun /* Standalone VESA CVT standard timing modelines generator. */
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun #include "xf86.h"
27*4882a593Smuzhiyun #include "xf86Modes.h"
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun /* FatalError implementation used by the server code we built in */
30*4882a593Smuzhiyun void
FatalError(const char * f,...)31*4882a593Smuzhiyun FatalError(const char *f, ...)
32*4882a593Smuzhiyun {
33*4882a593Smuzhiyun va_list args;
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun va_start(args, f);
36*4882a593Smuzhiyun vfprintf(stderr, f, args);
37*4882a593Smuzhiyun va_end(args);
38*4882a593Smuzhiyun exit(1);
39*4882a593Smuzhiyun }
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun /* xnfalloc implementation used by the server code we built in */
42*4882a593Smuzhiyun void *
XNFalloc(unsigned long n)43*4882a593Smuzhiyun XNFalloc(unsigned long n)
44*4882a593Smuzhiyun {
45*4882a593Smuzhiyun void *r;
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun r = malloc(n);
48*4882a593Smuzhiyun if (!r) {
49*4882a593Smuzhiyun perror("malloc failed");
50*4882a593Smuzhiyun exit(1);
51*4882a593Smuzhiyun }
52*4882a593Smuzhiyun return r;
53*4882a593Smuzhiyun }
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun /* xnfcalloc implementation used by the server code we built in */
56*4882a593Smuzhiyun void *
XNFcallocarray(size_t nmemb,size_t size)57*4882a593Smuzhiyun XNFcallocarray(size_t nmemb, size_t size)
58*4882a593Smuzhiyun {
59*4882a593Smuzhiyun void *r;
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun r = calloc(nmemb, size);
62*4882a593Smuzhiyun if (!r) {
63*4882a593Smuzhiyun perror("calloc failed");
64*4882a593Smuzhiyun exit(1);
65*4882a593Smuzhiyun }
66*4882a593Smuzhiyun return r;
67*4882a593Smuzhiyun }
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun /*
70*4882a593Smuzhiyun * Quickly check wether this is a CVT standard mode.
71*4882a593Smuzhiyun */
72*4882a593Smuzhiyun static Bool
CVTCheckStandard(int HDisplay,int VDisplay,float VRefresh,Bool Reduced,Bool Verbose)73*4882a593Smuzhiyun CVTCheckStandard(int HDisplay, int VDisplay, float VRefresh, Bool Reduced,
74*4882a593Smuzhiyun Bool Verbose)
75*4882a593Smuzhiyun {
76*4882a593Smuzhiyun Bool IsCVT = TRUE;
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun if ((!(VDisplay % 3) && ((VDisplay * 4 / 3) == HDisplay)) ||
79*4882a593Smuzhiyun (!(VDisplay % 9) && ((VDisplay * 16 / 9) == HDisplay)) ||
80*4882a593Smuzhiyun (!(VDisplay % 10) && ((VDisplay * 16 / 10) == HDisplay)) ||
81*4882a593Smuzhiyun (!(VDisplay % 4) && ((VDisplay * 5 / 4) == HDisplay)) ||
82*4882a593Smuzhiyun (!(VDisplay % 9) && ((VDisplay * 15 / 9) == HDisplay)));
83*4882a593Smuzhiyun else {
84*4882a593Smuzhiyun if (Verbose)
85*4882a593Smuzhiyun fprintf(stderr, "Warning: Aspect Ratio is not CVT standard.\n");
86*4882a593Smuzhiyun IsCVT = FALSE;
87*4882a593Smuzhiyun }
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun if ((VRefresh != 50.0) && (VRefresh != 60.0) &&
90*4882a593Smuzhiyun (VRefresh != 75.0) && (VRefresh != 85.0)) {
91*4882a593Smuzhiyun if (Verbose)
92*4882a593Smuzhiyun fprintf(stderr, "Warning: Refresh Rate is not CVT standard "
93*4882a593Smuzhiyun "(50, 60, 75 or 85Hz).\n");
94*4882a593Smuzhiyun IsCVT = FALSE;
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun return IsCVT;
98*4882a593Smuzhiyun }
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun /*
101*4882a593Smuzhiyun * I'm not documenting --interlaced for obvious reasons, even though I did
102*4882a593Smuzhiyun * implement it. I also can't deny having looked at gtf here.
103*4882a593Smuzhiyun */
104*4882a593Smuzhiyun static void
PrintUsage(char * Name)105*4882a593Smuzhiyun PrintUsage(char *Name)
106*4882a593Smuzhiyun {
107*4882a593Smuzhiyun fprintf(stderr, "\n");
108*4882a593Smuzhiyun fprintf(stderr, "usage: %s [-v|--verbose] [-r|--reduced] X Y [refresh]\n",
109*4882a593Smuzhiyun Name);
110*4882a593Smuzhiyun fprintf(stderr, "\n");
111*4882a593Smuzhiyun fprintf(stderr, " -v|--verbose : Warn about CVT standard adherance.\n");
112*4882a593Smuzhiyun fprintf(stderr, " -r|--reduced : Create a mode with reduced blanking "
113*4882a593Smuzhiyun "(default: normal blanking).\n");
114*4882a593Smuzhiyun fprintf(stderr, " X : Desired horizontal resolution "
115*4882a593Smuzhiyun "(multiple of 8, required).\n");
116*4882a593Smuzhiyun fprintf(stderr,
117*4882a593Smuzhiyun " Y : Desired vertical resolution (required).\n");
118*4882a593Smuzhiyun fprintf(stderr,
119*4882a593Smuzhiyun " refresh : Desired refresh rate (default: 60.0Hz).\n");
120*4882a593Smuzhiyun fprintf(stderr, "\n");
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun fprintf(stderr, "Calculates VESA CVT (Coordinated Video Timing) modelines"
123*4882a593Smuzhiyun " for use with X.\n");
124*4882a593Smuzhiyun }
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun /*
127*4882a593Smuzhiyun *
128*4882a593Smuzhiyun */
129*4882a593Smuzhiyun static void
PrintComment(DisplayModeRec * Mode,Bool CVT,Bool Reduced)130*4882a593Smuzhiyun PrintComment(DisplayModeRec * Mode, Bool CVT, Bool Reduced)
131*4882a593Smuzhiyun {
132*4882a593Smuzhiyun printf("# %dx%d %.2f Hz ", Mode->HDisplay, Mode->VDisplay, Mode->VRefresh);
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun if (CVT) {
135*4882a593Smuzhiyun printf("(CVT %.2fM",
136*4882a593Smuzhiyun ((float) Mode->HDisplay * Mode->VDisplay) / 1000000.0);
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun if (!(Mode->VDisplay % 3) &&
139*4882a593Smuzhiyun ((Mode->VDisplay * 4 / 3) == Mode->HDisplay))
140*4882a593Smuzhiyun printf("3");
141*4882a593Smuzhiyun else if (!(Mode->VDisplay % 9) &&
142*4882a593Smuzhiyun ((Mode->VDisplay * 16 / 9) == Mode->HDisplay))
143*4882a593Smuzhiyun printf("9");
144*4882a593Smuzhiyun else if (!(Mode->VDisplay % 10) &&
145*4882a593Smuzhiyun ((Mode->VDisplay * 16 / 10) == Mode->HDisplay))
146*4882a593Smuzhiyun printf("A");
147*4882a593Smuzhiyun else if (!(Mode->VDisplay % 4) &&
148*4882a593Smuzhiyun ((Mode->VDisplay * 5 / 4) == Mode->HDisplay))
149*4882a593Smuzhiyun printf("4");
150*4882a593Smuzhiyun else if (!(Mode->VDisplay % 9) &&
151*4882a593Smuzhiyun ((Mode->VDisplay * 15 / 9) == Mode->HDisplay))
152*4882a593Smuzhiyun printf("9");
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun if (Reduced)
155*4882a593Smuzhiyun printf("-R");
156*4882a593Smuzhiyun
157*4882a593Smuzhiyun printf(") ");
158*4882a593Smuzhiyun }
159*4882a593Smuzhiyun else
160*4882a593Smuzhiyun printf("(CVT) ");
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun printf("hsync: %.2f kHz; ", Mode->HSync);
163*4882a593Smuzhiyun printf("pclk: %.2f MHz", ((float) Mode->Clock) / 1000.0);
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun printf("\n");
166*4882a593Smuzhiyun }
167*4882a593Smuzhiyun
168*4882a593Smuzhiyun /*
169*4882a593Smuzhiyun * Originally grabbed from xf86Mode.c.
170*4882a593Smuzhiyun *
171*4882a593Smuzhiyun * Ignoring the actual Mode->name, as the user will want something solid
172*4882a593Smuzhiyun * to grab hold of.
173*4882a593Smuzhiyun */
174*4882a593Smuzhiyun static void
PrintModeline(DisplayModePtr Mode,int HDisplay,int VDisplay,float VRefresh,Bool Reduced)175*4882a593Smuzhiyun PrintModeline(DisplayModePtr Mode, int HDisplay, int VDisplay, float VRefresh,
176*4882a593Smuzhiyun Bool Reduced)
177*4882a593Smuzhiyun {
178*4882a593Smuzhiyun if (Reduced)
179*4882a593Smuzhiyun printf("Modeline \"%dx%dR\" ", HDisplay, VDisplay);
180*4882a593Smuzhiyun else
181*4882a593Smuzhiyun printf("Modeline \"%dx%d_%.2f\" ", HDisplay, VDisplay, VRefresh);
182*4882a593Smuzhiyun
183*4882a593Smuzhiyun printf("%6.2f %i %i %i %i %i %i %i %i", Mode->Clock / 1000.,
184*4882a593Smuzhiyun Mode->HDisplay, Mode->HSyncStart, Mode->HSyncEnd, Mode->HTotal,
185*4882a593Smuzhiyun Mode->VDisplay, Mode->VSyncStart, Mode->VSyncEnd, Mode->VTotal);
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun if (Mode->Flags & V_INTERLACE)
188*4882a593Smuzhiyun printf(" interlace");
189*4882a593Smuzhiyun if (Mode->Flags & V_PHSYNC)
190*4882a593Smuzhiyun printf(" +hsync");
191*4882a593Smuzhiyun if (Mode->Flags & V_NHSYNC)
192*4882a593Smuzhiyun printf(" -hsync");
193*4882a593Smuzhiyun if (Mode->Flags & V_PVSYNC)
194*4882a593Smuzhiyun printf(" +vsync");
195*4882a593Smuzhiyun if (Mode->Flags & V_NVSYNC)
196*4882a593Smuzhiyun printf(" -vsync");
197*4882a593Smuzhiyun
198*4882a593Smuzhiyun printf("\n");
199*4882a593Smuzhiyun }
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun /*
202*4882a593Smuzhiyun *
203*4882a593Smuzhiyun */
204*4882a593Smuzhiyun int
main(int argc,char * argv[])205*4882a593Smuzhiyun main(int argc, char *argv[])
206*4882a593Smuzhiyun {
207*4882a593Smuzhiyun DisplayModeRec *Mode;
208*4882a593Smuzhiyun int HDisplay = 0, VDisplay = 0;
209*4882a593Smuzhiyun float VRefresh = 0.0;
210*4882a593Smuzhiyun Bool Reduced = FALSE, Verbose = FALSE, IsCVT;
211*4882a593Smuzhiyun Bool Interlaced = FALSE;
212*4882a593Smuzhiyun int n;
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun if ((argc < 3) || (argc > 7)) {
215*4882a593Smuzhiyun PrintUsage(argv[0]);
216*4882a593Smuzhiyun return 1;
217*4882a593Smuzhiyun }
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun /* This doesn't filter out bad flags properly. Bad flags get passed down
220*4882a593Smuzhiyun * to atoi/atof, which then return 0, so that these variables can get
221*4882a593Smuzhiyun * filled next time round. So this is just a cosmetic problem.
222*4882a593Smuzhiyun */
223*4882a593Smuzhiyun for (n = 1; n < argc; n++) {
224*4882a593Smuzhiyun if (!strcmp(argv[n], "-r") || !strcmp(argv[n], "--reduced"))
225*4882a593Smuzhiyun Reduced = TRUE;
226*4882a593Smuzhiyun else if (!strcmp(argv[n], "-i") || !strcmp(argv[n], "--interlaced"))
227*4882a593Smuzhiyun Interlaced = TRUE;
228*4882a593Smuzhiyun else if (!strcmp(argv[n], "-v") || !strcmp(argv[n], "--verbose"))
229*4882a593Smuzhiyun Verbose = TRUE;
230*4882a593Smuzhiyun else if (!strcmp(argv[n], "-h") || !strcmp(argv[n], "--help")) {
231*4882a593Smuzhiyun PrintUsage(argv[0]);
232*4882a593Smuzhiyun return 0;
233*4882a593Smuzhiyun }
234*4882a593Smuzhiyun else if (!HDisplay) {
235*4882a593Smuzhiyun HDisplay = atoi(argv[n]);
236*4882a593Smuzhiyun if (!HDisplay) {
237*4882a593Smuzhiyun PrintUsage(argv[0]);
238*4882a593Smuzhiyun return 1;
239*4882a593Smuzhiyun }
240*4882a593Smuzhiyun }
241*4882a593Smuzhiyun else if (!VDisplay) {
242*4882a593Smuzhiyun VDisplay = atoi(argv[n]);
243*4882a593Smuzhiyun if (!VDisplay) {
244*4882a593Smuzhiyun PrintUsage(argv[0]);
245*4882a593Smuzhiyun return 1;
246*4882a593Smuzhiyun }
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun else if (!VRefresh) {
249*4882a593Smuzhiyun VRefresh = atof(argv[n]);
250*4882a593Smuzhiyun if (!VRefresh) {
251*4882a593Smuzhiyun PrintUsage(argv[0]);
252*4882a593Smuzhiyun return 1;
253*4882a593Smuzhiyun }
254*4882a593Smuzhiyun }
255*4882a593Smuzhiyun else {
256*4882a593Smuzhiyun PrintUsage(argv[0]);
257*4882a593Smuzhiyun return 1;
258*4882a593Smuzhiyun }
259*4882a593Smuzhiyun }
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun if (!HDisplay || !VDisplay) {
262*4882a593Smuzhiyun PrintUsage(argv[0]);
263*4882a593Smuzhiyun return 0;
264*4882a593Smuzhiyun }
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun /* Default to 60.0Hz */
267*4882a593Smuzhiyun if (!VRefresh)
268*4882a593Smuzhiyun VRefresh = 60.0;
269*4882a593Smuzhiyun
270*4882a593Smuzhiyun /* Horizontal timing is always a multiple of 8: round up. */
271*4882a593Smuzhiyun if (HDisplay & 0x07) {
272*4882a593Smuzhiyun HDisplay &= ~0x07;
273*4882a593Smuzhiyun HDisplay += 8;
274*4882a593Smuzhiyun }
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun if (Reduced) {
277*4882a593Smuzhiyun if ((VRefresh / 60.0) != floor(VRefresh / 60.0)) {
278*4882a593Smuzhiyun fprintf(stderr,
279*4882a593Smuzhiyun "\nERROR: Multiple of 60Hz refresh rate required for "
280*4882a593Smuzhiyun " reduced blanking.\n");
281*4882a593Smuzhiyun PrintUsage(argv[0]);
282*4882a593Smuzhiyun return 0;
283*4882a593Smuzhiyun }
284*4882a593Smuzhiyun }
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun IsCVT = CVTCheckStandard(HDisplay, VDisplay, VRefresh, Reduced, Verbose);
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun Mode = xf86CVTMode(HDisplay, VDisplay, VRefresh, Reduced, Interlaced);
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun PrintComment(Mode, IsCVT, Reduced);
291*4882a593Smuzhiyun PrintModeline(Mode, HDisplay, VDisplay, VRefresh, Reduced);
292*4882a593Smuzhiyun
293*4882a593Smuzhiyun return 0;
294*4882a593Smuzhiyun }
295