1 /* 2 * linux/drivers/video/fbmon.c 3 * 4 * Copyright (C) 2002 James Simmons <jsimmons@users.sf.net> 5 * 6 * Credits: 7 * 8 * The EDID Parser is a conglomeration from the following sources: 9 * 10 * 1. SciTech SNAP Graphics Architecture 11 * Copyright (C) 1991-2002 SciTech Software, Inc. All rights reserved. 12 * 13 * 2. XFree86 4.3.0, interpret_edid.c 14 * Copyright 1998 by Egbert Eich <Egbert.Eich@Physik.TU-Darmstadt.DE> 15 * 16 * 3. John Fremlin <vii@users.sourceforge.net> and 17 * Ani Joshi <ajoshi@unixbox.com> 18 * 19 * Generalized Timing Formula is derived from: 20 * 21 * GTF Spreadsheet by Andy Morrish (1/5/97) 22 * available at https://www.vesa.org 23 * 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 26 * for more details. 27 * 28 */ 29 30 #include <linux/export.h> 31 #include <linux/fb.h> 32 #include <linux/module.h> 33 #include <linux/pci.h> 34 #include <linux/slab.h> 35 #include <video/edid.h> 36 #include <video/of_videomode.h> 37 #include <video/videomode.h> 38 #include "../edid.h" 39 40 /* 41 * EDID parser 42 */ 43 44 #undef DEBUG /* define this for verbose EDID parsing output */ 45 46 #ifdef DEBUG 47 #define DPRINTK(fmt, args...) printk(fmt,## args) 48 #else 49 #define DPRINTK(fmt, args...) no_printk(fmt, ##args) 50 #endif 51 52 #define FBMON_FIX_HEADER 1 53 #define FBMON_FIX_INPUT 2 54 #define FBMON_FIX_TIMINGS 3 55 56 #ifdef CONFIG_FB_MODE_HELPERS 57 struct broken_edid { 58 u8 manufacturer[4]; 59 u32 model; 60 u32 fix; 61 }; 62 63 static const struct broken_edid brokendb[] = { 64 /* DEC FR-PCXAV-YZ */ 65 { 66 .manufacturer = "DEC", 67 .model = 0x073a, 68 .fix = FBMON_FIX_HEADER, 69 }, 70 /* ViewSonic PF775a */ 71 { 72 .manufacturer = "VSC", 73 .model = 0x5a44, 74 .fix = FBMON_FIX_INPUT, 75 }, 76 /* Sharp UXGA? */ 77 { 78 .manufacturer = "SHP", 79 .model = 0x138e, 80 .fix = FBMON_FIX_TIMINGS, 81 }, 82 }; 83 84 static const unsigned char edid_v1_header[] = { 0x00, 0xff, 0xff, 0xff, 85 0xff, 0xff, 0xff, 0x00 86 }; 87 88 static void copy_string(unsigned char *c, unsigned char *s) 89 { 90 int i; 91 c = c + 5; 92 for (i = 0; (i < 13 && *c != 0x0A); i++) 93 *(s++) = *(c++); 94 *s = 0; 95 while (i-- && (*--s == 0x20)) *s = 0; 96 } 97 98 static int edid_is_serial_block(unsigned char *block) 99 { 100 if ((block[0] == 0x00) && (block[1] == 0x00) && 101 (block[2] == 0x00) && (block[3] == 0xff) && 102 (block[4] == 0x00)) 103 return 1; 104 else 105 return 0; 106 } 107 108 static int edid_is_ascii_block(unsigned char *block) 109 { 110 if ((block[0] == 0x00) && (block[1] == 0x00) && 111 (block[2] == 0x00) && (block[3] == 0xfe) && 112 (block[4] == 0x00)) 113 return 1; 114 else 115 return 0; 116 } 117 118 static int edid_is_limits_block(unsigned char *block) 119 { 120 if ((block[0] == 0x00) && (block[1] == 0x00) && 121 (block[2] == 0x00) && (block[3] == 0xfd) && 122 (block[4] == 0x00)) 123 return 1; 124 else 125 return 0; 126 } 127 128 static int edid_is_monitor_block(unsigned char *block) 129 { 130 if ((block[0] == 0x00) && (block[1] == 0x00) && 131 (block[2] == 0x00) && (block[3] == 0xfc) && 132 (block[4] == 0x00)) 133 return 1; 134 else 135 return 0; 136 } 137 138 static int edid_is_timing_block(unsigned char *block) 139 { 140 if ((block[0] != 0x00) || (block[1] != 0x00) || 141 (block[2] != 0x00) || (block[4] != 0x00)) 142 return 1; 143 else 144 return 0; 145 } 146 147 static int check_edid(unsigned char *edid) 148 { 149 unsigned char *block = edid + ID_MANUFACTURER_NAME, manufacturer[4]; 150 unsigned char *b; 151 u32 model; 152 int i, fix = 0, ret = 0; 153 154 manufacturer[0] = ((block[0] & 0x7c) >> 2) + '@'; 155 manufacturer[1] = ((block[0] & 0x03) << 3) + 156 ((block[1] & 0xe0) >> 5) + '@'; 157 manufacturer[2] = (block[1] & 0x1f) + '@'; 158 manufacturer[3] = 0; 159 model = block[2] + (block[3] << 8); 160 161 for (i = 0; i < ARRAY_SIZE(brokendb); i++) { 162 if (!strncmp(manufacturer, brokendb[i].manufacturer, 4) && 163 brokendb[i].model == model) { 164 fix = brokendb[i].fix; 165 break; 166 } 167 } 168 169 switch (fix) { 170 case FBMON_FIX_HEADER: 171 for (i = 0; i < 8; i++) { 172 if (edid[i] != edid_v1_header[i]) { 173 ret = fix; 174 break; 175 } 176 } 177 break; 178 case FBMON_FIX_INPUT: 179 b = edid + EDID_STRUCT_DISPLAY; 180 /* Only if display is GTF capable will 181 the input type be reset to analog */ 182 if (b[4] & 0x01 && b[0] & 0x80) 183 ret = fix; 184 break; 185 case FBMON_FIX_TIMINGS: 186 b = edid + DETAILED_TIMING_DESCRIPTIONS_START; 187 ret = fix; 188 189 for (i = 0; i < 4; i++) { 190 if (edid_is_limits_block(b)) { 191 ret = 0; 192 break; 193 } 194 195 b += DETAILED_TIMING_DESCRIPTION_SIZE; 196 } 197 198 break; 199 } 200 201 if (ret) 202 printk("fbmon: The EDID Block of " 203 "Manufacturer: %s Model: 0x%x is known to " 204 "be broken,\n", manufacturer, model); 205 206 return ret; 207 } 208 209 static void fix_edid(unsigned char *edid, int fix) 210 { 211 int i; 212 unsigned char *b, csum = 0; 213 214 switch (fix) { 215 case FBMON_FIX_HEADER: 216 printk("fbmon: trying a header reconstruct\n"); 217 memcpy(edid, edid_v1_header, 8); 218 break; 219 case FBMON_FIX_INPUT: 220 printk("fbmon: trying to fix input type\n"); 221 b = edid + EDID_STRUCT_DISPLAY; 222 b[0] &= ~0x80; 223 edid[127] += 0x80; 224 break; 225 case FBMON_FIX_TIMINGS: 226 printk("fbmon: trying to fix monitor timings\n"); 227 b = edid + DETAILED_TIMING_DESCRIPTIONS_START; 228 for (i = 0; i < 4; i++) { 229 if (!(edid_is_serial_block(b) || 230 edid_is_ascii_block(b) || 231 edid_is_monitor_block(b) || 232 edid_is_timing_block(b))) { 233 b[0] = 0x00; 234 b[1] = 0x00; 235 b[2] = 0x00; 236 b[3] = 0xfd; 237 b[4] = 0x00; 238 b[5] = 60; /* vfmin */ 239 b[6] = 60; /* vfmax */ 240 b[7] = 30; /* hfmin */ 241 b[8] = 75; /* hfmax */ 242 b[9] = 17; /* pixclock - 170 MHz*/ 243 b[10] = 0; /* GTF */ 244 break; 245 } 246 247 b += DETAILED_TIMING_DESCRIPTION_SIZE; 248 } 249 250 for (i = 0; i < EDID_LENGTH - 1; i++) 251 csum += edid[i]; 252 253 edid[127] = 256 - csum; 254 break; 255 } 256 } 257 258 static int edid_checksum(unsigned char *edid) 259 { 260 unsigned char csum = 0, all_null = 0; 261 int i, err = 0, fix = check_edid(edid); 262 263 if (fix) 264 fix_edid(edid, fix); 265 266 for (i = 0; i < EDID_LENGTH; i++) { 267 csum += edid[i]; 268 all_null |= edid[i]; 269 } 270 271 if (csum == 0x00 && all_null) { 272 /* checksum passed, everything's good */ 273 err = 1; 274 } 275 276 return err; 277 } 278 279 static int edid_check_header(unsigned char *edid) 280 { 281 int i, err = 1, fix = check_edid(edid); 282 283 if (fix) 284 fix_edid(edid, fix); 285 286 for (i = 0; i < 8; i++) { 287 if (edid[i] != edid_v1_header[i]) 288 err = 0; 289 } 290 291 return err; 292 } 293 294 static void parse_vendor_block(unsigned char *block, struct fb_monspecs *specs) 295 { 296 specs->manufacturer[0] = ((block[0] & 0x7c) >> 2) + '@'; 297 specs->manufacturer[1] = ((block[0] & 0x03) << 3) + 298 ((block[1] & 0xe0) >> 5) + '@'; 299 specs->manufacturer[2] = (block[1] & 0x1f) + '@'; 300 specs->manufacturer[3] = 0; 301 specs->model = block[2] + (block[3] << 8); 302 specs->serial = block[4] + (block[5] << 8) + 303 (block[6] << 16) + (block[7] << 24); 304 specs->year = block[9] + 1990; 305 specs->week = block[8]; 306 DPRINTK(" Manufacturer: %s\n", specs->manufacturer); 307 DPRINTK(" Model: %x\n", specs->model); 308 DPRINTK(" Serial#: %u\n", specs->serial); 309 DPRINTK(" Year: %u Week %u\n", specs->year, specs->week); 310 } 311 312 static void get_dpms_capabilities(unsigned char flags, 313 struct fb_monspecs *specs) 314 { 315 specs->dpms = 0; 316 if (flags & DPMS_ACTIVE_OFF) 317 specs->dpms |= FB_DPMS_ACTIVE_OFF; 318 if (flags & DPMS_SUSPEND) 319 specs->dpms |= FB_DPMS_SUSPEND; 320 if (flags & DPMS_STANDBY) 321 specs->dpms |= FB_DPMS_STANDBY; 322 DPRINTK(" DPMS: Active %s, Suspend %s, Standby %s\n", 323 (flags & DPMS_ACTIVE_OFF) ? "yes" : "no", 324 (flags & DPMS_SUSPEND) ? "yes" : "no", 325 (flags & DPMS_STANDBY) ? "yes" : "no"); 326 } 327 328 static void get_chroma(unsigned char *block, struct fb_monspecs *specs) 329 { 330 int tmp; 331 332 DPRINTK(" Chroma\n"); 333 /* Chromaticity data */ 334 tmp = ((block[5] & (3 << 6)) >> 6) | (block[0x7] << 2); 335 tmp *= 1000; 336 tmp += 512; 337 specs->chroma.redx = tmp/1024; 338 DPRINTK(" RedX: 0.%03d ", specs->chroma.redx); 339 340 tmp = ((block[5] & (3 << 4)) >> 4) | (block[0x8] << 2); 341 tmp *= 1000; 342 tmp += 512; 343 specs->chroma.redy = tmp/1024; 344 DPRINTK("RedY: 0.%03d\n", specs->chroma.redy); 345 346 tmp = ((block[5] & (3 << 2)) >> 2) | (block[0x9] << 2); 347 tmp *= 1000; 348 tmp += 512; 349 specs->chroma.greenx = tmp/1024; 350 DPRINTK(" GreenX: 0.%03d ", specs->chroma.greenx); 351 352 tmp = (block[5] & 3) | (block[0xa] << 2); 353 tmp *= 1000; 354 tmp += 512; 355 specs->chroma.greeny = tmp/1024; 356 DPRINTK("GreenY: 0.%03d\n", specs->chroma.greeny); 357 358 tmp = ((block[6] & (3 << 6)) >> 6) | (block[0xb] << 2); 359 tmp *= 1000; 360 tmp += 512; 361 specs->chroma.bluex = tmp/1024; 362 DPRINTK(" BlueX: 0.%03d ", specs->chroma.bluex); 363 364 tmp = ((block[6] & (3 << 4)) >> 4) | (block[0xc] << 2); 365 tmp *= 1000; 366 tmp += 512; 367 specs->chroma.bluey = tmp/1024; 368 DPRINTK("BlueY: 0.%03d\n", specs->chroma.bluey); 369 370 tmp = ((block[6] & (3 << 2)) >> 2) | (block[0xd] << 2); 371 tmp *= 1000; 372 tmp += 512; 373 specs->chroma.whitex = tmp/1024; 374 DPRINTK(" WhiteX: 0.%03d ", specs->chroma.whitex); 375 376 tmp = (block[6] & 3) | (block[0xe] << 2); 377 tmp *= 1000; 378 tmp += 512; 379 specs->chroma.whitey = tmp/1024; 380 DPRINTK("WhiteY: 0.%03d\n", specs->chroma.whitey); 381 } 382 383 static void calc_mode_timings(int xres, int yres, int refresh, 384 struct fb_videomode *mode) 385 { 386 struct fb_var_screeninfo *var; 387 388 var = kzalloc(sizeof(struct fb_var_screeninfo), GFP_KERNEL); 389 390 if (var) { 391 var->xres = xres; 392 var->yres = yres; 393 fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 394 refresh, var, NULL); 395 mode->xres = xres; 396 mode->yres = yres; 397 mode->pixclock = var->pixclock; 398 mode->refresh = refresh; 399 mode->left_margin = var->left_margin; 400 mode->right_margin = var->right_margin; 401 mode->upper_margin = var->upper_margin; 402 mode->lower_margin = var->lower_margin; 403 mode->hsync_len = var->hsync_len; 404 mode->vsync_len = var->vsync_len; 405 mode->vmode = 0; 406 mode->sync = 0; 407 kfree(var); 408 } 409 } 410 411 static int get_est_timing(unsigned char *block, struct fb_videomode *mode) 412 { 413 int num = 0; 414 unsigned char c; 415 416 c = block[0]; 417 if (c&0x80) { 418 calc_mode_timings(720, 400, 70, &mode[num]); 419 mode[num++].flag = FB_MODE_IS_CALCULATED; 420 DPRINTK(" 720x400@70Hz\n"); 421 } 422 if (c&0x40) { 423 calc_mode_timings(720, 400, 88, &mode[num]); 424 mode[num++].flag = FB_MODE_IS_CALCULATED; 425 DPRINTK(" 720x400@88Hz\n"); 426 } 427 if (c&0x20) { 428 mode[num++] = vesa_modes[3]; 429 DPRINTK(" 640x480@60Hz\n"); 430 } 431 if (c&0x10) { 432 calc_mode_timings(640, 480, 67, &mode[num]); 433 mode[num++].flag = FB_MODE_IS_CALCULATED; 434 DPRINTK(" 640x480@67Hz\n"); 435 } 436 if (c&0x08) { 437 mode[num++] = vesa_modes[4]; 438 DPRINTK(" 640x480@72Hz\n"); 439 } 440 if (c&0x04) { 441 mode[num++] = vesa_modes[5]; 442 DPRINTK(" 640x480@75Hz\n"); 443 } 444 if (c&0x02) { 445 mode[num++] = vesa_modes[7]; 446 DPRINTK(" 800x600@56Hz\n"); 447 } 448 if (c&0x01) { 449 mode[num++] = vesa_modes[8]; 450 DPRINTK(" 800x600@60Hz\n"); 451 } 452 453 c = block[1]; 454 if (c&0x80) { 455 mode[num++] = vesa_modes[9]; 456 DPRINTK(" 800x600@72Hz\n"); 457 } 458 if (c&0x40) { 459 mode[num++] = vesa_modes[10]; 460 DPRINTK(" 800x600@75Hz\n"); 461 } 462 if (c&0x20) { 463 calc_mode_timings(832, 624, 75, &mode[num]); 464 mode[num++].flag = FB_MODE_IS_CALCULATED; 465 DPRINTK(" 832x624@75Hz\n"); 466 } 467 if (c&0x10) { 468 mode[num++] = vesa_modes[12]; 469 DPRINTK(" 1024x768@87Hz Interlaced\n"); 470 } 471 if (c&0x08) { 472 mode[num++] = vesa_modes[13]; 473 DPRINTK(" 1024x768@60Hz\n"); 474 } 475 if (c&0x04) { 476 mode[num++] = vesa_modes[14]; 477 DPRINTK(" 1024x768@70Hz\n"); 478 } 479 if (c&0x02) { 480 mode[num++] = vesa_modes[15]; 481 DPRINTK(" 1024x768@75Hz\n"); 482 } 483 if (c&0x01) { 484 mode[num++] = vesa_modes[21]; 485 DPRINTK(" 1280x1024@75Hz\n"); 486 } 487 c = block[2]; 488 if (c&0x80) { 489 mode[num++] = vesa_modes[17]; 490 DPRINTK(" 1152x870@75Hz\n"); 491 } 492 DPRINTK(" Manufacturer's mask: %x\n",c&0x7F); 493 return num; 494 } 495 496 static int get_std_timing(unsigned char *block, struct fb_videomode *mode, 497 int ver, int rev, const struct fb_monspecs *specs) 498 { 499 int i; 500 501 for (i = 0; i < DMT_SIZE; i++) { 502 u32 std_2byte_code = block[0] << 8 | block[1]; 503 if (std_2byte_code == dmt_modes[i].std_2byte_code) 504 break; 505 } 506 507 if (i < DMT_SIZE && dmt_modes[i].mode) { 508 /* DMT mode found */ 509 *mode = *dmt_modes[i].mode; 510 mode->flag |= FB_MODE_IS_STANDARD; 511 DPRINTK(" DMT id=%d\n", dmt_modes[i].dmt_id); 512 513 } else { 514 int xres, yres = 0, refresh, ratio; 515 516 xres = (block[0] + 31) * 8; 517 if (xres <= 256) 518 return 0; 519 520 ratio = (block[1] & 0xc0) >> 6; 521 switch (ratio) { 522 case 0: 523 /* in EDID 1.3 the meaning of 0 changed to 16:10 (prior 1:1) */ 524 if (ver < 1 || (ver == 1 && rev < 3)) 525 yres = xres; 526 else 527 yres = (xres * 10)/16; 528 break; 529 case 1: 530 yres = (xres * 3)/4; 531 break; 532 case 2: 533 yres = (xres * 4)/5; 534 break; 535 case 3: 536 yres = (xres * 9)/16; 537 break; 538 } 539 refresh = (block[1] & 0x3f) + 60; 540 DPRINTK(" %dx%d@%dHz\n", xres, yres, refresh); 541 542 calc_mode_timings(xres, yres, refresh, mode); 543 } 544 545 /* Check the mode we got is within valid spec of the monitor */ 546 if (specs && specs->dclkmax 547 && PICOS2KHZ(mode->pixclock) * 1000 > specs->dclkmax) { 548 DPRINTK(" mode exceed max DCLK\n"); 549 return 0; 550 } 551 552 return 1; 553 } 554 555 static int get_dst_timing(unsigned char *block, struct fb_videomode *mode, 556 int ver, int rev, const struct fb_monspecs *specs) 557 { 558 int j, num = 0; 559 560 for (j = 0; j < 6; j++, block += STD_TIMING_DESCRIPTION_SIZE) 561 num += get_std_timing(block, &mode[num], ver, rev, specs); 562 563 return num; 564 } 565 566 static void get_detailed_timing(unsigned char *block, 567 struct fb_videomode *mode) 568 { 569 mode->xres = H_ACTIVE; 570 mode->yres = V_ACTIVE; 571 mode->pixclock = PIXEL_CLOCK; 572 mode->pixclock /= 1000; 573 mode->pixclock = KHZ2PICOS(mode->pixclock); 574 mode->right_margin = H_SYNC_OFFSET; 575 mode->left_margin = (H_ACTIVE + H_BLANKING) - 576 (H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH); 577 mode->upper_margin = V_BLANKING - V_SYNC_OFFSET - 578 V_SYNC_WIDTH; 579 mode->lower_margin = V_SYNC_OFFSET; 580 mode->hsync_len = H_SYNC_WIDTH; 581 mode->vsync_len = V_SYNC_WIDTH; 582 if (HSYNC_POSITIVE) 583 mode->sync |= FB_SYNC_HOR_HIGH_ACT; 584 if (VSYNC_POSITIVE) 585 mode->sync |= FB_SYNC_VERT_HIGH_ACT; 586 mode->refresh = PIXEL_CLOCK/((H_ACTIVE + H_BLANKING) * 587 (V_ACTIVE + V_BLANKING)); 588 if (INTERLACED) { 589 mode->yres *= 2; 590 mode->upper_margin *= 2; 591 mode->lower_margin *= 2; 592 mode->vsync_len *= 2; 593 mode->vmode |= FB_VMODE_INTERLACED; 594 } 595 mode->flag = FB_MODE_IS_DETAILED; 596 597 DPRINTK(" %d MHz ", PIXEL_CLOCK/1000000); 598 DPRINTK("%d %d %d %d ", H_ACTIVE, H_ACTIVE + H_SYNC_OFFSET, 599 H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH, H_ACTIVE + H_BLANKING); 600 DPRINTK("%d %d %d %d ", V_ACTIVE, V_ACTIVE + V_SYNC_OFFSET, 601 V_ACTIVE + V_SYNC_OFFSET + V_SYNC_WIDTH, V_ACTIVE + V_BLANKING); 602 DPRINTK("%sHSync %sVSync\n\n", (HSYNC_POSITIVE) ? "+" : "-", 603 (VSYNC_POSITIVE) ? "+" : "-"); 604 } 605 606 /** 607 * fb_create_modedb - create video mode database 608 * @edid: EDID data 609 * @dbsize: database size 610 * @specs: monitor specifications, may be NULL 611 * 612 * RETURNS: struct fb_videomode, @dbsize contains length of database 613 * 614 * DESCRIPTION: 615 * This function builds a mode database using the contents of the EDID 616 * data 617 */ 618 static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize, 619 const struct fb_monspecs *specs) 620 { 621 struct fb_videomode *mode, *m; 622 unsigned char *block; 623 int num = 0, i, first = 1; 624 int ver, rev; 625 626 mode = kcalloc(50, sizeof(struct fb_videomode), GFP_KERNEL); 627 if (mode == NULL) 628 return NULL; 629 630 if (edid == NULL || !edid_checksum(edid) || 631 !edid_check_header(edid)) { 632 kfree(mode); 633 return NULL; 634 } 635 636 ver = edid[EDID_STRUCT_VERSION]; 637 rev = edid[EDID_STRUCT_REVISION]; 638 639 *dbsize = 0; 640 641 DPRINTK(" Detailed Timings\n"); 642 block = edid + DETAILED_TIMING_DESCRIPTIONS_START; 643 for (i = 0; i < 4; i++, block+= DETAILED_TIMING_DESCRIPTION_SIZE) { 644 if (!(block[0] == 0x00 && block[1] == 0x00)) { 645 get_detailed_timing(block, &mode[num]); 646 if (first) { 647 mode[num].flag |= FB_MODE_IS_FIRST; 648 first = 0; 649 } 650 num++; 651 } 652 } 653 654 DPRINTK(" Supported VESA Modes\n"); 655 block = edid + ESTABLISHED_TIMING_1; 656 num += get_est_timing(block, &mode[num]); 657 658 DPRINTK(" Standard Timings\n"); 659 block = edid + STD_TIMING_DESCRIPTIONS_START; 660 for (i = 0; i < STD_TIMING; i++, block += STD_TIMING_DESCRIPTION_SIZE) 661 num += get_std_timing(block, &mode[num], ver, rev, specs); 662 663 block = edid + DETAILED_TIMING_DESCRIPTIONS_START; 664 for (i = 0; i < 4; i++, block+= DETAILED_TIMING_DESCRIPTION_SIZE) { 665 if (block[0] == 0x00 && block[1] == 0x00 && block[3] == 0xfa) 666 num += get_dst_timing(block + 5, &mode[num], 667 ver, rev, specs); 668 } 669 670 /* Yikes, EDID data is totally useless */ 671 if (!num) { 672 kfree(mode); 673 return NULL; 674 } 675 676 *dbsize = num; 677 m = kmalloc_array(num, sizeof(struct fb_videomode), GFP_KERNEL); 678 if (!m) 679 return mode; 680 memmove(m, mode, num * sizeof(struct fb_videomode)); 681 kfree(mode); 682 return m; 683 } 684 685 /** 686 * fb_destroy_modedb - destroys mode database 687 * @modedb: mode database to destroy 688 * 689 * DESCRIPTION: 690 * Destroy mode database created by fb_create_modedb 691 */ 692 void fb_destroy_modedb(struct fb_videomode *modedb) 693 { 694 kfree(modedb); 695 } 696 697 static int fb_get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs) 698 { 699 int i, retval = 1; 700 unsigned char *block; 701 702 block = edid + DETAILED_TIMING_DESCRIPTIONS_START; 703 704 DPRINTK(" Monitor Operating Limits: "); 705 706 for (i = 0; i < 4; i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) { 707 if (edid_is_limits_block(block)) { 708 specs->hfmin = H_MIN_RATE * 1000; 709 specs->hfmax = H_MAX_RATE * 1000; 710 specs->vfmin = V_MIN_RATE; 711 specs->vfmax = V_MAX_RATE; 712 specs->dclkmax = MAX_PIXEL_CLOCK * 1000000; 713 specs->gtf = (GTF_SUPPORT) ? 1 : 0; 714 retval = 0; 715 DPRINTK("From EDID\n"); 716 break; 717 } 718 } 719 720 /* estimate monitor limits based on modes supported */ 721 if (retval) { 722 struct fb_videomode *modes, *mode; 723 int num_modes, hz, hscan, pixclock; 724 int vtotal, htotal; 725 726 modes = fb_create_modedb(edid, &num_modes, specs); 727 if (!modes) { 728 DPRINTK("None Available\n"); 729 return 1; 730 } 731 732 retval = 0; 733 for (i = 0; i < num_modes; i++) { 734 mode = &modes[i]; 735 pixclock = PICOS2KHZ(modes[i].pixclock) * 1000; 736 htotal = mode->xres + mode->right_margin + mode->hsync_len 737 + mode->left_margin; 738 vtotal = mode->yres + mode->lower_margin + mode->vsync_len 739 + mode->upper_margin; 740 741 if (mode->vmode & FB_VMODE_INTERLACED) 742 vtotal /= 2; 743 744 if (mode->vmode & FB_VMODE_DOUBLE) 745 vtotal *= 2; 746 747 hscan = (pixclock + htotal / 2) / htotal; 748 hscan = (hscan + 500) / 1000 * 1000; 749 hz = (hscan + vtotal / 2) / vtotal; 750 751 if (specs->dclkmax == 0 || specs->dclkmax < pixclock) 752 specs->dclkmax = pixclock; 753 754 if (specs->dclkmin == 0 || specs->dclkmin > pixclock) 755 specs->dclkmin = pixclock; 756 757 if (specs->hfmax == 0 || specs->hfmax < hscan) 758 specs->hfmax = hscan; 759 760 if (specs->hfmin == 0 || specs->hfmin > hscan) 761 specs->hfmin = hscan; 762 763 if (specs->vfmax == 0 || specs->vfmax < hz) 764 specs->vfmax = hz; 765 766 if (specs->vfmin == 0 || specs->vfmin > hz) 767 specs->vfmin = hz; 768 } 769 DPRINTK("Extrapolated\n"); 770 fb_destroy_modedb(modes); 771 } 772 DPRINTK(" H: %d-%dKHz V: %d-%dHz DCLK: %dMHz\n", 773 specs->hfmin/1000, specs->hfmax/1000, specs->vfmin, 774 specs->vfmax, specs->dclkmax/1000000); 775 return retval; 776 } 777 778 static void get_monspecs(unsigned char *edid, struct fb_monspecs *specs) 779 { 780 unsigned char c, *block; 781 782 block = edid + EDID_STRUCT_DISPLAY; 783 784 fb_get_monitor_limits(edid, specs); 785 786 c = block[0] & 0x80; 787 specs->input = 0; 788 if (c) { 789 specs->input |= FB_DISP_DDI; 790 DPRINTK(" Digital Display Input"); 791 } else { 792 DPRINTK(" Analog Display Input: Input Voltage - "); 793 switch ((block[0] & 0x60) >> 5) { 794 case 0: 795 DPRINTK("0.700V/0.300V"); 796 specs->input |= FB_DISP_ANA_700_300; 797 break; 798 case 1: 799 DPRINTK("0.714V/0.286V"); 800 specs->input |= FB_DISP_ANA_714_286; 801 break; 802 case 2: 803 DPRINTK("1.000V/0.400V"); 804 specs->input |= FB_DISP_ANA_1000_400; 805 break; 806 case 3: 807 DPRINTK("0.700V/0.000V"); 808 specs->input |= FB_DISP_ANA_700_000; 809 break; 810 } 811 } 812 DPRINTK("\n Sync: "); 813 c = block[0] & 0x10; 814 if (c) 815 DPRINTK(" Configurable signal level\n"); 816 c = block[0] & 0x0f; 817 specs->signal = 0; 818 if (c & 0x10) { 819 DPRINTK("Blank to Blank "); 820 specs->signal |= FB_SIGNAL_BLANK_BLANK; 821 } 822 if (c & 0x08) { 823 DPRINTK("Separate "); 824 specs->signal |= FB_SIGNAL_SEPARATE; 825 } 826 if (c & 0x04) { 827 DPRINTK("Composite "); 828 specs->signal |= FB_SIGNAL_COMPOSITE; 829 } 830 if (c & 0x02) { 831 DPRINTK("Sync on Green "); 832 specs->signal |= FB_SIGNAL_SYNC_ON_GREEN; 833 } 834 if (c & 0x01) { 835 DPRINTK("Serration on "); 836 specs->signal |= FB_SIGNAL_SERRATION_ON; 837 } 838 DPRINTK("\n"); 839 specs->max_x = block[1]; 840 specs->max_y = block[2]; 841 DPRINTK(" Max H-size in cm: "); 842 if (specs->max_x) 843 DPRINTK("%d\n", specs->max_x); 844 else 845 DPRINTK("variable\n"); 846 DPRINTK(" Max V-size in cm: "); 847 if (specs->max_y) 848 DPRINTK("%d\n", specs->max_y); 849 else 850 DPRINTK("variable\n"); 851 852 c = block[3]; 853 specs->gamma = c+100; 854 DPRINTK(" Gamma: "); 855 DPRINTK("%d.%d\n", specs->gamma/100, specs->gamma % 100); 856 857 get_dpms_capabilities(block[4], specs); 858 859 switch ((block[4] & 0x18) >> 3) { 860 case 0: 861 DPRINTK(" Monochrome/Grayscale\n"); 862 specs->input |= FB_DISP_MONO; 863 break; 864 case 1: 865 DPRINTK(" RGB Color Display\n"); 866 specs->input |= FB_DISP_RGB; 867 break; 868 case 2: 869 DPRINTK(" Non-RGB Multicolor Display\n"); 870 specs->input |= FB_DISP_MULTI; 871 break; 872 default: 873 DPRINTK(" Unknown\n"); 874 specs->input |= FB_DISP_UNKNOWN; 875 break; 876 } 877 878 get_chroma(block, specs); 879 880 specs->misc = 0; 881 c = block[4] & 0x7; 882 if (c & 0x04) { 883 DPRINTK(" Default color format is primary\n"); 884 specs->misc |= FB_MISC_PRIM_COLOR; 885 } 886 if (c & 0x02) { 887 DPRINTK(" First DETAILED Timing is preferred\n"); 888 specs->misc |= FB_MISC_1ST_DETAIL; 889 } 890 if (c & 0x01) { 891 printk(" Display is GTF capable\n"); 892 specs->gtf = 1; 893 } 894 } 895 896 int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var) 897 { 898 int i; 899 unsigned char *block; 900 901 if (edid == NULL || var == NULL) 902 return 1; 903 904 if (!(edid_checksum(edid))) 905 return 1; 906 907 if (!(edid_check_header(edid))) 908 return 1; 909 910 block = edid + DETAILED_TIMING_DESCRIPTIONS_START; 911 912 for (i = 0; i < 4; i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) { 913 if (edid_is_timing_block(block)) { 914 var->xres = var->xres_virtual = H_ACTIVE; 915 var->yres = var->yres_virtual = V_ACTIVE; 916 var->height = var->width = 0; 917 var->right_margin = H_SYNC_OFFSET; 918 var->left_margin = (H_ACTIVE + H_BLANKING) - 919 (H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH); 920 var->upper_margin = V_BLANKING - V_SYNC_OFFSET - 921 V_SYNC_WIDTH; 922 var->lower_margin = V_SYNC_OFFSET; 923 var->hsync_len = H_SYNC_WIDTH; 924 var->vsync_len = V_SYNC_WIDTH; 925 var->pixclock = PIXEL_CLOCK; 926 var->pixclock /= 1000; 927 var->pixclock = KHZ2PICOS(var->pixclock); 928 929 if (HSYNC_POSITIVE) 930 var->sync |= FB_SYNC_HOR_HIGH_ACT; 931 if (VSYNC_POSITIVE) 932 var->sync |= FB_SYNC_VERT_HIGH_ACT; 933 return 0; 934 } 935 } 936 return 1; 937 } 938 939 void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs) 940 { 941 unsigned char *block; 942 int i, found = 0; 943 944 if (edid == NULL) 945 return; 946 947 if (!(edid_checksum(edid))) 948 return; 949 950 if (!(edid_check_header(edid))) 951 return; 952 953 memset(specs, 0, sizeof(struct fb_monspecs)); 954 955 specs->version = edid[EDID_STRUCT_VERSION]; 956 specs->revision = edid[EDID_STRUCT_REVISION]; 957 958 DPRINTK("========================================\n"); 959 DPRINTK("Display Information (EDID)\n"); 960 DPRINTK("========================================\n"); 961 DPRINTK(" EDID Version %d.%d\n", (int) specs->version, 962 (int) specs->revision); 963 964 parse_vendor_block(edid + ID_MANUFACTURER_NAME, specs); 965 966 block = edid + DETAILED_TIMING_DESCRIPTIONS_START; 967 for (i = 0; i < 4; i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) { 968 if (edid_is_serial_block(block)) { 969 copy_string(block, specs->serial_no); 970 DPRINTK(" Serial Number: %s\n", specs->serial_no); 971 } else if (edid_is_ascii_block(block)) { 972 copy_string(block, specs->ascii); 973 DPRINTK(" ASCII Block: %s\n", specs->ascii); 974 } else if (edid_is_monitor_block(block)) { 975 copy_string(block, specs->monitor); 976 DPRINTK(" Monitor Name: %s\n", specs->monitor); 977 } 978 } 979 980 DPRINTK(" Display Characteristics:\n"); 981 get_monspecs(edid, specs); 982 983 specs->modedb = fb_create_modedb(edid, &specs->modedb_len, specs); 984 if (!specs->modedb) 985 return; 986 987 /* 988 * Workaround for buggy EDIDs that sets that the first 989 * detailed timing is preferred but has not detailed 990 * timing specified 991 */ 992 for (i = 0; i < specs->modedb_len; i++) { 993 if (specs->modedb[i].flag & FB_MODE_IS_DETAILED) { 994 found = 1; 995 break; 996 } 997 } 998 999 if (!found) 1000 specs->misc &= ~FB_MISC_1ST_DETAIL; 1001 1002 DPRINTK("========================================\n"); 1003 } 1004 1005 /* 1006 * VESA Generalized Timing Formula (GTF) 1007 */ 1008 1009 #define FLYBACK 550 1010 #define V_FRONTPORCH 1 1011 #define H_OFFSET 40 1012 #define H_SCALEFACTOR 20 1013 #define H_BLANKSCALE 128 1014 #define H_GRADIENT 600 1015 #define C_VAL 30 1016 #define M_VAL 300 1017 1018 struct __fb_timings { 1019 u32 dclk; 1020 u32 hfreq; 1021 u32 vfreq; 1022 u32 hactive; 1023 u32 vactive; 1024 u32 hblank; 1025 u32 vblank; 1026 u32 htotal; 1027 u32 vtotal; 1028 }; 1029 1030 /** 1031 * fb_get_vblank - get vertical blank time 1032 * @hfreq: horizontal freq 1033 * 1034 * DESCRIPTION: 1035 * vblank = right_margin + vsync_len + left_margin 1036 * 1037 * given: right_margin = 1 (V_FRONTPORCH) 1038 * vsync_len = 3 1039 * flyback = 550 1040 * 1041 * flyback * hfreq 1042 * left_margin = --------------- - vsync_len 1043 * 1000000 1044 */ 1045 static u32 fb_get_vblank(u32 hfreq) 1046 { 1047 u32 vblank; 1048 1049 vblank = (hfreq * FLYBACK)/1000; 1050 vblank = (vblank + 500)/1000; 1051 return (vblank + V_FRONTPORCH); 1052 } 1053 1054 /** 1055 * fb_get_hblank_by_hfreq - get horizontal blank time given hfreq 1056 * @hfreq: horizontal freq 1057 * @xres: horizontal resolution in pixels 1058 * 1059 * DESCRIPTION: 1060 * 1061 * xres * duty_cycle 1062 * hblank = ------------------ 1063 * 100 - duty_cycle 1064 * 1065 * duty cycle = percent of htotal assigned to inactive display 1066 * duty cycle = C - (M/Hfreq) 1067 * 1068 * where: C = ((offset - scale factor) * blank_scale) 1069 * -------------------------------------- + scale factor 1070 * 256 1071 * M = blank_scale * gradient 1072 * 1073 */ 1074 static u32 fb_get_hblank_by_hfreq(u32 hfreq, u32 xres) 1075 { 1076 u32 c_val, m_val, duty_cycle, hblank; 1077 1078 c_val = (((H_OFFSET - H_SCALEFACTOR) * H_BLANKSCALE)/256 + 1079 H_SCALEFACTOR) * 1000; 1080 m_val = (H_BLANKSCALE * H_GRADIENT)/256; 1081 m_val = (m_val * 1000000)/hfreq; 1082 duty_cycle = c_val - m_val; 1083 hblank = (xres * duty_cycle)/(100000 - duty_cycle); 1084 return (hblank); 1085 } 1086 1087 /** 1088 * fb_get_hblank_by_dclk - get horizontal blank time given pixelclock 1089 * @dclk: pixelclock in Hz 1090 * @xres: horizontal resolution in pixels 1091 * 1092 * DESCRIPTION: 1093 * 1094 * xres * duty_cycle 1095 * hblank = ------------------ 1096 * 100 - duty_cycle 1097 * 1098 * duty cycle = percent of htotal assigned to inactive display 1099 * duty cycle = C - (M * h_period) 1100 * 1101 * where: h_period = SQRT(100 - C + (0.4 * xres * M)/dclk) + C - 100 1102 * ----------------------------------------------- 1103 * 2 * M 1104 * M = 300; 1105 * C = 30; 1106 */ 1107 static u32 fb_get_hblank_by_dclk(u32 dclk, u32 xres) 1108 { 1109 u32 duty_cycle, h_period, hblank; 1110 1111 dclk /= 1000; 1112 h_period = 100 - C_VAL; 1113 h_period *= h_period; 1114 h_period += (M_VAL * xres * 2 * 1000)/(5 * dclk); 1115 h_period *= 10000; 1116 1117 h_period = int_sqrt(h_period); 1118 h_period -= (100 - C_VAL) * 100; 1119 h_period *= 1000; 1120 h_period /= 2 * M_VAL; 1121 1122 duty_cycle = C_VAL * 1000 - (M_VAL * h_period)/100; 1123 hblank = (xres * duty_cycle)/(100000 - duty_cycle) + 8; 1124 hblank &= ~15; 1125 return (hblank); 1126 } 1127 1128 /** 1129 * fb_get_hfreq - estimate hsync 1130 * @vfreq: vertical refresh rate 1131 * @yres: vertical resolution 1132 * 1133 * DESCRIPTION: 1134 * 1135 * (yres + front_port) * vfreq * 1000000 1136 * hfreq = ------------------------------------- 1137 * (1000000 - (vfreq * FLYBACK) 1138 * 1139 */ 1140 1141 static u32 fb_get_hfreq(u32 vfreq, u32 yres) 1142 { 1143 u32 divisor, hfreq; 1144 1145 divisor = (1000000 - (vfreq * FLYBACK))/1000; 1146 hfreq = (yres + V_FRONTPORCH) * vfreq * 1000; 1147 return (hfreq/divisor); 1148 } 1149 1150 static void fb_timings_vfreq(struct __fb_timings *timings) 1151 { 1152 timings->hfreq = fb_get_hfreq(timings->vfreq, timings->vactive); 1153 timings->vblank = fb_get_vblank(timings->hfreq); 1154 timings->vtotal = timings->vactive + timings->vblank; 1155 timings->hblank = fb_get_hblank_by_hfreq(timings->hfreq, 1156 timings->hactive); 1157 timings->htotal = timings->hactive + timings->hblank; 1158 timings->dclk = timings->htotal * timings->hfreq; 1159 } 1160 1161 static void fb_timings_hfreq(struct __fb_timings *timings) 1162 { 1163 timings->vblank = fb_get_vblank(timings->hfreq); 1164 timings->vtotal = timings->vactive + timings->vblank; 1165 timings->vfreq = timings->hfreq/timings->vtotal; 1166 timings->hblank = fb_get_hblank_by_hfreq(timings->hfreq, 1167 timings->hactive); 1168 timings->htotal = timings->hactive + timings->hblank; 1169 timings->dclk = timings->htotal * timings->hfreq; 1170 } 1171 1172 static void fb_timings_dclk(struct __fb_timings *timings) 1173 { 1174 timings->hblank = fb_get_hblank_by_dclk(timings->dclk, 1175 timings->hactive); 1176 timings->htotal = timings->hactive + timings->hblank; 1177 timings->hfreq = timings->dclk/timings->htotal; 1178 timings->vblank = fb_get_vblank(timings->hfreq); 1179 timings->vtotal = timings->vactive + timings->vblank; 1180 timings->vfreq = timings->hfreq/timings->vtotal; 1181 } 1182 1183 /* 1184 * fb_get_mode - calculates video mode using VESA GTF 1185 * @flags: if: 0 - maximize vertical refresh rate 1186 * 1 - vrefresh-driven calculation; 1187 * 2 - hscan-driven calculation; 1188 * 3 - pixelclock-driven calculation; 1189 * @val: depending on @flags, ignored, vrefresh, hsync or pixelclock 1190 * @var: pointer to fb_var_screeninfo 1191 * @info: pointer to fb_info 1192 * 1193 * DESCRIPTION: 1194 * Calculates video mode based on monitor specs using VESA GTF. 1195 * The GTF is best for VESA GTF compliant monitors but is 1196 * specifically formulated to work for older monitors as well. 1197 * 1198 * If @flag==0, the function will attempt to maximize the 1199 * refresh rate. Otherwise, it will calculate timings based on 1200 * the flag and accompanying value. 1201 * 1202 * If FB_IGNOREMON bit is set in @flags, monitor specs will be 1203 * ignored and @var will be filled with the calculated timings. 1204 * 1205 * All calculations are based on the VESA GTF Spreadsheet 1206 * available at VESA's public ftp (https://www.vesa.org). 1207 * 1208 * NOTES: 1209 * The timings generated by the GTF will be different from VESA 1210 * DMT. It might be a good idea to keep a table of standard 1211 * VESA modes as well. The GTF may also not work for some displays, 1212 * such as, and especially, analog TV. 1213 * 1214 * REQUIRES: 1215 * A valid info->monspecs, otherwise 'safe numbers' will be used. 1216 */ 1217 int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_info *info) 1218 { 1219 struct __fb_timings *timings; 1220 u32 interlace = 1, dscan = 1; 1221 u32 hfmin, hfmax, vfmin, vfmax, dclkmin, dclkmax, err = 0; 1222 1223 1224 timings = kzalloc(sizeof(struct __fb_timings), GFP_KERNEL); 1225 1226 if (!timings) 1227 return -ENOMEM; 1228 1229 /* 1230 * If monspecs are invalid, use values that are enough 1231 * for 640x480@60 1232 */ 1233 if (!info || !info->monspecs.hfmax || !info->monspecs.vfmax || 1234 !info->monspecs.dclkmax || 1235 info->monspecs.hfmax < info->monspecs.hfmin || 1236 info->monspecs.vfmax < info->monspecs.vfmin || 1237 info->monspecs.dclkmax < info->monspecs.dclkmin) { 1238 hfmin = 29000; hfmax = 30000; 1239 vfmin = 60; vfmax = 60; 1240 dclkmin = 0; dclkmax = 25000000; 1241 } else { 1242 hfmin = info->monspecs.hfmin; 1243 hfmax = info->monspecs.hfmax; 1244 vfmin = info->monspecs.vfmin; 1245 vfmax = info->monspecs.vfmax; 1246 dclkmin = info->monspecs.dclkmin; 1247 dclkmax = info->monspecs.dclkmax; 1248 } 1249 1250 timings->hactive = var->xres; 1251 timings->vactive = var->yres; 1252 if (var->vmode & FB_VMODE_INTERLACED) { 1253 timings->vactive /= 2; 1254 interlace = 2; 1255 } 1256 if (var->vmode & FB_VMODE_DOUBLE) { 1257 timings->vactive *= 2; 1258 dscan = 2; 1259 } 1260 1261 switch (flags & ~FB_IGNOREMON) { 1262 case FB_MAXTIMINGS: /* maximize refresh rate */ 1263 timings->hfreq = hfmax; 1264 fb_timings_hfreq(timings); 1265 if (timings->vfreq > vfmax) { 1266 timings->vfreq = vfmax; 1267 fb_timings_vfreq(timings); 1268 } 1269 if (timings->dclk > dclkmax) { 1270 timings->dclk = dclkmax; 1271 fb_timings_dclk(timings); 1272 } 1273 break; 1274 case FB_VSYNCTIMINGS: /* vrefresh driven */ 1275 timings->vfreq = val; 1276 fb_timings_vfreq(timings); 1277 break; 1278 case FB_HSYNCTIMINGS: /* hsync driven */ 1279 timings->hfreq = val; 1280 fb_timings_hfreq(timings); 1281 break; 1282 case FB_DCLKTIMINGS: /* pixelclock driven */ 1283 timings->dclk = PICOS2KHZ(val) * 1000; 1284 fb_timings_dclk(timings); 1285 break; 1286 default: 1287 err = -EINVAL; 1288 1289 } 1290 1291 if (err || (!(flags & FB_IGNOREMON) && 1292 (timings->vfreq < vfmin || timings->vfreq > vfmax || 1293 timings->hfreq < hfmin || timings->hfreq > hfmax || 1294 timings->dclk < dclkmin || timings->dclk > dclkmax))) { 1295 err = -EINVAL; 1296 } else { 1297 var->pixclock = KHZ2PICOS(timings->dclk/1000); 1298 var->hsync_len = (timings->htotal * 8)/100; 1299 var->right_margin = (timings->hblank/2) - var->hsync_len; 1300 var->left_margin = timings->hblank - var->right_margin - 1301 var->hsync_len; 1302 var->vsync_len = (3 * interlace)/dscan; 1303 var->lower_margin = (1 * interlace)/dscan; 1304 var->upper_margin = (timings->vblank * interlace)/dscan - 1305 (var->vsync_len + var->lower_margin); 1306 } 1307 1308 kfree(timings); 1309 return err; 1310 } 1311 1312 #ifdef CONFIG_VIDEOMODE_HELPERS 1313 int fb_videomode_from_videomode(const struct videomode *vm, 1314 struct fb_videomode *fbmode) 1315 { 1316 unsigned int htotal, vtotal, total; 1317 1318 fbmode->xres = vm->hactive; 1319 fbmode->left_margin = vm->hback_porch; 1320 fbmode->right_margin = vm->hfront_porch; 1321 fbmode->hsync_len = vm->hsync_len; 1322 1323 fbmode->yres = vm->vactive; 1324 fbmode->upper_margin = vm->vback_porch; 1325 fbmode->lower_margin = vm->vfront_porch; 1326 fbmode->vsync_len = vm->vsync_len; 1327 1328 /* prevent division by zero in KHZ2PICOS macro */ 1329 fbmode->pixclock = vm->pixelclock ? 1330 KHZ2PICOS(vm->pixelclock / 1000) : 0; 1331 1332 fbmode->sync = 0; 1333 fbmode->vmode = 0; 1334 if (vm->flags & DISPLAY_FLAGS_HSYNC_HIGH) 1335 fbmode->sync |= FB_SYNC_HOR_HIGH_ACT; 1336 if (vm->flags & DISPLAY_FLAGS_VSYNC_HIGH) 1337 fbmode->sync |= FB_SYNC_VERT_HIGH_ACT; 1338 if (vm->flags & DISPLAY_FLAGS_INTERLACED) 1339 fbmode->vmode |= FB_VMODE_INTERLACED; 1340 if (vm->flags & DISPLAY_FLAGS_DOUBLESCAN) 1341 fbmode->vmode |= FB_VMODE_DOUBLE; 1342 fbmode->flag = 0; 1343 1344 htotal = vm->hactive + vm->hfront_porch + vm->hback_porch + 1345 vm->hsync_len; 1346 vtotal = vm->vactive + vm->vfront_porch + vm->vback_porch + 1347 vm->vsync_len; 1348 /* prevent division by zero */ 1349 total = htotal * vtotal; 1350 if (total) { 1351 fbmode->refresh = vm->pixelclock / total; 1352 /* a mode must have htotal and vtotal != 0 or it is invalid */ 1353 } else { 1354 fbmode->refresh = 0; 1355 return -EINVAL; 1356 } 1357 1358 return 0; 1359 } 1360 EXPORT_SYMBOL_GPL(fb_videomode_from_videomode); 1361 1362 #ifdef CONFIG_OF 1363 static inline void dump_fb_videomode(const struct fb_videomode *m) 1364 { 1365 pr_debug("fb_videomode = %ux%u@%uHz (%ukHz) %u %u %u %u %u %u %u %u %u\n", 1366 m->xres, m->yres, m->refresh, m->pixclock, m->left_margin, 1367 m->right_margin, m->upper_margin, m->lower_margin, 1368 m->hsync_len, m->vsync_len, m->sync, m->vmode, m->flag); 1369 } 1370 1371 /** 1372 * of_get_fb_videomode - get a fb_videomode from devicetree 1373 * @np: device_node with the timing specification 1374 * @fb: will be set to the return value 1375 * @index: index into the list of display timings in devicetree 1376 * 1377 * DESCRIPTION: 1378 * This function is expensive and should only be used, if only one mode is to be 1379 * read from DT. To get multiple modes start with of_get_display_timings ond 1380 * work with that instead. 1381 */ 1382 int of_get_fb_videomode(struct device_node *np, struct fb_videomode *fb, 1383 int index) 1384 { 1385 struct videomode vm; 1386 int ret; 1387 1388 ret = of_get_videomode(np, &vm, index); 1389 if (ret) 1390 return ret; 1391 1392 ret = fb_videomode_from_videomode(&vm, fb); 1393 if (ret) 1394 return ret; 1395 1396 pr_debug("%pOF: got %dx%d display mode\n", 1397 np, vm.hactive, vm.vactive); 1398 dump_fb_videomode(fb); 1399 1400 return 0; 1401 } 1402 EXPORT_SYMBOL_GPL(of_get_fb_videomode); 1403 #endif /* CONFIG_OF */ 1404 #endif /* CONFIG_VIDEOMODE_HELPERS */ 1405 1406 #else 1407 int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var) 1408 { 1409 return 1; 1410 } 1411 void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs) 1412 { 1413 } 1414 void fb_destroy_modedb(struct fb_videomode *modedb) 1415 { 1416 } 1417 int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, 1418 struct fb_info *info) 1419 { 1420 return -EINVAL; 1421 } 1422 #endif /* CONFIG_FB_MODE_HELPERS */ 1423 1424 /* 1425 * fb_validate_mode - validates var against monitor capabilities 1426 * @var: pointer to fb_var_screeninfo 1427 * @info: pointer to fb_info 1428 * 1429 * DESCRIPTION: 1430 * Validates video mode against monitor capabilities specified in 1431 * info->monspecs. 1432 * 1433 * REQUIRES: 1434 * A valid info->monspecs. 1435 */ 1436 int fb_validate_mode(const struct fb_var_screeninfo *var, struct fb_info *info) 1437 { 1438 u32 hfreq, vfreq, htotal, vtotal, pixclock; 1439 u32 hfmin, hfmax, vfmin, vfmax, dclkmin, dclkmax; 1440 1441 /* 1442 * If monspecs are invalid, use values that are enough 1443 * for 640x480@60 1444 */ 1445 if (!info->monspecs.hfmax || !info->monspecs.vfmax || 1446 !info->monspecs.dclkmax || 1447 info->monspecs.hfmax < info->monspecs.hfmin || 1448 info->monspecs.vfmax < info->monspecs.vfmin || 1449 info->monspecs.dclkmax < info->monspecs.dclkmin) { 1450 hfmin = 29000; hfmax = 30000; 1451 vfmin = 60; vfmax = 60; 1452 dclkmin = 0; dclkmax = 25000000; 1453 } else { 1454 hfmin = info->monspecs.hfmin; 1455 hfmax = info->monspecs.hfmax; 1456 vfmin = info->monspecs.vfmin; 1457 vfmax = info->monspecs.vfmax; 1458 dclkmin = info->monspecs.dclkmin; 1459 dclkmax = info->monspecs.dclkmax; 1460 } 1461 1462 if (!var->pixclock) 1463 return -EINVAL; 1464 pixclock = PICOS2KHZ(var->pixclock) * 1000; 1465 1466 htotal = var->xres + var->right_margin + var->hsync_len + 1467 var->left_margin; 1468 vtotal = var->yres + var->lower_margin + var->vsync_len + 1469 var->upper_margin; 1470 1471 if (var->vmode & FB_VMODE_INTERLACED) 1472 vtotal /= 2; 1473 if (var->vmode & FB_VMODE_DOUBLE) 1474 vtotal *= 2; 1475 1476 hfreq = pixclock/htotal; 1477 hfreq = (hfreq + 500) / 1000 * 1000; 1478 1479 vfreq = hfreq/vtotal; 1480 1481 return (vfreq < vfmin || vfreq > vfmax || 1482 hfreq < hfmin || hfreq > hfmax || 1483 pixclock < dclkmin || pixclock > dclkmax) ? 1484 -EINVAL : 0; 1485 } 1486 1487 /* 1488 * We need to ensure that the EDID block is only returned for 1489 * the primary graphics adapter. 1490 */ 1491 1492 #if defined(CONFIG_FIRMWARE_EDID) 1493 const unsigned char *fb_firmware_edid(struct device *device) 1494 { 1495 struct pci_dev *dev = NULL; 1496 struct resource *res = NULL; 1497 unsigned char *edid = NULL; 1498 1499 if (device) 1500 dev = to_pci_dev(device); 1501 1502 if (dev) 1503 res = &dev->resource[PCI_ROM_RESOURCE]; 1504 1505 if (res && res->flags & IORESOURCE_ROM_SHADOW) 1506 edid = edid_info.dummy; 1507 1508 return edid; 1509 } 1510 #else 1511 const unsigned char *fb_firmware_edid(struct device *device) 1512 { 1513 return NULL; 1514 } 1515 #endif 1516 EXPORT_SYMBOL(fb_firmware_edid); 1517 1518 EXPORT_SYMBOL(fb_parse_edid); 1519 EXPORT_SYMBOL(fb_edid_to_monspecs); 1520 EXPORT_SYMBOL(fb_get_mode); 1521 EXPORT_SYMBOL(fb_validate_mode); 1522 EXPORT_SYMBOL(fb_destroy_modedb); 1523