/* * +-------------------------------------------------------+ * | | * | videogen | * | | * | a simple XFree86 Modeline calculator | * | (c) 1997-2002, Szabolcs Rumi | * | | * | http://www.rtfm.hu/videogen | * | | * | the videogen package is distributed under the | * | GNU General Public License Version 2 (GPLv2) | * | | * +-------------------------------------------------------+ */ #include #include #include #include #include #include "config.h" #include "videogen.h" extern FILE *yyin; extern int yyparse (void); extern int yydebug; char *cfgfile = CFG_CFGFILE; unsigned int verbose = CFG_VERBOSE; unsigned int fbset = CFG_FBSET; unsigned int nvidia = CFG_NVIDIA; unsigned int num_modes = 0; resolution_t modes[256]; double max_dotclk = 0; double max_hfreq = 0; double max_vfreq = 0; double desired_vfreq = 0; double hvisible = CFG_HORIZ_VISIBLE; double vvisible = CFG_VERT_VISIBLE; double hfporch = CFG_HORIZ_FRONT_PORCH; double hbporch = CFG_HORIZ_BACK_PORCH; double hsync = CFG_HORIZ_SYNC_PULSE; double vfporch = CFG_VERT_FRONT_PORCH; double vbporch = CFG_VERT_BACK_PORCH; double vsync = CFG_VERT_SYNC_PULSE; void banner (void) { pmsg (VL_VERBOSE, "\n +--------------------------------------------------------------+\n"); pmsg (VL_VERBOSE, " | |\n"); pmsg (VL_VERBOSE, " | videogen %s simple XFree86 Modeline calculator |\n", CFG_VIDEOGEN_VERSION); pmsg (VL_VERBOSE, " | |\n"); pmsg (VL_VERBOSE, " | by Szabolcs Rumi, (c) 1997 - 2002 |\n"); pmsg (VL_VERBOSE, " | THIS PROGRAM COMES WITH ABSOLUTELY NO WARRANTY |\n"); pmsg (VL_VERBOSE, " | for details see the GNU General Public License (GPLv2) |\n"); pmsg (VL_VERBOSE, " | |\n"); pmsg (VL_VERBOSE, " +--------------------------------------------------------------+\n\n"); } void usage (void) { pmsg (VL_QUIET, "USAGE: videogen [-h] [-v|-q] [-fb|-nfb] [-nv|-nnv] [-f=] [-m=]\n"); pmsg (VL_QUIET, " [-mdc=] [-mhf=] [-mvf=] [-dvf=] [-hv=] [-vv=]\n"); pmsg (VL_QUIET, " [-hfp=] [-hbp=] [-hsp=] [-vfp=] [-vbp=] [-vsp=]\n\n"); } int main (int argc, char **argv) { char pathname_buf[4096]; arg_parse_t ap = { 0, 0, 0, NULL, &opts }; int i; double calc_dc, calc_hf, calc_vf; unsigned int calc_hfl, calc_vfl, calc_hfp, calc_hsp, calc_hbp, calc_vfp, calc_vsp, calc_vbp; /* * reading command line parameters */ ap.argc = argc; ap.argv = argv; if (arg_parse (&ap, &arg_action) < 0) { pmsg (VL_VERBOSE, "command line syntax error\n"); exit (ERR_CMDLINE); } /* * reading config file */ if (strcmp (cfgfile, "-")) { yyin = fopen (tpathexp (cfgfile, (char *)&pathname_buf), "r"); if (yyin == NULL) { pmsg (VL_VERBOSE, "could not open configuration file \"%s\" (errno=%i)\n", cfgfile, errno); } else { pmsg (VL_VERBOSE, "reading configuration from file %s\n", cfgfile); if (yyparse () != 0) exit (ERR_CFGFILE); } } else { yyin = stdin; if (yyin == NULL) { pmsg (VL_DEBUG, "[main] stdin not open\n"); } else { pmsg (VL_VERBOSE, "reading configuration from standard input\n"); if (yyparse () != 0) exit (ERR_CFGFILE); } } /* * print out some information about the program itself (in verbose mode only) */ banner (); /* * check if the mandatory parameters are present */ if (num_modes == 0) { pmsg (VL_VERBOSE, "error: no modes (resolutions) have been specified\n"); exit (ERR_RES); } if (max_dotclk == 0) { pmsg (VL_VERBOSE, "error: the maximum dot clock rate has not been specified\n"); exit (ERR_MDC); } if (max_hfreq == 0) { pmsg (VL_VERBOSE, "error: the maximum horizontal refresh frequency has not been specified\n"); exit (ERR_MHF); } if (max_vfreq == 0) { pmsg (VL_VERBOSE, "error: the maximum vertical refresh frequency has not been specified\n"); exit (ERR_MVF); } if (desired_vfreq == 0) desired_vfreq = max_vfreq; /* * do our main job */ for (i = 0; i < num_modes; i++) { calc_vf = desired_vfreq; calc_hfl = (unsigned int)floor (modes[i].hres * 100 / hvisible / 8) * 8; if ((nvidia > 0) && (calc_hfl - modes[i].hres > CFG_NV_MAX_HBLANK)) { pmsg (VL_DEBUG, "[main] hblank: %u > %u\n", calc_hfl - modes[i].hres, CFG_NV_MAX_HBLANK); hvisible = 100 - ((100 - hvisible) * (CFG_NV_MAX_HBLANK / (calc_hfl - modes[i].hres))); calc_hfl = (unsigned int)floor (modes[i].hres * 100 / hvisible); calc_hfl = (unsigned int)floor (calc_hfl / 8) * 8; } calc_hfp = (unsigned int)floor ((calc_hfl - modes[i].hres) / 64) * 8; calc_hbp = (unsigned int)floor ((calc_hfl - modes[i].hres - calc_hfp) / 8) * 8; calc_hsp = floor (hsync * max_dotclk / 8) * 8; if ((nvidia > 0) && (calc_hsp > CFG_NV_MAX_HSP)) { /* calc_hsp is assumed to be a multiple of 8 because all values it is * calculated from are assumed to be multiples of 8. */ pmsg (VL_DEBUG, "[main] hsp: %u > %u\n", calc_hsp, CFG_NV_MAX_HSP); calc_hsp = CFG_NV_MAX_HSP; } calc_hbp -= calc_hsp; calc_vfl = (unsigned int)floor (modes[i].vres * 100 / vvisible + 0.5); if ((nvidia > 0) && (calc_vfl - modes[i].vres > CFG_NV_MAX_VBLANK)) { pmsg (VL_DEBUG, "[main] vblank: %u > %u\n", calc_vfl - modes[i].vres, CFG_NV_MAX_VBLANK); vvisible = 100 - ((100 - vvisible) * (CFG_NV_MAX_VBLANK / (calc_vfl - modes[i].vres))); calc_vfl = (unsigned int)floor (modes[i].vres * 100 / vvisible); } calc_dc = calc_vf * calc_hfl * calc_vfl / 1000000; calc_hf = (1000 * calc_dc) / calc_hfl; calc_vfp = (unsigned int)vfporch; calc_vbp = calc_vfl - modes[i].vres - calc_vfp; calc_vsp = floor (vsync * calc_hf / 1000); if ((nvidia > 0) && (calc_vsp > CFG_NV_MAX_VSP)) { /* framelength must be the same after the correction */ pmsg (VL_DEBUG, "[main] vsp: %u > %u\n", calc_vsp, CFG_NV_MAX_VSP); calc_vsp = CFG_NV_MAX_VSP; } calc_vbp -= calc_vsp; pmsg (VL_DEBUG, "[main] dump 1: visible=%ux%u frame=%ux%u\n", modes[i].hres, modes[i].vres, calc_hfl, calc_vfl); pmsg (VL_DEBUG, "[main] dump 1: dc=%f hf=%f vf=%f\n", calc_dc, calc_hf, calc_vf); pmsg (VL_DEBUG, "[main] dump 1: hsp=%u vsp=%u\n\n", calc_hsp, calc_vsp); if (calc_dc > max_dotclk) { pmsg (VL_DEBUG, "[main] dc: %f > %f\n", calc_dc, max_dotclk); calc_dc = max_dotclk; calc_vf = (1000000 * calc_dc) / (calc_hfl * calc_vfl); } calc_hf = (1000 * calc_dc) / calc_hfl; pmsg (VL_DEBUG, "[main] dump 2: visible=%ux%u frame=%ux%u\n", modes[i].hres, modes[i].vres, calc_hfl, calc_vfl); pmsg (VL_DEBUG, "[main] dump 2: dc=%f hf=%f vf=%f\n", calc_dc, calc_hf, calc_vf); pmsg (VL_DEBUG, "[main] dump 2: hsp=%u vsp=%u\n\n", calc_hsp, calc_vsp); if (calc_hf > max_hfreq) { pmsg (VL_DEBUG, "[main] hf: %f > %f\n", calc_hf, max_hfreq); calc_hf = max_hfreq; calc_dc = calc_hf * calc_hfl / 1000; calc_vf = (1000000 * calc_dc) / (calc_hfl * calc_vfl); } pmsg (VL_DEBUG, "[main] dump 3: visible=%ux%u frame=%ux%u\n", modes[i].hres, modes[i].vres, calc_hfl, calc_vfl); pmsg (VL_DEBUG, "[main] dump 3: dc=%f hf=%f vf=%f\n", calc_dc, calc_hf, calc_vf); pmsg (VL_DEBUG, "[main] dump 3: hsp=%u vsp=%u\n\n", calc_hsp, calc_vsp); /* * printing out the results */ if (fbset == 0) { fprintf (stdout, "Modeline \"%ux%u\" %0.2f %u %u %u %u %u %u %u %u # %0.0f MHz, %0.1f kHz, %0.1f Hz\n", modes[i].hres, modes[i].vres, calc_dc, modes[i].hres, modes[i].hres + calc_hfp, modes[i].hres + calc_hfp + calc_hsp, modes[i].hres + calc_hfp + calc_hsp + calc_hbp, modes[i].vres, modes[i].vres + calc_vfp, modes[i].vres + calc_vfp + calc_vsp, modes[i].vres + calc_vfp + calc_vsp + calc_vbp, calc_dc, calc_hf, calc_vf); } else { fprintf (stdout, "timings %0.0f %u %u %u %u %u %u # %0.0f MHz, %0.1f kHz, %0.1f Hz\n", 1000000 / calc_dc, calc_hbp, calc_hfp, calc_vbp, calc_vfp, calc_hsp, calc_vsp, calc_dc, calc_hf, calc_vf); } } return (0); } /* EOF */