1
|
1 /*
|
|
2 * Linux Frame Buffer Device Configuration
|
|
3 *
|
|
4 * © Copyright 1995-1999 by Geert Uytterhoeven
|
|
5 * (Geert.Uytterhoeven@cs.kuleuven.ac.be)
|
|
6 *
|
|
7 * --------------------------------------------------------------------------
|
|
8 *
|
|
9 * This file is subject to the terms and conditions of the GNU General Public
|
|
10 * License. See the file COPYING in the main directory of the Linux
|
|
11 * distribution for more details.
|
|
12 *
|
|
13 * Petr Vandrovec <vandrove@vc.cvut.cz>:
|
|
14 * -grayscale, -rgba, -nonstd, VGA modes reporting
|
|
15 *
|
|
16 * Brad Midgley <brad@exodus.pht.com>:
|
|
17 * -match
|
|
18 *
|
|
19 */
|
|
20
|
|
21
|
|
22 #include <stdarg.h>
|
|
23 #include <stdlib.h>
|
|
24 #include <unistd.h>
|
|
25 #include <string.h>
|
|
26 #include <fcntl.h>
|
|
27 #include <errno.h>
|
|
28 #include <sys/ioctl.h>
|
|
29 #include <ctype.h>
|
|
30 #include <sys/stat.h>
|
|
31
|
|
32 struct file;
|
|
33 struct inode;
|
|
34
|
|
35 #include "fb.h"
|
|
36
|
|
37 #include "fbset.h"
|
|
38
|
|
39
|
|
40 /*
|
|
41 * Default Frame Buffer Special Device Node
|
|
42 */
|
|
43
|
|
44 #define DEFAULT_FRAMEBUFFER "/dev/fb0"
|
|
45
|
|
46
|
|
47 /*
|
|
48 * Default Video Mode Database File
|
|
49 */
|
|
50
|
|
51 #define DEFAULT_MODEDBFILE "/etc/fb.modes"
|
|
52
|
|
53
|
|
54 /*
|
|
55 * Command Line Options
|
|
56 */
|
|
57
|
|
58 static const char *ProgramName;
|
|
59
|
|
60 static int Opt_test = 0;
|
|
61 static int Opt_show = 0;
|
|
62 static int Opt_info = 0;
|
|
63 static int Opt_version = 0;
|
|
64 static int Opt_verbose = 0;
|
|
65 static int Opt_xfree86 = 0;
|
|
66 static int Opt_change = 0;
|
|
67 static int Opt_all = 0;
|
|
68
|
|
69 static const char *Opt_fb = NULL;
|
|
70 const char *Opt_modedb = DEFAULT_MODEDBFILE;
|
|
71 static const char *Opt_xres = NULL;
|
|
72 static const char *Opt_yres = NULL;
|
|
73 static const char *Opt_vxres = NULL;
|
|
74 static const char *Opt_vyres = NULL;
|
|
75 static const char *Opt_depth = NULL;
|
|
76 static const char *Opt_pixclock = NULL;
|
|
77 static const char *Opt_left = NULL;
|
|
78 static const char *Opt_right = NULL;
|
|
79 static const char *Opt_upper = NULL;
|
|
80 static const char *Opt_lower = NULL;
|
|
81 static const char *Opt_hslen = NULL;
|
|
82 static const char *Opt_vslen = NULL;
|
|
83 static const char *Opt_accel = NULL;
|
|
84 static const char *Opt_hsync = NULL;
|
|
85 static const char *Opt_vsync = NULL;
|
|
86 static const char *Opt_csync = NULL;
|
|
87 static const char *Opt_gsync = NULL;
|
|
88 static const char *Opt_extsync = NULL;
|
|
89 static const char *Opt_bcast = NULL;
|
|
90 static const char *Opt_laced = NULL;
|
|
91 static const char *Opt_double = NULL;
|
|
92 static const char *Opt_move = NULL;
|
|
93 static const char *Opt_step = NULL;
|
|
94 static const char *Opt_modename = NULL;
|
|
95 static const char *Opt_rgba = NULL;
|
|
96 static const char *Opt_nonstd = NULL;
|
|
97 static const char *Opt_grayscale = NULL;
|
|
98 static const char *Opt_matchyres = NULL;
|
|
99
|
|
100 static struct {
|
|
101 const char *name;
|
|
102 const char **value;
|
|
103 const int change;
|
|
104 } Options[] = {
|
|
105 { "-fb", &Opt_fb, 0 },
|
|
106 { "-db", &Opt_modedb, 0 },
|
|
107 { "-xres", &Opt_xres, 1 },
|
|
108 { "-yres", &Opt_yres, 1 },
|
|
109 { "-vxres", &Opt_vxres, 1 },
|
|
110 { "-vyres", &Opt_vyres, 1 },
|
|
111 { "-depth", &Opt_depth, 1 },
|
|
112 { "-nonstd", &Opt_nonstd, 1},
|
|
113 { "-pixclock", &Opt_pixclock, 1 },
|
|
114 { "-left", &Opt_left, 1 },
|
|
115 { "-right", &Opt_right, 1 },
|
|
116 { "-upper", &Opt_upper, 1 },
|
|
117 { "-lower", &Opt_lower, 1 },
|
|
118 { "-hslen", &Opt_hslen, 1 },
|
|
119 { "-vslen", &Opt_vslen, 1 },
|
|
120 { "-accel", &Opt_accel, 1 },
|
|
121 { "-hsync", &Opt_hsync, 1 },
|
|
122 { "-vsync", &Opt_vsync, 1 },
|
|
123 { "-csync", &Opt_csync, 1 },
|
|
124 { "-gsync", &Opt_gsync, 1 },
|
|
125 { "-extsync", &Opt_extsync, 1 },
|
|
126 { "-bcast", &Opt_bcast, 1 },
|
|
127 { "-laced", &Opt_laced, 1 },
|
|
128 { "-double", &Opt_double, 1 },
|
|
129 { "-move", &Opt_move, 1 },
|
|
130 { "-step", &Opt_step, 1 },
|
|
131 { "-rgba", &Opt_rgba, 1 },
|
|
132 { "-grayscale", &Opt_grayscale, 1 },
|
|
133 { NULL, NULL, 0 }
|
|
134 };
|
|
135
|
|
136
|
|
137 /*
|
|
138 * Video Mode Database
|
|
139 */
|
|
140
|
|
141 struct VideoMode *VideoModes = NULL;
|
|
142
|
|
143
|
|
144 /*
|
|
145 * Hardware Text Modes
|
|
146 */
|
|
147
|
|
148 static struct textentry {
|
|
149 __u32 id;
|
|
150 const char *name;
|
|
151 } Textmodes[] = {
|
|
152 { FB_AUX_TEXT_MDA, "Monochrome text" },
|
|
153 { FB_AUX_TEXT_CGA, "CGA/EGA/VGA Color text" },
|
|
154 { FB_AUX_TEXT_S3_MMIO, "S3 MMIO fasttext" },
|
|
155 { FB_AUX_TEXT_MGA_STEP16, "MGA Millennium I step 16 text" },
|
|
156 { FB_AUX_TEXT_MGA_STEP8, "MGA step 8 text" },
|
|
157 };
|
|
158
|
|
159 static struct textentry VGAModes[] = {
|
|
160 { FB_AUX_VGA_PLANES_VGA4, "VGA 16 colors in 4 planes" },
|
|
161 { FB_AUX_VGA_PLANES_CFB4, "VGA 16 colors in 1 plane" },
|
|
162 { FB_AUX_VGA_PLANES_CFB8, "VGA 256 colors in 4 planes" },
|
|
163 /* last entry has name == NULL */
|
|
164 { 0, NULL}
|
|
165 };
|
|
166
|
|
167 /*
|
|
168 * Hardware Accelerators
|
|
169 */
|
|
170
|
|
171 static struct accelentry {
|
|
172 __u32 id;
|
|
173 const char *name;
|
|
174 } Accelerators[] = {
|
|
175 { FB_ACCEL_NONE, "No" },
|
|
176 { FB_ACCEL_ATARIBLITT, "Atari Blitter" },
|
|
177 { FB_ACCEL_AMIGABLITT, "Amiga Blitter" },
|
|
178 { FB_ACCEL_S3_TRIO64, "S3 Trio64" },
|
|
179 { FB_ACCEL_NCR_77C32BLT, "NCR 77C32BLT" },
|
|
180 { FB_ACCEL_S3_VIRGE, "S3 ViRGE" },
|
|
181 { FB_ACCEL_ATI_MACH64GX, "ATI Mach64GX" },
|
|
182 { FB_ACCEL_DEC_TGA, "DEC 21030 TGA" },
|
|
183 { FB_ACCEL_ATI_MACH64CT, "ATI Mach64CT" },
|
|
184 { FB_ACCEL_ATI_MACH64VT, "ATI Mach64VT" },
|
|
185 { FB_ACCEL_ATI_MACH64GT, "ATI Mach64GT" },
|
|
186 { FB_ACCEL_SUN_CREATOR, "Sun Creator/Creator3D" },
|
|
187 { FB_ACCEL_SUN_CGSIX, "Sun cg6" },
|
|
188 { FB_ACCEL_SUN_LEO, "Sun leo/zx" },
|
|
189 { FB_ACCEL_IMS_TWINTURBO, "IMS Twin Turbo" },
|
|
190 { FB_ACCEL_3DLABS_PERMEDIA2, "3Dlabs Permedia 2" },
|
|
191 { FB_ACCEL_MATROX_MGA2064W, "Matrox MGA2064W (Millennium)" },
|
|
192 { FB_ACCEL_MATROX_MGA1064SG, "Matrox MGA1064SG (Mystique)" },
|
|
193 { FB_ACCEL_MATROX_MGA2164W, "Matrox MGA2164W (Millennium II)" },
|
|
194 { FB_ACCEL_MATROX_MGA2164W_AGP, "Matrox MGA2164W (Millennium II AGP)" },
|
|
195 { FB_ACCEL_MATROX_MGAG100, "Matrox G100 (Productiva G100)" },
|
|
196 { FB_ACCEL_MATROX_MGAG200, "Matrox G200 (Millennium, Mystique)" },
|
|
197 { FB_ACCEL_SUN_CG14, "Sun cg14" },
|
|
198 { FB_ACCEL_SUN_BWTWO, "Sun bw2" },
|
|
199 { FB_ACCEL_SUN_CGTHREE, "Sun cg3" },
|
|
200 { FB_ACCEL_SUN_TCX, "Sun tcx" },
|
|
201 { FB_ACCEL_MATROX_MGAG400, "Matrox G400" },
|
|
202 };
|
|
203
|
|
204
|
|
205 /*
|
|
206 * Current Video Mode
|
|
207 */
|
|
208
|
|
209 struct VideoMode Current;
|
|
210
|
|
211
|
|
212 /*
|
|
213 * Function Prototypes
|
|
214 */
|
|
215
|
|
216 int OpenFrameBuffer(const char *name);
|
|
217 void CloseFrameBuffer(int fh);
|
|
218 void GetVarScreenInfo(int fh, struct fb_var_screeninfo *var);
|
|
219 void SetVarScreenInfo(int fh, struct fb_var_screeninfo *var);
|
|
220 void GetFixScreenInfo(int fh, struct fb_fix_screeninfo *fix);
|
|
221 static void ConvertFromVideoMode(const struct VideoMode *vmode,
|
|
222 struct fb_var_screeninfo *var);
|
|
223 static void ConvertToVideoMode(const struct fb_var_screeninfo *var,
|
|
224 struct VideoMode *vmode);
|
|
225 static int atoboolean(const char *var);
|
|
226 static void ReadModeDB(void);
|
|
227 static struct VideoMode *FindVideoMode(const char *name);
|
|
228 static void ModifyVideoMode(struct VideoMode *vmode);
|
|
229 static void DisplayVModeInfo(struct VideoMode *vmode);
|
|
230 static void DisplayFBInfo(struct fb_fix_screeninfo *fix);
|
|
231 static int FillScanRates(struct VideoMode *vmode);
|
|
232 static void Usage(void) __attribute__ ((noreturn));
|
|
233 int main(int argc, char *argv[]);
|
|
234
|
|
235
|
|
236 /*
|
|
237 * Print an Error Message and Exit
|
|
238 */
|
|
239
|
|
240 void Die(const char *fmt, ...)
|
|
241 {
|
|
242 va_list ap;
|
|
243
|
|
244 fflush(stdout);
|
|
245 va_start(ap, fmt);
|
|
246 vfprintf(stderr, fmt, ap);
|
|
247 va_end(ap);
|
|
248 exit(1);
|
|
249 }
|
|
250
|
|
251
|
|
252 /*
|
|
253 * Open the Frame Buffer Device
|
|
254 */
|
|
255
|
|
256 int OpenFrameBuffer(const char *name)
|
|
257 {
|
|
258 int fh;
|
|
259
|
|
260 if (Opt_verbose)
|
|
261 printf("Opening frame buffer device `%s'\n", name);
|
|
262
|
|
263 if ((fh = open(name, O_RDONLY)) == -1)
|
|
264 Die("open %s: %s\n", name, strerror(errno));
|
|
265 return fh;
|
|
266 }
|
|
267
|
|
268
|
|
269 /*
|
|
270 * Close the Frame Buffer Device
|
|
271 */
|
|
272
|
|
273 void CloseFrameBuffer(int fh)
|
|
274 {
|
|
275 close(fh);
|
|
276 }
|
|
277
|
|
278 /*
|
|
279 * Get the Variable Part of the Screen Info
|
|
280 */
|
|
281
|
|
282 void GetVarScreenInfo(int fh, struct fb_var_screeninfo *var)
|
|
283 {
|
|
284 if (ioctl(fh, FBIOGET_VSCREENINFO, var))
|
|
285 Die("ioctl FBIOGET_VSCREENINFO: %s\n", strerror(errno));
|
|
286 }
|
|
287
|
|
288
|
|
289 /*
|
|
290 * Set (and Get) the Variable Part of the Screen Info
|
|
291 */
|
|
292
|
|
293 void SetVarScreenInfo(int fh, struct fb_var_screeninfo *var)
|
|
294 {
|
|
295 if (ioctl(fh, FBIOPUT_VSCREENINFO, var))
|
|
296 Die("ioctl FBIOPUT_VSCREENINFO: %s\n", strerror(errno));
|
|
297 }
|
|
298
|
|
299
|
|
300 /*
|
|
301 * Get the Fixed Part of the Screen Info
|
|
302 */
|
|
303
|
|
304 void GetFixScreenInfo(int fh, struct fb_fix_screeninfo *fix)
|
|
305 {
|
|
306 if (ioctl(fh, FBIOGET_FSCREENINFO, fix))
|
|
307 Die("ioctl FBIOGET_FSCREENINFO: %s\n", strerror(errno));
|
|
308 }
|
|
309
|
|
310
|
|
311 /*
|
|
312 * Conversion Routines
|
|
313 */
|
|
314
|
|
315 static void ConvertFromVideoMode(const struct VideoMode *vmode,
|
|
316 struct fb_var_screeninfo *var)
|
|
317 {
|
|
318 memset(var, 0, sizeof(struct fb_var_screeninfo));
|
|
319 var->xres = vmode->xres;
|
|
320 var->yres = vmode->yres;
|
|
321 var->xres_virtual = vmode->vxres;
|
|
322 var->yres_virtual = vmode->vyres;
|
|
323 var->bits_per_pixel = vmode->depth;
|
|
324 var->nonstd = vmode->nonstd;
|
|
325 if (Opt_test)
|
|
326 var->activate = FB_ACTIVATE_TEST;
|
|
327 else
|
|
328 var->activate = FB_ACTIVATE_NOW;
|
|
329 if (Opt_all)
|
|
330 var->activate = FB_ACTIVATE_ALL;
|
|
331 var->accel_flags = vmode->accel_flags;
|
|
332 var->pixclock = vmode->pixclock;
|
|
333 var->left_margin = vmode->left;
|
|
334 var->right_margin = vmode->right;
|
|
335 var->upper_margin = vmode->upper;
|
|
336 var->lower_margin = vmode->lower;
|
|
337 var->hsync_len = vmode->hslen;
|
|
338 var->vsync_len = vmode->vslen;
|
|
339 if (vmode->hsync == HIGH)
|
|
340 var->sync |= FB_SYNC_HOR_HIGH_ACT;
|
|
341 if (vmode->vsync == HIGH)
|
|
342 var->sync |= FB_SYNC_VERT_HIGH_ACT;
|
|
343 if (vmode->csync == HIGH)
|
|
344 var->sync |= FB_SYNC_COMP_HIGH_ACT;
|
|
345 if (vmode->gsync == HIGH)
|
|
346 var->sync |= FB_SYNC_ON_GREEN;
|
|
347 if (vmode->extsync == TRUE)
|
|
348 var->sync |= FB_SYNC_EXT;
|
|
349 if (vmode->bcast == TRUE)
|
|
350 var->sync |= FB_SYNC_BROADCAST;
|
|
351 if (vmode->laced == TRUE)
|
|
352 var->vmode = FB_VMODE_INTERLACED;
|
|
353 else if (vmode->dblscan == TRUE)
|
|
354 var->vmode = FB_VMODE_DOUBLE;
|
|
355 else
|
|
356 var->vmode = FB_VMODE_NONINTERLACED;
|
|
357 var->vmode |= FB_VMODE_CONUPDATE;
|
|
358 var->red.length = vmode->red.length;
|
|
359 var->red.offset = vmode->red.offset;
|
|
360 var->green.length = vmode->green.length;
|
|
361 var->green.offset = vmode->green.offset;
|
|
362 var->blue.length = vmode->blue.length;
|
|
363 var->blue.offset = vmode->blue.offset;
|
|
364 var->transp.length = vmode->transp.length;
|
|
365 var->transp.offset = vmode->transp.offset;
|
|
366 var->grayscale = vmode->grayscale;
|
|
367 }
|
|
368
|
|
369
|
|
370 static void ConvertToVideoMode(const struct fb_var_screeninfo *var,
|
|
371 struct VideoMode *vmode)
|
|
372 {
|
|
373 vmode->name = NULL;
|
|
374 vmode->xres = var->xres;
|
|
375 vmode->yres = var->yres;
|
|
376 vmode->vxres = var->xres_virtual;
|
|
377 vmode->vyres = var->yres_virtual;
|
|
378 vmode->depth = var->bits_per_pixel;
|
|
379 vmode->nonstd = var->nonstd;
|
|
380 vmode->accel_flags = var->accel_flags;
|
|
381 vmode->pixclock = var->pixclock;
|
|
382 vmode->left = var->left_margin;
|
|
383 vmode->right = var->right_margin;
|
|
384 vmode->upper = var->upper_margin;
|
|
385 vmode->lower = var->lower_margin;
|
|
386 vmode->hslen = var->hsync_len;
|
|
387 vmode->vslen = var->vsync_len;
|
|
388 vmode->hsync = var->sync & FB_SYNC_HOR_HIGH_ACT ? HIGH : LOW;
|
|
389 vmode->vsync = var->sync & FB_SYNC_VERT_HIGH_ACT ? HIGH : LOW;
|
|
390 vmode->csync = var->sync & FB_SYNC_COMP_HIGH_ACT ? HIGH : LOW;
|
|
391 vmode->gsync = var->sync & FB_SYNC_ON_GREEN ? TRUE : FALSE;
|
|
392 vmode->extsync = var->sync & FB_SYNC_EXT ? TRUE : FALSE;
|
|
393 vmode->bcast = var->sync & FB_SYNC_BROADCAST ? TRUE : FALSE;
|
|
394 vmode->grayscale = var->grayscale;
|
|
395 vmode->laced = FALSE;
|
|
396 vmode->dblscan = FALSE;
|
|
397 switch (var->vmode & FB_VMODE_MASK) {
|
|
398 case FB_VMODE_INTERLACED:
|
|
399 vmode->laced = TRUE;
|
|
400 break;
|
|
401 case FB_VMODE_DOUBLE:
|
|
402 vmode->dblscan = TRUE;
|
|
403 break;
|
|
404 }
|
|
405 vmode->red.length = var->red.length;
|
|
406 vmode->red.offset = var->red.offset;
|
|
407 vmode->green.length = var->green.length;
|
|
408 vmode->green.offset = var->green.offset;
|
|
409 vmode->blue.length = var->blue.length;
|
|
410 vmode->blue.offset = var->blue.offset;
|
|
411 vmode->transp.length = var->transp.length;
|
|
412 vmode->transp.offset = var->transp.offset;
|
|
413 FillScanRates(vmode);
|
|
414 }
|
|
415
|
|
416
|
|
417 static int atoboolean(const char *var)
|
|
418 {
|
|
419 int value = 0;
|
|
420
|
|
421 if (!strcasecmp(var, "false") || !strcasecmp(var, "low") ||
|
|
422 !strcasecmp(var, "no") || !strcasecmp(var, "off") ||
|
|
423 !strcmp(var, "0"))
|
|
424 value = 0;
|
|
425 else if (!strcasecmp(var, "true") || !strcasecmp(var, "high") ||
|
|
426 !strcasecmp(var, "yes") || !strcasecmp(var, "on") ||
|
|
427 !strcmp(var, "1"))
|
|
428 value = 1;
|
|
429 else
|
|
430 Die("Invalid value `%s'\n", var);
|
|
431
|
|
432 return value;
|
|
433 }
|
|
434
|
|
435
|
|
436 void AddVideoMode(const struct VideoMode *vmode)
|
|
437 {
|
|
438 struct VideoMode *vmode2;
|
|
439
|
|
440 if (FindVideoMode(vmode->name))
|
|
441 Die("%s:%d: Duplicate mode name `%s'\n", Opt_modedb, line,
|
|
442 vmode->name);
|
|
443 vmode2 = malloc(sizeof(struct VideoMode));
|
|
444 *vmode2 = *vmode;
|
|
445 if (!FillScanRates(vmode2))
|
|
446 Die("%s:%d: Bad video mode `%s'\n", Opt_modedb, line, vmode2->name);
|
|
447 vmode2->next = VideoModes;
|
|
448 VideoModes = vmode2;
|
|
449 }
|
|
450
|
|
451
|
|
452 /*
|
|
453 * Read the Video Mode Database
|
|
454 */
|
|
455
|
|
456 static void ReadModeDB(void)
|
|
457 {
|
|
458 if (Opt_verbose)
|
|
459 printf("Reading mode database from file `%s'\n", Opt_modedb);
|
|
460
|
|
461 if (!(yyin = fopen(Opt_modedb, "r")))
|
|
462 Die("fopen %s: %s\n", Opt_modedb, strerror(errno));
|
|
463 yyparse();
|
|
464 fclose(yyin);
|
|
465 }
|
|
466
|
|
467
|
|
468 static void getColor(struct color *color, const char** opt)
|
|
469 {
|
|
470 char* ptr;
|
|
471
|
|
472 color->length = 0;
|
|
473 color->offset = 0;
|
|
474 ptr = (char*)(*opt);
|
|
475 if (!ptr)
|
|
476 return;
|
|
477 color->length = strtoul(ptr, &ptr, 0);
|
|
478 if (!ptr)
|
|
479 return;
|
|
480 if (*ptr == '/')
|
|
481 color->offset = strtoul(ptr+1, &ptr, 0);
|
|
482 if (ptr) {
|
|
483 while (*ptr && isspace(*ptr))
|
|
484 ptr++;
|
|
485 if (*ptr == ',') {
|
|
486 ptr++;
|
|
487 } else if (*ptr)
|
|
488 Die("Bad RGBA syntax, rL/rO,gL/gO,bL/bO,tL/tO or rL,gL,bL,tL\n");
|
|
489 }
|
|
490 *opt = ptr;
|
|
491 return;
|
|
492 }
|
|
493
|
|
494 void makeRGBA(struct VideoMode *vmode, const char* opt)
|
|
495 {
|
|
496 getColor(&vmode->red, &opt);
|
|
497 getColor(&vmode->green, &opt);
|
|
498 getColor(&vmode->blue, &opt);
|
|
499 getColor(&vmode->transp, &opt);
|
|
500 }
|
|
501
|
|
502 /*
|
|
503 * Find a Video Mode
|
|
504 */
|
|
505
|
|
506 static struct VideoMode *FindVideoMode(const char *name)
|
|
507 {
|
|
508 struct VideoMode *vmode;
|
|
509
|
|
510 for (vmode = VideoModes; vmode; vmode = vmode->next)
|
|
511 if (!strcmp(name, vmode->name))
|
|
512 break;
|
|
513
|
|
514 return vmode;
|
|
515 }
|
|
516
|
|
517
|
|
518 /*
|
|
519 * Modify a Video Mode
|
|
520 */
|
|
521
|
|
522 static void ModifyVideoMode(struct VideoMode *vmode)
|
|
523 {
|
|
524 u_int hstep = 8, vstep = 2;
|
|
525
|
|
526 if (Opt_xres)
|
|
527 vmode->xres = strtoul(Opt_xres, NULL, 0);
|
|
528 if (Opt_yres)
|
|
529 vmode->yres = strtoul(Opt_yres, NULL, 0);
|
|
530 if (Opt_vxres)
|
|
531 vmode->vxres = strtoul(Opt_vxres, NULL, 0);
|
|
532 if (Opt_vyres)
|
|
533 vmode->vyres = strtoul(Opt_vyres, NULL, 0);
|
|
534 if (Opt_depth)
|
|
535 vmode->depth = strtoul(Opt_depth, NULL, 0);
|
|
536 if (Opt_nonstd)
|
|
537 vmode->nonstd = strtoul(Opt_nonstd, NULL, 0);
|
|
538 if (Opt_accel)
|
|
539 vmode->accel_flags = atoboolean(Opt_accel) ? FB_ACCELF_TEXT : 0;
|
|
540 if (Opt_pixclock)
|
|
541 vmode->pixclock = strtoul(Opt_pixclock, NULL, 0);
|
|
542 if (Opt_left)
|
|
543 vmode->left = strtoul(Opt_left, NULL, 0);
|
|
544 if (Opt_right)
|
|
545 vmode->right = strtoul(Opt_right, NULL, 0);
|
|
546 if (Opt_upper)
|
|
547 vmode->upper = strtoul(Opt_upper, NULL, 0);
|
|
548 if (Opt_lower)
|
|
549 vmode->lower = strtoul(Opt_lower, NULL, 0);
|
|
550 if (Opt_hslen)
|
|
551 vmode->hslen = strtoul(Opt_hslen, NULL, 0);
|
|
552 if (Opt_vslen)
|
|
553 vmode->vslen = strtoul(Opt_vslen, NULL, 0);
|
|
554 if (Opt_hsync)
|
|
555 vmode->hsync = atoboolean(Opt_hsync);
|
|
556 if (Opt_vsync)
|
|
557 vmode->vsync = atoboolean(Opt_vsync);
|
|
558 if (Opt_csync)
|
|
559 vmode->csync = atoboolean(Opt_csync);
|
|
560 if (Opt_gsync)
|
|
561 vmode->gsync = atoboolean(Opt_gsync);
|
|
562 if (Opt_extsync)
|
|
563 vmode->extsync = atoboolean(Opt_extsync);
|
|
564 if (Opt_bcast)
|
|
565 vmode->bcast = atoboolean(Opt_bcast);
|
|
566 if (Opt_laced)
|
|
567 vmode->laced = atoboolean(Opt_laced);
|
|
568 if (Opt_double)
|
|
569 vmode->dblscan = atoboolean(Opt_double);
|
|
570 if (Opt_grayscale)
|
|
571 vmode->grayscale = atoboolean(Opt_grayscale);
|
|
572 if (Opt_step)
|
|
573 hstep = vstep = strtoul(Opt_step, NULL, 0);
|
|
574 if (Opt_matchyres)
|
|
575 vmode->vyres = vmode->yres;
|
|
576 if (Opt_move) {
|
|
577 if (!strcasecmp(Opt_move, "left")) {
|
|
578 if (hstep > vmode->left)
|
|
579 Die("The left margin cannot be negative\n");
|
|
580 vmode->left -= hstep;
|
|
581 vmode->right += hstep;
|
|
582 } else if (!strcasecmp(Opt_move, "right")) {
|
|
583 if (hstep > vmode->right)
|
|
584 Die("The right margin cannot be negative\n");
|
|
585 vmode->left += hstep;
|
|
586 vmode->right -= hstep;
|
|
587 } else if (!strcasecmp(Opt_move, "up")) {
|
|
588 if (vstep > vmode->upper)
|
|
589 Die("The upper margin cannot be negative\n");
|
|
590 vmode->upper -= vstep;
|
|
591 vmode->lower += vstep;
|
|
592 } else if (!strcasecmp(Opt_move, "down")) {
|
|
593 if (vstep > vmode->lower)
|
|
594 Die("The lower margin cannot be negative\n");
|
|
595 vmode->upper += vstep;
|
|
596 vmode->lower -= vstep;
|
|
597 } else
|
|
598 Die("Invalid direction `%s'\n", Opt_move);
|
|
599 }
|
|
600 if (Opt_rgba) {
|
|
601 makeRGBA(vmode, Opt_rgba);
|
|
602 }
|
|
603 if (!FillScanRates(vmode))
|
|
604 Die("Bad video mode\n");
|
|
605 }
|
|
606
|
|
607
|
|
608 /*
|
|
609 * Display the Video Mode Information
|
|
610 */
|
|
611
|
|
612 static void DisplayVModeInfo(struct VideoMode *vmode)
|
|
613 {
|
|
614 u_int res, sstart, send, total;
|
|
615
|
|
616 puts("");
|
|
617 if (!Opt_xfree86) {
|
|
618 printf("mode \"%dx%d", vmode->xres, vmode->yres);
|
|
619 if (vmode->pixclock) {
|
|
620 printf("-%d\"\n", (int)(vmode->vrate+0.5));
|
|
621 printf(" # D: %5.3f MHz, H: %5.3f kHz, V: %5.3f Hz\n",
|
|
622 vmode->drate/1E6, vmode->hrate/1E3, vmode->vrate);
|
|
623 } else
|
|
624 puts("\"");
|
|
625 printf(" geometry %d %d %d %d %d\n", vmode->xres, vmode->yres,
|
|
626 vmode->vxres, vmode->vyres, vmode->depth);
|
|
627 printf(" timings %d %d %d %d %d %d %d\n", vmode->pixclock,
|
|
628 vmode->left, vmode->right, vmode->upper, vmode->lower,
|
|
629 vmode->hslen, vmode->vslen);
|
|
630 if (vmode->hsync)
|
|
631 puts(" hsync high");
|
|
632 if (vmode->vsync)
|
|
633 puts(" vsync high");
|
|
634 if (vmode->csync)
|
|
635 puts(" csync high");
|
|
636 if (vmode->gsync)
|
|
637 puts(" gsync true");
|
|
638 if (vmode->extsync)
|
|
639 puts(" extsync true");
|
|
640 if (vmode->bcast)
|
|
641 puts(" bcast true");
|
|
642 if (vmode->laced)
|
|
643 puts(" laced true");
|
|
644 if (vmode->dblscan)
|
|
645 puts(" double true");
|
|
646 if (vmode->nonstd)
|
|
647 printf(" nonstd %u\n", vmode->nonstd);
|
|
648 if (vmode->accel_flags)
|
|
649 puts(" accel true");
|
|
650 if (vmode->grayscale)
|
|
651 puts(" grayscale true");
|
|
652 printf(" rgba %u/%u,%u/%u,%u/%u,%u/%u\n",
|
|
653 vmode->red.length, vmode->red.offset, vmode->green.length,
|
|
654 vmode->green.offset, vmode->blue.length, vmode->blue.offset,
|
|
655 vmode->transp.length, vmode->transp.offset);
|
|
656 puts("endmode\n");
|
|
657 } else {
|
|
658 printf("Mode \"%dx%d\"\n", vmode->xres, vmode->yres);
|
|
659 if (vmode->pixclock) {
|
|
660 printf(" # D: %5.3f MHz, H: %5.3f kHz, V: %5.3f Hz\n",
|
|
661 vmode->drate/1E6, vmode->hrate/1E3, vmode->vrate);
|
|
662 printf(" DotClock %5.3f\n", vmode->drate/1E6+0.001);
|
|
663 } else
|
|
664 puts(" DotClock Unknown");
|
|
665 res = vmode->xres;
|
|
666 sstart = res+vmode->right;
|
|
667 send = sstart+vmode->hslen;
|
|
668 total = send+vmode->left;
|
|
669 printf(" HTimings %d %d %d %d\n", res, sstart, send, total);
|
|
670 res = vmode->yres;
|
|
671 sstart = res+vmode->lower;
|
|
672 send = sstart+vmode->vslen;
|
|
673 total = send+vmode->upper;
|
|
674 printf(" VTimings %d %d %d %d\n", res, sstart, send, total);
|
|
675 printf(" Flags ");
|
|
676 if (vmode->laced)
|
|
677 printf(" \"Interlace\"");
|
|
678 if (vmode->dblscan)
|
|
679 printf(" \"DoubleScan\"");
|
|
680 if (vmode->hsync)
|
|
681 printf(" \"+HSync\"");
|
|
682 else
|
|
683 printf(" \"-HSync\"");
|
|
684 if (vmode->vsync)
|
|
685 printf(" \"+VSync\"");
|
|
686 else
|
|
687 printf(" \"-VSync\"");
|
|
688 if (vmode->csync)
|
|
689 printf(" \"Composite\"");
|
|
690 if (vmode->extsync)
|
|
691 puts(" # Warning: XFree86 doesn't support extsync\n");
|
|
692 if (vmode->bcast)
|
|
693 printf(" \"bcast\"");
|
|
694 if (vmode->accel_flags)
|
|
695 puts(" # Warning: XFree86 doesn't support accel\n");
|
|
696 if (vmode->grayscale)
|
|
697 puts(" # Warning: XFree86 doesn't support grayscale\n");
|
|
698 puts("\nEndMode\n");
|
|
699 }
|
|
700 }
|
|
701
|
|
702
|
|
703 /*
|
|
704 * Display the Frame Buffer Device Information
|
|
705 */
|
|
706
|
|
707 static void DisplayFBInfo(struct fb_fix_screeninfo *fix)
|
|
708 {
|
|
709 int i;
|
|
710
|
|
711 puts("Frame buffer device information:");
|
|
712 printf(" Name : %s\n", fix->id);
|
|
713 printf(" Address : %p\n", fix->smem_start);
|
|
714 printf(" Size : %d\n", fix->smem_len);
|
|
715 printf(" Type : ");
|
|
716 switch (fix->type) {
|
|
717 case FB_TYPE_PACKED_PIXELS:
|
|
718 puts("PACKED PIXELS");
|
|
719 break;
|
|
720 case FB_TYPE_PLANES:
|
|
721 puts("PLANES");
|
|
722 break;
|
|
723 case FB_TYPE_INTERLEAVED_PLANES:
|
|
724 printf("INTERLEAVED PLANES (%d bytes interleave)\n",
|
|
725 fix->type_aux);
|
|
726 break;
|
|
727 case FB_TYPE_TEXT:
|
|
728 for (i = 0; i < sizeof(Textmodes)/sizeof(*Textmodes); i++)
|
|
729 if (fix->type_aux == Textmodes[i].id)
|
|
730 break;
|
|
731 if (i < sizeof(Textmodes)/sizeof(*Textmodes))
|
|
732 puts(Textmodes[i].name);
|
|
733 else
|
|
734 printf("Unknown text (%d)\n", fix->type_aux);
|
|
735 break;
|
|
736 case FB_TYPE_VGA_PLANES:
|
|
737 {
|
|
738 struct textentry *t;
|
|
739
|
|
740 for (t = VGAModes; t->name; t++)
|
|
741 if (fix->type_aux == t->id)
|
|
742 break;
|
|
743 if (t->name)
|
|
744 puts(t->name);
|
|
745 else
|
|
746 printf("Unknown VGA mode (%d)\n", fix->type_aux);
|
|
747 }
|
|
748 break;
|
|
749 default:
|
|
750 printf("%d (UNKNOWN)\n", fix->type);
|
|
751 printf(" Type_aux : %d\n", fix->type_aux);
|
|
752 break;
|
|
753 }
|
|
754 printf(" Visual : ");
|
|
755 switch (fix->visual) {
|
|
756 case FB_VISUAL_MONO01:
|
|
757 puts("MONO01");
|
|
758 break;
|
|
759 case FB_VISUAL_MONO10:
|
|
760 puts("MONO10");
|
|
761 break;
|
|
762 case FB_VISUAL_TRUECOLOR:
|
|
763 puts("TRUECOLOR");
|
|
764 break;
|
|
765 case FB_VISUAL_PSEUDOCOLOR:
|
|
766 puts("PSEUDOCOLOR");
|
|
767 break;
|
|
768 case FB_VISUAL_DIRECTCOLOR:
|
|
769 puts("DIRECTCOLOR");
|
|
770 break;
|
|
771 case FB_VISUAL_STATIC_PSEUDOCOLOR:
|
|
772 puts("STATIC PSEUDOCOLOR");
|
|
773 break;
|
|
774 default:
|
|
775 printf("%d (UNKNOWN)\n", fix->visual);
|
|
776 break;
|
|
777 }
|
|
778 printf(" XPanStep : %d\n", fix->xpanstep);
|
|
779 printf(" YPanStep : %d\n", fix->ypanstep);
|
|
780 printf(" YWrapStep : %d\n", fix->ywrapstep);
|
|
781 printf(" LineLength : %d\n", fix->line_length);
|
|
782 if (fix->mmio_len) {
|
|
783 printf(" MMIO Address: %p\n", fix->mmio_start);
|
|
784 printf(" MMIO Size : %d\n", fix->mmio_len);
|
|
785 }
|
|
786 printf(" Accelerator : ");
|
|
787 for (i = 0; i < sizeof(Accelerators)/sizeof(*Accelerators); i++)
|
|
788 if (fix->accel == Accelerators[i].id)
|
|
789 break;
|
|
790 if (i < sizeof(Accelerators)/sizeof(*Accelerators))
|
|
791 puts(Accelerators[i].name);
|
|
792 else
|
|
793 printf("Unknown (%d)\n", fix->accel);
|
|
794 }
|
|
795
|
|
796
|
|
797 /*
|
|
798 * Calculate the Scan Rates for a Video Mode
|
|
799 */
|
|
800
|
|
801 static int FillScanRates(struct VideoMode *vmode)
|
|
802 {
|
|
803 u_int htotal = vmode->left+vmode->xres+vmode->right+vmode->hslen;
|
|
804 u_int vtotal = vmode->upper+vmode->yres+vmode->lower+vmode->vslen;
|
|
805
|
|
806 if (vmode->dblscan)
|
|
807 vtotal <<= 2;
|
|
808 else if (!vmode->laced)
|
|
809 vtotal <<= 1;
|
|
810
|
|
811 if (!htotal || !vtotal)
|
|
812 return 0;
|
|
813
|
|
814 if (vmode->pixclock) {
|
|
815 vmode->drate = 1E12/vmode->pixclock;
|
|
816 vmode->hrate = vmode->drate/htotal;
|
|
817 vmode->vrate = vmode->hrate/vtotal*2;
|
|
818 } else {
|
|
819 vmode->drate = 0;
|
|
820 vmode->hrate = 0;
|
|
821 vmode->vrate = 0;
|
|
822 }
|
|
823
|
|
824 return 1;
|
|
825 }
|
|
826
|
|
827
|
|
828 /*
|
|
829 * Print the Usage Template and Exit
|
|
830 */
|
|
831
|
|
832 static void Usage(void)
|
|
833 {
|
|
834 puts(VERSION);
|
|
835 Die("\nUsage: %s [options] [mode]\n\n"
|
|
836 "Valid options:\n"
|
|
837 " General options:\n"
|
|
838 " -h, --help : display this usage information\n"
|
|
839 " --test : don't change, just test whether the mode is "
|
|
840 "valid\n"
|
|
841 " -s, --show : display video mode settings\n"
|
|
842 " -i, --info : display all frame buffer information\n"
|
|
843 " -v, --verbose : verbose mode\n"
|
|
844 " -V, --version : print version information\n"
|
|
845 " -x, --xfree86 : XFree86 compatibility mode\n"
|
|
846 " -a, --all : change all virtual consoles on this device\n"
|
|
847 " Frame buffer special device nodes:\n"
|
|
848 " -fb <device> : processed frame buffer device\n"
|
|
849 " (default is " DEFAULT_FRAMEBUFFER ")\n"
|
|
850 " Video mode database:\n"
|
|
851 " -db <file> : video mode database file\n"
|
|
852 " (default is " DEFAULT_MODEDBFILE ")\n"
|
|
853 " Display geometry:\n"
|
|
854 " -xres <value> : horizontal resolution (in pixels)\n"
|
|
855 " -yres <value> : vertical resolution (in pixels)\n"
|
|
856 " -vxres <value> : virtual horizontal resolution (in pixels)\n"
|
|
857 " -vyres <value> : virtual vertical resolution (in pixels)\n"
|
|
858 " -depth <value> : display depth (in bits per pixel)\n"
|
|
859 " -nonstd <value> : select nonstandard video mode\n"
|
|
860 " -g, --geometry ... : set all geometry parameters at once\n"
|
|
861 " -match : set virtual vertical resolution by virtual resolution\n"
|
|
862 " Display timings:\n"
|
|
863 " -pixclock <value> : pixel clock (in picoseconds)\n"
|
|
864 " -left <value> : left margin (in pixels)\n"
|
|
865 " -right <value> : right margin (in pixels)\n"
|
|
866 " -upper <value> : upper margin (in pixel lines)\n"
|
|
867 " -lower <value> : lower margin (in pixel lines)\n"
|
|
868 " -hslen <value> : horizontal sync length (in pixels)\n"
|
|
869 " -vslen <value> : vertical sync length (in pixel lines)\n"
|
|
870 " -t, --timings ... : set all timing parameters at once\n"
|
|
871 " Display flags:\n"
|
|
872 " -accel <value> : hardware text acceleration enable (false or "
|
|
873 "true)\n"
|
|
874 " -hsync <value> : horizontal sync polarity (low or high)\n"
|
|
875 " -vsync <value> : vertical sync polarity (low or high)\n"
|
|
876 " -csync <value> : composite sync polarity (low or high)\n"
|
|
877 " -gsync <value> : synch on green (false or true)\n"
|
|
878 " -extsync <value> : external sync enable (false or true)\n"
|
|
879 " -bcast <value> : broadcast enable (false or true)\n"
|
|
880 " -laced <value> : interlace enable (false or true)\n"
|
|
881 " -double <value> : doublescan enable (false or true)\n"
|
|
882 " -rgba <r,g,b,a> : recommended length of color entries\n"
|
|
883 " -grayscale <value> : grayscale enable (false or true)\n"
|
|
884 " Display positioning:\n"
|
|
885 " -move <direction> : move the visible part (left, right, up or "
|
|
886 "down)\n"
|
|
887 " -step <value> : step increment (in pixels or pixel lines)\n"
|
|
888 " (default is 8 horizontal, 2 vertical)\n",
|
|
889 ProgramName);
|
|
890 }
|
|
891
|
|
892
|
|
893 /*
|
|
894 * Main Routine
|
|
895 */
|
|
896
|
|
897 int main(int argc, char *argv[])
|
|
898 {
|
|
899 struct VideoMode *vmode;
|
|
900 struct fb_var_screeninfo var;
|
|
901 struct fb_fix_screeninfo fix;
|
|
902 int fh = -1, i;
|
|
903
|
|
904 ProgramName = argv[0];
|
|
905
|
|
906 /*
|
|
907 * Parse the Options
|
|
908 */
|
|
909
|
|
910 while (--argc > 0) {
|
|
911 argv++;
|
|
912 if (!strcmp(argv[0], "-h") || !strcmp(argv[0], "--help"))
|
|
913 Usage();
|
|
914 else if (!strcmp(argv[0], "-v") || !strcmp(argv[0], "--verbose"))
|
|
915 Opt_verbose = 1;
|
|
916 else if (!strcmp(argv[0], "-V") || !strcmp(argv[0], "--version"))
|
|
917 Opt_version = 1;
|
|
918 else if (!strcmp(argv[0], "--test"))
|
|
919 Opt_test = 1;
|
|
920 else if (!strcmp(argv[0], "-s") || !strcmp(argv[0], "--show"))
|
|
921 Opt_show = 1;
|
|
922 else if (!strcmp(argv[0], "-i") || !strcmp(argv[0], "--info")) {
|
|
923 Opt_show = 1;
|
|
924 Opt_info = 1;
|
|
925 } else if (!strcmp(argv[0], "-x") || !strcmp(argv[0], "--xfree86"))
|
|
926 Opt_xfree86 = 1;
|
|
927 else if (!strcmp(argv[0], "-a") || !strcmp(argv[0], "--all"))
|
|
928 Opt_all = 1;
|
|
929 else if (!strcmp(argv[0], "-g") || !strcmp(argv[0], "--geometry")) {
|
|
930 if (argc > 5) {
|
|
931 Opt_xres = argv[1];
|
|
932 Opt_yres = argv[2];
|
|
933 Opt_vxres = argv[3];
|
|
934 Opt_vyres = argv[4];
|
|
935 Opt_depth = argv[5];
|
|
936 Opt_change = 1;
|
|
937 argc -= 5;
|
|
938 argv += 5;
|
|
939 } else
|
|
940 Usage();
|
|
941 } else if (!strcmp(argv[0], "-t") || !strcmp(argv[0], "--timings")) {
|
|
942 if (argc > 7) {
|
|
943 Opt_pixclock = argv[1];
|
|
944 Opt_left = argv[2];
|
|
945 Opt_right = argv[3];
|
|
946 Opt_upper = argv[4];
|
|
947 Opt_lower = argv[5];
|
|
948 Opt_hslen = argv[6];
|
|
949 Opt_vslen = argv[7];
|
|
950 Opt_change = 1;
|
|
951 argc -= 7;
|
|
952 argv += 7;
|
|
953 } else
|
|
954 Usage();
|
|
955 } else if (!strcmp(argv[0], "-match")) {
|
|
956 Opt_matchyres = argv[0];
|
|
957 Opt_change = 1;
|
|
958 } else {
|
|
959 for (i = 0; Options[i].name; i++)
|
|
960 if (!strcmp(argv[0], Options[i].name))
|
|
961 break;
|
|
962 if (Options[i].name) {
|
|
963 if (argc-- > 1) {
|
|
964 *Options[i].value = argv[1];
|
|
965 Opt_change |= Options[i].change;
|
|
966 argv++;
|
|
967 } else
|
|
968 Usage();
|
|
969 } else if (!Opt_modename) {
|
|
970 Opt_modename = argv[0];
|
|
971 Opt_change = 1;
|
|
972 } else
|
|
973 Usage();
|
|
974 }
|
|
975 }
|
|
976
|
|
977 if (Opt_version || Opt_verbose)
|
|
978 puts(VERSION);
|
|
979
|
|
980 if (!Opt_fb)
|
|
981 Opt_fb = DEFAULT_FRAMEBUFFER;
|
|
982
|
|
983 /*
|
|
984 * Open the Frame Buffer Device
|
|
985 */
|
|
986
|
|
987 fh = OpenFrameBuffer(Opt_fb);
|
|
988
|
|
989 /*
|
|
990 * Get the Video Mode
|
|
991 */
|
|
992
|
|
993 if (Opt_modename) {
|
|
994
|
|
995 /*
|
|
996 * Read the Video Mode Database
|
|
997 */
|
|
998
|
|
999 ReadModeDB();
|
|
1000
|
|
1001 if (!(vmode = FindVideoMode(Opt_modename)))
|
|
1002 Die("Unknown video mode `%s'\n", Opt_modename);
|
|
1003
|
|
1004 Current = *vmode;
|
|
1005 if (Opt_verbose)
|
|
1006 printf("Using video mode `%s'\n", Opt_modename);
|
|
1007 } else {
|
|
1008 GetVarScreenInfo(fh, &var);
|
|
1009 ConvertToVideoMode(&var, &Current);
|
|
1010 if (Opt_verbose)
|
|
1011 printf("Using current video mode from `%s'\n", Opt_fb);
|
|
1012 }
|
|
1013
|
|
1014 if (Opt_change) {
|
|
1015
|
|
1016 /*
|
|
1017 * Optionally Modify the Video Mode
|
|
1018 */
|
|
1019
|
|
1020 ModifyVideoMode(&Current);
|
|
1021
|
|
1022 /*
|
|
1023 * Set the Video Mode
|
|
1024 */
|
|
1025
|
|
1026 ConvertFromVideoMode(&Current, &var);
|
|
1027 if (Opt_verbose)
|
|
1028 printf("Setting video mode to `%s'\n", Opt_fb);
|
|
1029 SetVarScreenInfo(fh, &var);
|
|
1030 ConvertToVideoMode(&var, &Current);
|
|
1031 }
|
|
1032
|
|
1033 /*
|
|
1034 * Display some Video Mode Information
|
|
1035 */
|
|
1036
|
|
1037 if (Opt_show || !Opt_change)
|
|
1038 DisplayVModeInfo(&Current);
|
|
1039
|
|
1040 if (Opt_info) {
|
|
1041 if (Opt_verbose)
|
|
1042 puts("Getting further frame buffer information");
|
|
1043 GetFixScreenInfo(fh, &fix);
|
|
1044 DisplayFBInfo(&fix);
|
|
1045 }
|
|
1046
|
|
1047 /*
|
|
1048 * Close the Frame Buffer Device
|
|
1049 */
|
|
1050
|
|
1051 CloseFrameBuffer(fh);
|
|
1052
|
|
1053 exit(0);
|
|
1054 }
|