2  * linux/drivers/video/fbmon.c
 
   4  * Copyright (C) 2002 James Simmons <jsimmons@users.sf.net>
 
   8  * The EDID Parser is a conglomeration from the following sources:
 
  10  *   1. SciTech SNAP Graphics Architecture
 
  11  *      Copyright (C) 1991-2002 SciTech Software, Inc. All rights reserved.
 
  13  *   2. XFree86 4.3.0, interpret_edid.c
 
  14  *      Copyright 1998 by Egbert Eich <Egbert.Eich@Physik.TU-Darmstadt.DE>
 
  16  *   3. John Fremlin <vii@users.sourceforge.net> and 
 
  17  *      Ani Joshi <ajoshi@unixbox.com>
 
  19  * Generalized Timing Formula is derived from:
 
  21  *      GTF Spreadsheet by Andy Morrish (1/5/97) 
 
  22  *      available at http://www.vesa.org
 
  24  * This file is subject to the terms and conditions of the GNU General Public
 
  25  * License.  See the file COPYING in the main directory of this archive
 
  30 #include <linux/module.h>
 
  31 #include <linux/pci.h>
 
  32 #include <video/edid.h>
 
  35 #include <asm/pci-bridge.h>
 
  43 #undef DEBUG  /* define this for verbose EDID parsing output */
 
  46 #define DPRINTK(fmt, args...) printk(fmt,## args)
 
  48 #define DPRINTK(fmt, args...)
 
  51 #define FBMON_FIX_HEADER  1
 
  52 #define FBMON_FIX_INPUT   2
 
  53 #define FBMON_FIX_TIMINGS 3
 
  55 #ifdef CONFIG_FB_MODE_HELPERS
 
  62 static const struct broken_edid brokendb[] = {
 
  65                 .manufacturer = "DEC",
 
  67                 .fix          = FBMON_FIX_HEADER,
 
  69         /* ViewSonic PF775a */
 
  71                 .manufacturer = "VSC",
 
  73                 .fix          = FBMON_FIX_INPUT,
 
  77                 .manufacturer = "SHP",
 
  79                 .fix          = FBMON_FIX_TIMINGS,
 
  83 static const unsigned char edid_v1_header[] = { 0x00, 0xff, 0xff, 0xff,
 
  84         0xff, 0xff, 0xff, 0x00
 
  87 static void copy_string(unsigned char *c, unsigned char *s)
 
  91   for (i = 0; (i < 13 && *c != 0x0A); i++)
 
  94   while (i-- && (*--s == 0x20)) *s = 0;
 
  97 static int edid_is_serial_block(unsigned char *block)
 
  99         if ((block[0] == 0x00) && (block[1] == 0x00) &&
 
 100             (block[2] == 0x00) && (block[3] == 0xff) &&
 
 107 static int edid_is_ascii_block(unsigned char *block)
 
 109         if ((block[0] == 0x00) && (block[1] == 0x00) &&
 
 110             (block[2] == 0x00) && (block[3] == 0xfe) &&
 
 117 static int edid_is_limits_block(unsigned char *block)
 
 119         if ((block[0] == 0x00) && (block[1] == 0x00) &&
 
 120             (block[2] == 0x00) && (block[3] == 0xfd) &&
 
 127 static int edid_is_monitor_block(unsigned char *block)
 
 129         if ((block[0] == 0x00) && (block[1] == 0x00) &&
 
 130             (block[2] == 0x00) && (block[3] == 0xfc) &&
 
 137 static int edid_is_timing_block(unsigned char *block)
 
 139         if ((block[0] != 0x00) || (block[1] != 0x00) ||
 
 140             (block[2] != 0x00) || (block[4] != 0x00))
 
 146 static int check_edid(unsigned char *edid)
 
 148         unsigned char *block = edid + ID_MANUFACTURER_NAME, manufacturer[4];
 
 151         int i, fix = 0, ret = 0;
 
 153         manufacturer[0] = ((block[0] & 0x7c) >> 2) + '@';
 
 154         manufacturer[1] = ((block[0] & 0x03) << 3) +
 
 155                 ((block[1] & 0xe0) >> 5) + '@';
 
 156         manufacturer[2] = (block[1] & 0x1f) + '@';
 
 158         model = block[2] + (block[3] << 8);
 
 160         for (i = 0; i < ARRAY_SIZE(brokendb); i++) {
 
 161                 if (!strncmp(manufacturer, brokendb[i].manufacturer, 4) &&
 
 162                         brokendb[i].model == model) {
 
 163                         fix = brokendb[i].fix;
 
 169         case FBMON_FIX_HEADER:
 
 170                 for (i = 0; i < 8; i++) {
 
 171                         if (edid[i] != edid_v1_header[i]) {
 
 177         case FBMON_FIX_INPUT:
 
 178                 b = edid + EDID_STRUCT_DISPLAY;
 
 179                 /* Only if display is GTF capable will
 
 180                    the input type be reset to analog */
 
 181                 if (b[4] & 0x01 && b[0] & 0x80)
 
 184         case FBMON_FIX_TIMINGS:
 
 185                 b = edid + DETAILED_TIMING_DESCRIPTIONS_START;
 
 188                 for (i = 0; i < 4; i++) {
 
 189                         if (edid_is_limits_block(b)) {
 
 194                         b += DETAILED_TIMING_DESCRIPTION_SIZE;
 
 201                 printk("fbmon: The EDID Block of "
 
 202                        "Manufacturer: %s Model: 0x%x is known to "
 
 203                        "be broken,\n",  manufacturer, model);
 
 208 static void fix_edid(unsigned char *edid, int fix)
 
 211         unsigned char *b, csum = 0;
 
 214         case FBMON_FIX_HEADER:
 
 215                 printk("fbmon: trying a header reconstruct\n");
 
 216                 memcpy(edid, edid_v1_header, 8);
 
 218         case FBMON_FIX_INPUT:
 
 219                 printk("fbmon: trying to fix input type\n");
 
 220                 b = edid + EDID_STRUCT_DISPLAY;
 
 224         case FBMON_FIX_TIMINGS:
 
 225                 printk("fbmon: trying to fix monitor timings\n");
 
 226                 b = edid + DETAILED_TIMING_DESCRIPTIONS_START;
 
 227                 for (i = 0; i < 4; i++) {
 
 228                         if (!(edid_is_serial_block(b) ||
 
 229                               edid_is_ascii_block(b) ||
 
 230                               edid_is_monitor_block(b) ||
 
 231                               edid_is_timing_block(b))) {
 
 237                                 b[5] = 60;   /* vfmin */
 
 238                                 b[6] = 60;   /* vfmax */
 
 239                                 b[7] = 30;   /* hfmin */
 
 240                                 b[8] = 75;   /* hfmax */
 
 241                                 b[9] = 17;   /* pixclock - 170 MHz*/
 
 246                         b += DETAILED_TIMING_DESCRIPTION_SIZE;
 
 249                 for (i = 0; i < EDID_LENGTH - 1; i++)
 
 252                 edid[127] = 256 - csum;
 
 257 static int edid_checksum(unsigned char *edid)
 
 259         unsigned char i, csum = 0, all_null = 0;
 
 260         int err = 0, fix = check_edid(edid);
 
 265         for (i = 0; i < EDID_LENGTH; i++) {
 
 270         if (csum == 0x00 && all_null) {
 
 271                 /* checksum passed, everything's good */
 
 278 static int edid_check_header(unsigned char *edid)
 
 280         int i, err = 1, fix = check_edid(edid);
 
 285         for (i = 0; i < 8; i++) {
 
 286                 if (edid[i] != edid_v1_header[i])
 
 293 static void parse_vendor_block(unsigned char *block, struct fb_monspecs *specs)
 
 295         specs->manufacturer[0] = ((block[0] & 0x7c) >> 2) + '@';
 
 296         specs->manufacturer[1] = ((block[0] & 0x03) << 3) +
 
 297                 ((block[1] & 0xe0) >> 5) + '@';
 
 298         specs->manufacturer[2] = (block[1] & 0x1f) + '@';
 
 299         specs->manufacturer[3] = 0;
 
 300         specs->model = block[2] + (block[3] << 8);
 
 301         specs->serial = block[4] + (block[5] << 8) +
 
 302                (block[6] << 16) + (block[7] << 24);
 
 303         specs->year = block[9] + 1990;
 
 304         specs->week = block[8];
 
 305         DPRINTK("   Manufacturer: %s\n", specs->manufacturer);
 
 306         DPRINTK("   Model: %x\n", specs->model);
 
 307         DPRINTK("   Serial#: %u\n", specs->serial);
 
 308         DPRINTK("   Year: %u Week %u\n", specs->year, specs->week);
 
 311 static void get_dpms_capabilities(unsigned char flags,
 
 312                                   struct fb_monspecs *specs)
 
 315         if (flags & DPMS_ACTIVE_OFF)
 
 316                 specs->dpms |= FB_DPMS_ACTIVE_OFF;
 
 317         if (flags & DPMS_SUSPEND)
 
 318                 specs->dpms |= FB_DPMS_SUSPEND;
 
 319         if (flags & DPMS_STANDBY)
 
 320                 specs->dpms |= FB_DPMS_STANDBY;
 
 321         DPRINTK("      DPMS: Active %s, Suspend %s, Standby %s\n",
 
 322                (flags & DPMS_ACTIVE_OFF) ? "yes" : "no",
 
 323                (flags & DPMS_SUSPEND)    ? "yes" : "no",
 
 324                (flags & DPMS_STANDBY)    ? "yes" : "no");
 
 327 static void get_chroma(unsigned char *block, struct fb_monspecs *specs)
 
 331         DPRINTK("      Chroma\n");
 
 332         /* Chromaticity data */
 
 333         tmp = ((block[5] & (3 << 6)) >> 6) | (block[0x7] << 2);
 
 336         specs->chroma.redx = tmp/1024;
 
 337         DPRINTK("         RedX:     0.%03d ", specs->chroma.redx);
 
 339         tmp = ((block[5] & (3 << 4)) >> 4) | (block[0x8] << 2);
 
 342         specs->chroma.redy = tmp/1024;
 
 343         DPRINTK("RedY:     0.%03d\n", specs->chroma.redy);
 
 345         tmp = ((block[5] & (3 << 2)) >> 2) | (block[0x9] << 2);
 
 348         specs->chroma.greenx = tmp/1024;
 
 349         DPRINTK("         GreenX:   0.%03d ", specs->chroma.greenx);
 
 351         tmp = (block[5] & 3) | (block[0xa] << 2);
 
 354         specs->chroma.greeny = tmp/1024;
 
 355         DPRINTK("GreenY:   0.%03d\n", specs->chroma.greeny);
 
 357         tmp = ((block[6] & (3 << 6)) >> 6) | (block[0xb] << 2);
 
 360         specs->chroma.bluex = tmp/1024;
 
 361         DPRINTK("         BlueX:    0.%03d ", specs->chroma.bluex);
 
 363         tmp = ((block[6] & (3 << 4)) >> 4) | (block[0xc] << 2);
 
 366         specs->chroma.bluey = tmp/1024;
 
 367         DPRINTK("BlueY:    0.%03d\n", specs->chroma.bluey);
 
 369         tmp = ((block[6] & (3 << 2)) >> 2) | (block[0xd] << 2);
 
 372         specs->chroma.whitex = tmp/1024;
 
 373         DPRINTK("         WhiteX:   0.%03d ", specs->chroma.whitex);
 
 375         tmp = (block[6] & 3) | (block[0xe] << 2);
 
 378         specs->chroma.whitey = tmp/1024;
 
 379         DPRINTK("WhiteY:   0.%03d\n", specs->chroma.whitey);
 
 382 static void calc_mode_timings(int xres, int yres, int refresh,
 
 383                               struct fb_videomode *mode)
 
 385         struct fb_var_screeninfo *var;
 
 387         var = kzalloc(sizeof(struct fb_var_screeninfo), GFP_KERNEL);
 
 392                 fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON,
 
 396                 mode->pixclock = var->pixclock;
 
 397                 mode->refresh = refresh;
 
 398                 mode->left_margin = var->left_margin;
 
 399                 mode->right_margin = var->right_margin;
 
 400                 mode->upper_margin = var->upper_margin;
 
 401                 mode->lower_margin = var->lower_margin;
 
 402                 mode->hsync_len = var->hsync_len;
 
 403                 mode->vsync_len = var->vsync_len;
 
 410 static int get_est_timing(unsigned char *block, struct fb_videomode *mode)
 
 417                 calc_mode_timings(720, 400, 70, &mode[num]);
 
 418                 mode[num++].flag = FB_MODE_IS_CALCULATED;
 
 419                 DPRINTK("      720x400@70Hz\n");
 
 422                 calc_mode_timings(720, 400, 88, &mode[num]);
 
 423                 mode[num++].flag = FB_MODE_IS_CALCULATED;
 
 424                 DPRINTK("      720x400@88Hz\n");
 
 427                 mode[num++] = vesa_modes[3];
 
 428                 DPRINTK("      640x480@60Hz\n");
 
 431                 calc_mode_timings(640, 480, 67, &mode[num]);
 
 432                 mode[num++].flag = FB_MODE_IS_CALCULATED;
 
 433                 DPRINTK("      640x480@67Hz\n");
 
 436                 mode[num++] = vesa_modes[4];
 
 437                 DPRINTK("      640x480@72Hz\n");
 
 440                 mode[num++] = vesa_modes[5];
 
 441                 DPRINTK("      640x480@75Hz\n");
 
 444                 mode[num++] = vesa_modes[7];
 
 445                 DPRINTK("      800x600@56Hz\n");
 
 448                 mode[num++] = vesa_modes[8];
 
 449                 DPRINTK("      800x600@60Hz\n");
 
 454                 mode[num++] = vesa_modes[9];
 
 455                 DPRINTK("      800x600@72Hz\n");
 
 458                 mode[num++] = vesa_modes[10];
 
 459                 DPRINTK("      800x600@75Hz\n");
 
 462                 calc_mode_timings(832, 624, 75, &mode[num]);
 
 463                 mode[num++].flag = FB_MODE_IS_CALCULATED;
 
 464                 DPRINTK("      832x624@75Hz\n");
 
 467                 mode[num++] = vesa_modes[12];
 
 468                 DPRINTK("      1024x768@87Hz Interlaced\n");
 
 471                 mode[num++] = vesa_modes[13];
 
 472                 DPRINTK("      1024x768@60Hz\n");
 
 475                 mode[num++] = vesa_modes[14];
 
 476                 DPRINTK("      1024x768@70Hz\n");
 
 479                 mode[num++] = vesa_modes[15];
 
 480                 DPRINTK("      1024x768@75Hz\n");
 
 483                 mode[num++] = vesa_modes[21];
 
 484                 DPRINTK("      1280x1024@75Hz\n");
 
 488                 mode[num++] = vesa_modes[17];
 
 489                 DPRINTK("      1152x870@75Hz\n");
 
 491         DPRINTK("      Manufacturer's mask: %x\n",c&0x7F);
 
 495 static int get_std_timing(unsigned char *block, struct fb_videomode *mode)
 
 497         int xres, yres = 0, refresh, ratio, i;
 
 499         xres = (block[0] + 31) * 8;
 
 503         ratio = (block[1] & 0xc0) >> 6;
 
 515                 yres = (xres * 9)/16;
 
 518         refresh = (block[1] & 0x3f) + 60;
 
 520         DPRINTK("      %dx%d@%dHz\n", xres, yres, refresh);
 
 521         for (i = 0; i < VESA_MODEDB_SIZE; i++) {
 
 522                 if (vesa_modes[i].xres == xres && 
 
 523                     vesa_modes[i].yres == yres &&
 
 524                     vesa_modes[i].refresh == refresh) {
 
 525                         *mode = vesa_modes[i];
 
 526                         mode->flag |= FB_MODE_IS_STANDARD;
 
 530         calc_mode_timings(xres, yres, refresh, mode);
 
 534 static int get_dst_timing(unsigned char *block,
 
 535                           struct fb_videomode *mode)
 
 539         for (j = 0; j < 6; j++, block+= STD_TIMING_DESCRIPTION_SIZE) 
 
 540                 num += get_std_timing(block, &mode[num]);
 
 545 static void get_detailed_timing(unsigned char *block, 
 
 546                                 struct fb_videomode *mode)
 
 548         mode->xres = H_ACTIVE;
 
 549         mode->yres = V_ACTIVE;
 
 550         mode->pixclock = PIXEL_CLOCK;
 
 551         mode->pixclock /= 1000;
 
 552         mode->pixclock = KHZ2PICOS(mode->pixclock);
 
 553         mode->right_margin = H_SYNC_OFFSET;
 
 554         mode->left_margin = (H_ACTIVE + H_BLANKING) -
 
 555                 (H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH);
 
 556         mode->upper_margin = V_BLANKING - V_SYNC_OFFSET - 
 
 558         mode->lower_margin = V_SYNC_OFFSET;
 
 559         mode->hsync_len = H_SYNC_WIDTH;
 
 560         mode->vsync_len = V_SYNC_WIDTH;
 
 562                 mode->sync |= FB_SYNC_HOR_HIGH_ACT;
 
 564                 mode->sync |= FB_SYNC_VERT_HIGH_ACT;
 
 565         mode->refresh = PIXEL_CLOCK/((H_ACTIVE + H_BLANKING) *
 
 566                                      (V_ACTIVE + V_BLANKING));
 
 568         mode->flag = FB_MODE_IS_DETAILED;
 
 570         DPRINTK("      %d MHz ",  PIXEL_CLOCK/1000000);
 
 571         DPRINTK("%d %d %d %d ", H_ACTIVE, H_ACTIVE + H_SYNC_OFFSET,
 
 572                H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH, H_ACTIVE + H_BLANKING);
 
 573         DPRINTK("%d %d %d %d ", V_ACTIVE, V_ACTIVE + V_SYNC_OFFSET,
 
 574                V_ACTIVE + V_SYNC_OFFSET + V_SYNC_WIDTH, V_ACTIVE + V_BLANKING);
 
 575         DPRINTK("%sHSync %sVSync\n\n", (HSYNC_POSITIVE) ? "+" : "-",
 
 576                (VSYNC_POSITIVE) ? "+" : "-");
 
 580  * fb_create_modedb - create video mode database
 
 582  * @dbsize: database size
 
 584  * RETURNS: struct fb_videomode, @dbsize contains length of database
 
 587  * This function builds a mode database using the contents of the EDID
 
 590 static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize)
 
 592         struct fb_videomode *mode, *m;
 
 593         unsigned char *block;
 
 594         int num = 0, i, first = 1;
 
 596         mode = kzalloc(50 * sizeof(struct fb_videomode), GFP_KERNEL);
 
 600         if (edid == NULL || !edid_checksum(edid) || 
 
 601             !edid_check_header(edid)) {
 
 608         DPRINTK("   Detailed Timings\n");
 
 609         block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
 
 610         for (i = 0; i < 4; i++, block+= DETAILED_TIMING_DESCRIPTION_SIZE) {
 
 611                 if (!(block[0] == 0x00 && block[1] == 0x00)) {
 
 612                         get_detailed_timing(block, &mode[num]);
 
 614                                 mode[num].flag |= FB_MODE_IS_FIRST;
 
 621         DPRINTK("   Supported VESA Modes\n");
 
 622         block = edid + ESTABLISHED_TIMING_1;
 
 623         num += get_est_timing(block, &mode[num]);
 
 625         DPRINTK("   Standard Timings\n");
 
 626         block = edid + STD_TIMING_DESCRIPTIONS_START;
 
 627         for (i = 0; i < STD_TIMING; i++, block += STD_TIMING_DESCRIPTION_SIZE)
 
 628                 num += get_std_timing(block, &mode[num]);
 
 630         block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
 
 631         for (i = 0; i < 4; i++, block+= DETAILED_TIMING_DESCRIPTION_SIZE) {
 
 632                 if (block[0] == 0x00 && block[1] == 0x00 && block[3] == 0xfa)
 
 633                         num += get_dst_timing(block + 5, &mode[num]);
 
 636         /* Yikes, EDID data is totally useless */
 
 643         m = kmalloc(num * sizeof(struct fb_videomode), GFP_KERNEL);
 
 646         memmove(m, mode, num * sizeof(struct fb_videomode));
 
 652  * fb_destroy_modedb - destroys mode database
 
 653  * @modedb: mode database to destroy
 
 656  * Destroy mode database created by fb_create_modedb
 
 658 void fb_destroy_modedb(struct fb_videomode *modedb)
 
 663 static int fb_get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs)
 
 666         unsigned char *block;
 
 668         block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
 
 670         DPRINTK("      Monitor Operating Limits: ");
 
 672         for (i = 0; i < 4; i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) {
 
 673                 if (edid_is_limits_block(block)) {
 
 674                         specs->hfmin = H_MIN_RATE * 1000;
 
 675                         specs->hfmax = H_MAX_RATE * 1000;
 
 676                         specs->vfmin = V_MIN_RATE;
 
 677                         specs->vfmax = V_MAX_RATE;
 
 678                         specs->dclkmax = MAX_PIXEL_CLOCK * 1000000;
 
 679                         specs->gtf = (GTF_SUPPORT) ? 1 : 0;
 
 681                         DPRINTK("From EDID\n");
 
 686         /* estimate monitor limits based on modes supported */
 
 688                 struct fb_videomode *modes, *mode;
 
 689                 int num_modes, i, hz, hscan, pixclock;
 
 692                 modes = fb_create_modedb(edid, &num_modes);
 
 694                         DPRINTK("None Available\n");
 
 699                 for (i = 0; i < num_modes; i++) {
 
 701                         pixclock = PICOS2KHZ(modes[i].pixclock) * 1000;
 
 702                         htotal = mode->xres + mode->right_margin + mode->hsync_len
 
 704                         vtotal = mode->yres + mode->lower_margin + mode->vsync_len
 
 705                                 + mode->upper_margin;
 
 707                         if (mode->vmode & FB_VMODE_INTERLACED)
 
 710                         if (mode->vmode & FB_VMODE_DOUBLE)
 
 713                         hscan = (pixclock + htotal / 2) / htotal;
 
 714                         hscan = (hscan + 500) / 1000 * 1000;
 
 715                         hz = (hscan + vtotal / 2) / vtotal;
 
 717                         if (specs->dclkmax == 0 || specs->dclkmax < pixclock)
 
 718                                 specs->dclkmax = pixclock;
 
 720                         if (specs->dclkmin == 0 || specs->dclkmin > pixclock)
 
 721                                 specs->dclkmin = pixclock;
 
 723                         if (specs->hfmax == 0 || specs->hfmax < hscan)
 
 724                                 specs->hfmax = hscan;
 
 726                         if (specs->hfmin == 0 || specs->hfmin > hscan)
 
 727                                 specs->hfmin = hscan;
 
 729                         if (specs->vfmax == 0 || specs->vfmax < hz)
 
 732                         if (specs->vfmin == 0 || specs->vfmin > hz)
 
 735                 DPRINTK("Extrapolated\n");
 
 736                 fb_destroy_modedb(modes);
 
 738         DPRINTK("           H: %d-%dKHz V: %d-%dHz DCLK: %dMHz\n",
 
 739                 specs->hfmin/1000, specs->hfmax/1000, specs->vfmin,
 
 740                 specs->vfmax, specs->dclkmax/1000000);
 
 744 static void get_monspecs(unsigned char *edid, struct fb_monspecs *specs)
 
 746         unsigned char c, *block;
 
 748         block = edid + EDID_STRUCT_DISPLAY;
 
 750         fb_get_monitor_limits(edid, specs);
 
 755                 specs->input |= FB_DISP_DDI;
 
 756                 DPRINTK("      Digital Display Input");
 
 758                 DPRINTK("      Analog Display Input: Input Voltage - ");
 
 759                 switch ((block[0] & 0x60) >> 5) {
 
 761                         DPRINTK("0.700V/0.300V");
 
 762                         specs->input |= FB_DISP_ANA_700_300;
 
 765                         DPRINTK("0.714V/0.286V");
 
 766                         specs->input |= FB_DISP_ANA_714_286;
 
 769                         DPRINTK("1.000V/0.400V");
 
 770                         specs->input |= FB_DISP_ANA_1000_400;
 
 773                         DPRINTK("0.700V/0.000V");
 
 774                         specs->input |= FB_DISP_ANA_700_000;
 
 778         DPRINTK("\n      Sync: ");
 
 781                 DPRINTK("      Configurable signal level\n");
 
 785                 DPRINTK("Blank to Blank ");
 
 786                 specs->signal |= FB_SIGNAL_BLANK_BLANK;
 
 789                 DPRINTK("Separate ");
 
 790                 specs->signal |= FB_SIGNAL_SEPARATE;
 
 793                 DPRINTK("Composite ");
 
 794                 specs->signal |= FB_SIGNAL_COMPOSITE;
 
 797                 DPRINTK("Sync on Green ");
 
 798                 specs->signal |= FB_SIGNAL_SYNC_ON_GREEN;
 
 801                 DPRINTK("Serration on ");
 
 802                 specs->signal |= FB_SIGNAL_SERRATION_ON;
 
 805         specs->max_x = block[1];
 
 806         specs->max_y = block[2];
 
 807         DPRINTK("      Max H-size in cm: ");
 
 809                 DPRINTK("%d\n", specs->max_x);
 
 811                 DPRINTK("variable\n");
 
 812         DPRINTK("      Max V-size in cm: ");
 
 814                 DPRINTK("%d\n", specs->max_y);
 
 816                 DPRINTK("variable\n");
 
 819         specs->gamma = c+100;
 
 821         DPRINTK("%d.%d\n", specs->gamma/100, specs->gamma % 100);
 
 823         get_dpms_capabilities(block[4], specs);
 
 825         switch ((block[4] & 0x18) >> 3) {
 
 827                 DPRINTK("      Monochrome/Grayscale\n");
 
 828                 specs->input |= FB_DISP_MONO;
 
 831                 DPRINTK("      RGB Color Display\n");
 
 832                 specs->input |= FB_DISP_RGB;
 
 835                 DPRINTK("      Non-RGB Multicolor Display\n");
 
 836                 specs->input |= FB_DISP_MULTI;
 
 839                 DPRINTK("      Unknown\n");
 
 840                 specs->input |= FB_DISP_UNKNOWN;
 
 844         get_chroma(block, specs);
 
 849                 DPRINTK("      Default color format is primary\n");
 
 850                 specs->misc |= FB_MISC_PRIM_COLOR;
 
 853                 DPRINTK("      First DETAILED Timing is preferred\n");
 
 854                 specs->misc |= FB_MISC_1ST_DETAIL;
 
 857                 printk("      Display is GTF capable\n");
 
 862 int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
 
 865         unsigned char *block;
 
 867         if (edid == NULL || var == NULL)
 
 870         if (!(edid_checksum(edid)))
 
 873         if (!(edid_check_header(edid)))
 
 876         block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
 
 878         for (i = 0; i < 4; i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) {
 
 879                 if (edid_is_timing_block(block)) {
 
 880                         var->xres = var->xres_virtual = H_ACTIVE;
 
 881                         var->yres = var->yres_virtual = V_ACTIVE;
 
 882                         var->height = var->width = -1;
 
 883                         var->right_margin = H_SYNC_OFFSET;
 
 884                         var->left_margin = (H_ACTIVE + H_BLANKING) -
 
 885                                 (H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH);
 
 886                         var->upper_margin = V_BLANKING - V_SYNC_OFFSET -
 
 888                         var->lower_margin = V_SYNC_OFFSET;
 
 889                         var->hsync_len = H_SYNC_WIDTH;
 
 890                         var->vsync_len = V_SYNC_WIDTH;
 
 891                         var->pixclock = PIXEL_CLOCK;
 
 892                         var->pixclock /= 1000;
 
 893                         var->pixclock = KHZ2PICOS(var->pixclock);
 
 896                                 var->sync |= FB_SYNC_HOR_HIGH_ACT;
 
 898                                 var->sync |= FB_SYNC_VERT_HIGH_ACT;
 
 905 void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs)
 
 907         unsigned char *block;
 
 913         if (!(edid_checksum(edid)))
 
 916         if (!(edid_check_header(edid)))
 
 919         memset(specs, 0, sizeof(struct fb_monspecs));
 
 921         specs->version = edid[EDID_STRUCT_VERSION];
 
 922         specs->revision = edid[EDID_STRUCT_REVISION];
 
 924         DPRINTK("========================================\n");
 
 925         DPRINTK("Display Information (EDID)\n");
 
 926         DPRINTK("========================================\n");
 
 927         DPRINTK("   EDID Version %d.%d\n", (int) specs->version,
 
 928                (int) specs->revision);
 
 930         parse_vendor_block(edid + ID_MANUFACTURER_NAME, specs);
 
 932         block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
 
 933         for (i = 0; i < 4; i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) {
 
 934                 if (edid_is_serial_block(block)) {
 
 935                         copy_string(block, specs->serial_no);
 
 936                         DPRINTK("   Serial Number: %s\n", specs->serial_no);
 
 937                 } else if (edid_is_ascii_block(block)) {
 
 938                         copy_string(block, specs->ascii);
 
 939                         DPRINTK("   ASCII Block: %s\n", specs->ascii);
 
 940                 } else if (edid_is_monitor_block(block)) {
 
 941                         copy_string(block, specs->monitor);
 
 942                         DPRINTK("   Monitor Name: %s\n", specs->monitor);
 
 946         DPRINTK("   Display Characteristics:\n");
 
 947         get_monspecs(edid, specs);
 
 949         specs->modedb = fb_create_modedb(edid, &specs->modedb_len);
 
 952          * Workaround for buggy EDIDs that sets that the first
 
 953          * detailed timing is preferred but has not detailed
 
 956         for (i = 0; i < specs->modedb_len; i++) {
 
 957                 if (specs->modedb[i].flag & FB_MODE_IS_DETAILED) {
 
 964                 specs->misc &= ~FB_MISC_1ST_DETAIL;
 
 966         DPRINTK("========================================\n");
 
 970  * VESA Generalized Timing Formula (GTF) 
 
 974 #define V_FRONTPORCH                1
 
 976 #define H_SCALEFACTOR               20
 
 977 #define H_BLANKSCALE                128
 
 978 #define H_GRADIENT                  600
 
 982 struct __fb_timings {
 
 995  * fb_get_vblank - get vertical blank time
 
 996  * @hfreq: horizontal freq
 
 999  * vblank = right_margin + vsync_len + left_margin 
 
1001  *    given: right_margin = 1 (V_FRONTPORCH)
 
1006  *           left_margin  = --------------- - vsync_len
 
1009 static u32 fb_get_vblank(u32 hfreq)
 
1013         vblank = (hfreq * FLYBACK)/1000; 
 
1014         vblank = (vblank + 500)/1000;
 
1015         return (vblank + V_FRONTPORCH);
 
1019  * fb_get_hblank_by_freq - get horizontal blank time given hfreq
 
1020  * @hfreq: horizontal freq
 
1021  * @xres: horizontal resolution in pixels
 
1026  * hblank = ------------------
 
1029  * duty cycle = percent of htotal assigned to inactive display
 
1030  * duty cycle = C - (M/Hfreq)
 
1032  * where: C = ((offset - scale factor) * blank_scale)
 
1033  *            -------------------------------------- + scale factor
 
1035  *        M = blank_scale * gradient
 
1038 static u32 fb_get_hblank_by_hfreq(u32 hfreq, u32 xres)
 
1040         u32 c_val, m_val, duty_cycle, hblank;
 
1042         c_val = (((H_OFFSET - H_SCALEFACTOR) * H_BLANKSCALE)/256 + 
 
1043                  H_SCALEFACTOR) * 1000;
 
1044         m_val = (H_BLANKSCALE * H_GRADIENT)/256;
 
1045         m_val = (m_val * 1000000)/hfreq;
 
1046         duty_cycle = c_val - m_val;
 
1047         hblank = (xres * duty_cycle)/(100000 - duty_cycle);
 
1052  * fb_get_hblank_by_dclk - get horizontal blank time given pixelclock
 
1053  * @dclk: pixelclock in Hz
 
1054  * @xres: horizontal resolution in pixels
 
1059  * hblank = ------------------
 
1062  * duty cycle = percent of htotal assigned to inactive display
 
1063  * duty cycle = C - (M * h_period)
 
1065  * where: h_period = SQRT(100 - C + (0.4 * xres * M)/dclk) + C - 100
 
1066  *                   -----------------------------------------------
 
1072 static u32 fb_get_hblank_by_dclk(u32 dclk, u32 xres)
 
1074         u32 duty_cycle, h_period, hblank;
 
1077         h_period = 100 - C_VAL;
 
1078         h_period *= h_period;
 
1079         h_period += (M_VAL * xres * 2 * 1000)/(5 * dclk);
 
1082         h_period = int_sqrt(h_period);
 
1083         h_period -= (100 - C_VAL) * 100;
 
1085         h_period /= 2 * M_VAL;
 
1087         duty_cycle = C_VAL * 1000 - (M_VAL * h_period)/100;
 
1088         hblank = (xres * duty_cycle)/(100000 - duty_cycle) + 8;
 
1094  * fb_get_hfreq - estimate hsync
 
1095  * @vfreq: vertical refresh rate
 
1096  * @yres: vertical resolution
 
1100  *          (yres + front_port) * vfreq * 1000000
 
1101  * hfreq = -------------------------------------
 
1102  *          (1000000 - (vfreq * FLYBACK)
 
1106 static u32 fb_get_hfreq(u32 vfreq, u32 yres)
 
1110         divisor = (1000000 - (vfreq * FLYBACK))/1000;
 
1111         hfreq = (yres + V_FRONTPORCH) * vfreq  * 1000;
 
1112         return (hfreq/divisor);
 
1115 static void fb_timings_vfreq(struct __fb_timings *timings)
 
1117         timings->hfreq = fb_get_hfreq(timings->vfreq, timings->vactive);
 
1118         timings->vblank = fb_get_vblank(timings->hfreq);
 
1119         timings->vtotal = timings->vactive + timings->vblank;
 
1120         timings->hblank = fb_get_hblank_by_hfreq(timings->hfreq, 
 
1122         timings->htotal = timings->hactive + timings->hblank;
 
1123         timings->dclk = timings->htotal * timings->hfreq;
 
1126 static void fb_timings_hfreq(struct __fb_timings *timings)
 
1128         timings->vblank = fb_get_vblank(timings->hfreq);
 
1129         timings->vtotal = timings->vactive + timings->vblank;
 
1130         timings->vfreq = timings->hfreq/timings->vtotal;
 
1131         timings->hblank = fb_get_hblank_by_hfreq(timings->hfreq, 
 
1133         timings->htotal = timings->hactive + timings->hblank;
 
1134         timings->dclk = timings->htotal * timings->hfreq;
 
1137 static void fb_timings_dclk(struct __fb_timings *timings)
 
1139         timings->hblank = fb_get_hblank_by_dclk(timings->dclk, 
 
1141         timings->htotal = timings->hactive + timings->hblank;
 
1142         timings->hfreq = timings->dclk/timings->htotal;
 
1143         timings->vblank = fb_get_vblank(timings->hfreq);
 
1144         timings->vtotal = timings->vactive + timings->vblank;
 
1145         timings->vfreq = timings->hfreq/timings->vtotal;
 
1149  * fb_get_mode - calculates video mode using VESA GTF
 
1150  * @flags: if: 0 - maximize vertical refresh rate
 
1151  *             1 - vrefresh-driven calculation;
 
1152  *             2 - hscan-driven calculation;
 
1153  *             3 - pixelclock-driven calculation;
 
1154  * @val: depending on @flags, ignored, vrefresh, hsync or pixelclock
 
1155  * @var: pointer to fb_var_screeninfo
 
1156  * @info: pointer to fb_info
 
1159  * Calculates video mode based on monitor specs using VESA GTF. 
 
1160  * The GTF is best for VESA GTF compliant monitors but is 
 
1161  * specifically formulated to work for older monitors as well.
 
1163  * If @flag==0, the function will attempt to maximize the 
 
1164  * refresh rate.  Otherwise, it will calculate timings based on
 
1165  * the flag and accompanying value.  
 
1167  * If FB_IGNOREMON bit is set in @flags, monitor specs will be 
 
1168  * ignored and @var will be filled with the calculated timings.
 
1170  * All calculations are based on the VESA GTF Spreadsheet
 
1171  * available at VESA's public ftp (http://www.vesa.org).
 
1174  * The timings generated by the GTF will be different from VESA
 
1175  * DMT.  It might be a good idea to keep a table of standard
 
1176  * VESA modes as well.  The GTF may also not work for some displays,
 
1177  * such as, and especially, analog TV.
 
1180  * A valid info->monspecs, otherwise 'safe numbers' will be used.
 
1182 int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_info *info)
 
1184         struct __fb_timings *timings;
 
1185         u32 interlace = 1, dscan = 1;
 
1186         u32 hfmin, hfmax, vfmin, vfmax, dclkmin, dclkmax, err = 0;
 
1189         timings = kzalloc(sizeof(struct __fb_timings), GFP_KERNEL);
 
1195          * If monspecs are invalid, use values that are enough
 
1198         if (!info || !info->monspecs.hfmax || !info->monspecs.vfmax ||
 
1199             !info->monspecs.dclkmax ||
 
1200             info->monspecs.hfmax < info->monspecs.hfmin ||
 
1201             info->monspecs.vfmax < info->monspecs.vfmin ||
 
1202             info->monspecs.dclkmax < info->monspecs.dclkmin) {
 
1203                 hfmin = 29000; hfmax = 30000;
 
1204                 vfmin = 60; vfmax = 60;
 
1205                 dclkmin = 0; dclkmax = 25000000;
 
1207                 hfmin = info->monspecs.hfmin;
 
1208                 hfmax = info->monspecs.hfmax;
 
1209                 vfmin = info->monspecs.vfmin;
 
1210                 vfmax = info->monspecs.vfmax;
 
1211                 dclkmin = info->monspecs.dclkmin;
 
1212                 dclkmax = info->monspecs.dclkmax;
 
1215         timings->hactive = var->xres;
 
1216         timings->vactive = var->yres;
 
1217         if (var->vmode & FB_VMODE_INTERLACED) { 
 
1218                 timings->vactive /= 2;
 
1221         if (var->vmode & FB_VMODE_DOUBLE) {
 
1222                 timings->vactive *= 2;
 
1226         switch (flags & ~FB_IGNOREMON) {
 
1227         case FB_MAXTIMINGS: /* maximize refresh rate */
 
1228                 timings->hfreq = hfmax;
 
1229                 fb_timings_hfreq(timings);
 
1230                 if (timings->vfreq > vfmax) {
 
1231                         timings->vfreq = vfmax;
 
1232                         fb_timings_vfreq(timings);
 
1234                 if (timings->dclk > dclkmax) {
 
1235                         timings->dclk = dclkmax;
 
1236                         fb_timings_dclk(timings);
 
1239         case FB_VSYNCTIMINGS: /* vrefresh driven */
 
1240                 timings->vfreq = val;
 
1241                 fb_timings_vfreq(timings);
 
1243         case FB_HSYNCTIMINGS: /* hsync driven */
 
1244                 timings->hfreq = val;
 
1245                 fb_timings_hfreq(timings);
 
1247         case FB_DCLKTIMINGS: /* pixelclock driven */
 
1248                 timings->dclk = PICOS2KHZ(val) * 1000;
 
1249                 fb_timings_dclk(timings);
 
1256         if (err || (!(flags & FB_IGNOREMON) &&
 
1257             (timings->vfreq < vfmin || timings->vfreq > vfmax ||
 
1258              timings->hfreq < hfmin || timings->hfreq > hfmax ||
 
1259              timings->dclk < dclkmin || timings->dclk > dclkmax))) {
 
1262                 var->pixclock = KHZ2PICOS(timings->dclk/1000);
 
1263                 var->hsync_len = (timings->htotal * 8)/100;
 
1264                 var->right_margin = (timings->hblank/2) - var->hsync_len;
 
1265                 var->left_margin = timings->hblank - var->right_margin -
 
1267                 var->vsync_len = (3 * interlace)/dscan;
 
1268                 var->lower_margin = (1 * interlace)/dscan;
 
1269                 var->upper_margin = (timings->vblank * interlace)/dscan -
 
1270                         (var->vsync_len + var->lower_margin);
 
1277 int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
 
1281 void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs)
 
1285 void fb_destroy_modedb(struct fb_videomode *modedb)
 
1288 int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var,
 
1289                 struct fb_info *info)
 
1293 #endif /* CONFIG_FB_MODE_HELPERS */
 
1296  * fb_validate_mode - validates var against monitor capabilities
 
1297  * @var: pointer to fb_var_screeninfo
 
1298  * @info: pointer to fb_info
 
1301  * Validates video mode against monitor capabilities specified in
 
1305  * A valid info->monspecs.
 
1307 int fb_validate_mode(const struct fb_var_screeninfo *var, struct fb_info *info)
 
1309         u32 hfreq, vfreq, htotal, vtotal, pixclock;
 
1310         u32 hfmin, hfmax, vfmin, vfmax, dclkmin, dclkmax;
 
1313          * If monspecs are invalid, use values that are enough
 
1316         if (!info->monspecs.hfmax || !info->monspecs.vfmax ||
 
1317             !info->monspecs.dclkmax ||
 
1318             info->monspecs.hfmax < info->monspecs.hfmin ||
 
1319             info->monspecs.vfmax < info->monspecs.vfmin ||
 
1320             info->monspecs.dclkmax < info->monspecs.dclkmin) {
 
1321                 hfmin = 29000; hfmax = 30000;
 
1322                 vfmin = 60; vfmax = 60;
 
1323                 dclkmin = 0; dclkmax = 25000000;
 
1325                 hfmin = info->monspecs.hfmin;
 
1326                 hfmax = info->monspecs.hfmax;
 
1327                 vfmin = info->monspecs.vfmin;
 
1328                 vfmax = info->monspecs.vfmax;
 
1329                 dclkmin = info->monspecs.dclkmin;
 
1330                 dclkmax = info->monspecs.dclkmax;
 
1335         pixclock = PICOS2KHZ(var->pixclock) * 1000;
 
1337         htotal = var->xres + var->right_margin + var->hsync_len + 
 
1339         vtotal = var->yres + var->lower_margin + var->vsync_len + 
 
1342         if (var->vmode & FB_VMODE_INTERLACED)
 
1344         if (var->vmode & FB_VMODE_DOUBLE)
 
1347         hfreq = pixclock/htotal;
 
1348         hfreq = (hfreq + 500) / 1000 * 1000;
 
1350         vfreq = hfreq/vtotal;
 
1352         return (vfreq < vfmin || vfreq > vfmax || 
 
1353                 hfreq < hfmin || hfreq > hfmax ||
 
1354                 pixclock < dclkmin || pixclock > dclkmax) ?
 
1358 #if defined(CONFIG_FIRMWARE_EDID) && defined(CONFIG_X86)
 
1361  * We need to ensure that the EDID block is only returned for
 
1362  * the primary graphics adapter.
 
1365 const unsigned char *fb_firmware_edid(struct device *device)
 
1367         struct pci_dev *dev = NULL;
 
1368         struct resource *res = NULL;
 
1369         unsigned char *edid = NULL;
 
1372                 dev = to_pci_dev(device);
 
1375                 res = &dev->resource[PCI_ROM_RESOURCE];
 
1377         if (res && res->flags & IORESOURCE_ROM_SHADOW)
 
1378                 edid = edid_info.dummy;
 
1383 const unsigned char *fb_firmware_edid(struct device *device)
 
1388 EXPORT_SYMBOL(fb_firmware_edid);
 
1390 EXPORT_SYMBOL(fb_parse_edid);
 
1391 EXPORT_SYMBOL(fb_edid_to_monspecs);
 
1392 EXPORT_SYMBOL(fb_get_mode);
 
1393 EXPORT_SYMBOL(fb_validate_mode);
 
1394 EXPORT_SYMBOL(fb_destroy_modedb);