xref: /OK3568_Linux_fs/external/xserver/hw/xfree86/utils/cvt/cvt.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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