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