Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

video: fbdev: Check Standard Timing against DMT

Add the VESA Display Monitor Timing (DMT) table.
During parsing of Standard Timings, it compare the 2 byte STD code
with DMT to see what the VESA mode should be. If there is no entry
in the vesa_modes table or no match found, it fallsback to the
GTF timings.

Signed-off-by: David Ung <davidu@nvidia.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>

authored by

David Ung and committed by
Tomi Valkeinen
8f5ee77b 37715f55

+135 -33
+41 -33
drivers/video/fbdev/core/fbmon.c
··· 498 498 static int get_std_timing(unsigned char *block, struct fb_videomode *mode, 499 499 int ver, int rev) 500 500 { 501 - int xres, yres = 0, refresh, ratio, i; 501 + int i; 502 502 503 - xres = (block[0] + 31) * 8; 504 - if (xres <= 256) 505 - return 0; 506 - 507 - ratio = (block[1] & 0xc0) >> 6; 508 - switch (ratio) { 509 - case 0: 510 - /* in EDID 1.3 the meaning of 0 changed to 16:10 (prior 1:1) */ 511 - if (ver < 1 || (ver == 1 && rev < 3)) 512 - yres = xres; 513 - else 514 - yres = (xres * 10)/16; 515 - break; 516 - case 1: 517 - yres = (xres * 3)/4; 518 - break; 519 - case 2: 520 - yres = (xres * 4)/5; 521 - break; 522 - case 3: 523 - yres = (xres * 9)/16; 524 - break; 503 + for (i = 0; i < DMT_SIZE; i++) { 504 + u32 std_2byte_code = block[0] << 8 | block[1]; 505 + if (std_2byte_code == dmt_modes[i].std_2byte_code) 506 + break; 525 507 } 526 - refresh = (block[1] & 0x3f) + 60; 527 508 528 - DPRINTK(" %dx%d@%dHz\n", xres, yres, refresh); 529 - for (i = 0; i < VESA_MODEDB_SIZE; i++) { 530 - if (vesa_modes[i].xres == xres && 531 - vesa_modes[i].yres == yres && 532 - vesa_modes[i].refresh == refresh) { 533 - *mode = vesa_modes[i]; 534 - mode->flag |= FB_MODE_IS_STANDARD; 535 - return 1; 509 + if (i < DMT_SIZE && dmt_modes[i].mode) { 510 + /* DMT mode found */ 511 + *mode = *dmt_modes[i].mode; 512 + mode->flag |= FB_MODE_IS_STANDARD; 513 + DPRINTK(" DMT id=%d\n", dmt_modes[i].dmt_id); 514 + 515 + } else { 516 + int xres, yres = 0, refresh, ratio; 517 + 518 + xres = (block[0] + 31) * 8; 519 + if (xres <= 256) 520 + return 0; 521 + 522 + ratio = (block[1] & 0xc0) >> 6; 523 + switch (ratio) { 524 + case 0: 525 + /* in EDID 1.3 the meaning of 0 changed to 16:10 (prior 1:1) */ 526 + if (ver < 1 || (ver == 1 && rev < 3)) 527 + yres = xres; 528 + else 529 + yres = (xres * 10)/16; 530 + break; 531 + case 1: 532 + yres = (xres * 3)/4; 533 + break; 534 + case 2: 535 + yres = (xres * 4)/5; 536 + break; 537 + case 3: 538 + yres = (xres * 9)/16; 539 + break; 536 540 } 541 + refresh = (block[1] & 0x3f) + 60; 542 + DPRINTK(" %dx%d@%dHz\n", xres, yres, refresh); 543 + 544 + calc_mode_timings(xres, yres, refresh, mode); 537 545 } 538 - calc_mode_timings(xres, yres, refresh, mode); 546 + 539 547 return 1; 540 548 } 541 549
+84
drivers/video/fbdev/core/modedb.c
··· 497 497 FB_SYNC_HOR_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, 498 498 }; 499 499 EXPORT_SYMBOL(vesa_modes); 500 + 501 + const struct dmt_videomode dmt_modes[DMT_SIZE] = { 502 + { 0x01, 0x0000, 0x000000, &vesa_modes[0] }, 503 + { 0x02, 0x3119, 0x000000, &vesa_modes[1] }, 504 + { 0x03, 0x0000, 0x000000, &vesa_modes[2] }, 505 + { 0x04, 0x3140, 0x000000, &vesa_modes[3] }, 506 + { 0x05, 0x314c, 0x000000, &vesa_modes[4] }, 507 + { 0x06, 0x314f, 0x000000, &vesa_modes[5] }, 508 + { 0x07, 0x3159, 0x000000, &vesa_modes[6] }, 509 + { 0x08, 0x0000, 0x000000, &vesa_modes[7] }, 510 + { 0x09, 0x4540, 0x000000, &vesa_modes[8] }, 511 + { 0x0a, 0x454c, 0x000000, &vesa_modes[9] }, 512 + { 0x0b, 0x454f, 0x000000, &vesa_modes[10] }, 513 + { 0x0c, 0x4559, 0x000000, &vesa_modes[11] }, 514 + { 0x0d, 0x0000, 0x000000, 0 }, 515 + { 0x0e, 0x0000, 0x000000, 0 }, 516 + { 0x0f, 0x0000, 0x000000, &vesa_modes[12] }, 517 + { 0x10, 0x6140, 0x000000, &vesa_modes[13] }, 518 + { 0x11, 0x614a, 0x000000, &vesa_modes[14] }, 519 + { 0x12, 0x614f, 0x000000, &vesa_modes[15] }, 520 + { 0x13, 0x6159, 0x000000, &vesa_modes[16] }, 521 + { 0x14, 0x0000, 0x000000, 0 }, 522 + { 0x15, 0x714f, 0x000000, &vesa_modes[17] }, 523 + { 0x16, 0x0000, 0x7f1c21, 0 }, 524 + { 0x17, 0x0000, 0x7f1c28, 0 }, 525 + { 0x18, 0x0000, 0x7f1c44, 0 }, 526 + { 0x19, 0x0000, 0x7f1c62, 0 }, 527 + { 0x1a, 0x0000, 0x000000, 0 }, 528 + { 0x1b, 0x0000, 0x8f1821, 0 }, 529 + { 0x1c, 0x8100, 0x8f1828, 0 }, 530 + { 0x1d, 0x810f, 0x8f1844, 0 }, 531 + { 0x1e, 0x8119, 0x8f1862, 0 }, 532 + { 0x1f, 0x0000, 0x000000, 0 }, 533 + { 0x20, 0x8140, 0x000000, &vesa_modes[18] }, 534 + { 0x21, 0x8159, 0x000000, &vesa_modes[19] }, 535 + { 0x22, 0x0000, 0x000000, 0 }, 536 + { 0x23, 0x8180, 0x000000, &vesa_modes[20] }, 537 + { 0x24, 0x818f, 0x000000, &vesa_modes[21] }, 538 + { 0x25, 0x8199, 0x000000, &vesa_modes[22] }, 539 + { 0x26, 0x0000, 0x000000, 0 }, 540 + { 0x27, 0x0000, 0x000000, 0 }, 541 + { 0x28, 0x0000, 0x000000, 0 }, 542 + { 0x29, 0x0000, 0x0c2021, 0 }, 543 + { 0x2a, 0x9040, 0x0c2028, 0 }, 544 + { 0x2b, 0x904f, 0x0c2044, 0 }, 545 + { 0x2c, 0x9059, 0x0c2062, 0 }, 546 + { 0x2d, 0x0000, 0x000000, 0 }, 547 + { 0x2e, 0x9500, 0xc11821, 0 }, 548 + { 0x2f, 0x9500, 0xc11828, 0 }, 549 + { 0x30, 0x950f, 0xc11844, 0 }, 550 + { 0x31, 0x9519, 0xc11868, 0 }, 551 + { 0x32, 0x0000, 0x000000, 0 }, 552 + { 0x33, 0xa940, 0x000000, &vesa_modes[23] }, 553 + { 0x34, 0xa945, 0x000000, &vesa_modes[24] }, 554 + { 0x35, 0xa94a, 0x000000, &vesa_modes[25] }, 555 + { 0x36, 0xa94f, 0x000000, &vesa_modes[26] }, 556 + { 0x37, 0xa959, 0x000000, &vesa_modes[27] }, 557 + { 0x38, 0x0000, 0x000000, 0 }, 558 + { 0x39, 0x0000, 0x0c2821, 0 }, 559 + { 0x3a, 0xb300, 0x0c2828, 0 }, 560 + { 0x3b, 0xb30f, 0x0c2844, 0 }, 561 + { 0x3c, 0xb319, 0x0c2868, 0 }, 562 + { 0x3d, 0x0000, 0x000000, 0 }, 563 + { 0x3e, 0xc140, 0x000000, &vesa_modes[28] }, 564 + { 0x3f, 0xc14f, 0x000000, &vesa_modes[29] }, 565 + { 0x40, 0x0000, 0x000000, 0 }, 566 + { 0x41, 0xc940, 0x000000, &vesa_modes[30] }, 567 + { 0x42, 0xc94f, 0x000000, &vesa_modes[31] }, 568 + { 0x43, 0x0000, 0x000000, 0 }, 569 + { 0x44, 0x0000, 0x572821, &vesa_modes[34] }, 570 + { 0x45, 0xd100, 0x572828, &vesa_modes[35] }, 571 + { 0x46, 0xd10f, 0x572844, &vesa_modes[36] }, 572 + { 0x47, 0xd119, 0x572862, &vesa_modes[37] }, 573 + { 0x48, 0x0000, 0x000000, 0 }, 574 + { 0x49, 0xd140, 0x000000, &vesa_modes[32] }, 575 + { 0x4a, 0xd14f, 0x000000, &vesa_modes[33] }, 576 + { 0x4b, 0x0000, 0x000000, 0 }, 577 + { 0x4c, 0x0000, 0x1f3821, &vesa_modes[38] }, 578 + { 0x4d, 0x0000, 0x1f3828, &vesa_modes[39] }, 579 + { 0x4e, 0x0000, 0x1f3844, &vesa_modes[40] }, 580 + { 0x4f, 0x0000, 0x1f3862, &vesa_modes[41] }, 581 + { 0x50, 0x0000, 0x000000, &vesa_modes[42] }, 582 + }; 583 + EXPORT_SYMBOL(dmt_modes); 500 584 #endif /* CONFIG_FB_MODE_HELPERS */ 501 585 502 586 /**
+10
include/linux/fb.h
··· 727 727 728 728 /* drivers/video/modedb.c */ 729 729 #define VESA_MODEDB_SIZE 43 730 + #define DMT_SIZE 0x50 731 + 730 732 extern void fb_var_to_videomode(struct fb_videomode *mode, 731 733 const struct fb_var_screeninfo *var); 732 734 extern void fb_videomode_to_var(struct fb_var_screeninfo *var, ··· 779 777 u32 flag; 780 778 }; 781 779 780 + struct dmt_videomode { 781 + u32 dmt_id; 782 + u32 std_2byte_code; 783 + u32 cvt_3byte_code; 784 + const struct fb_videomode *mode; 785 + }; 786 + 782 787 extern const char *fb_mode_option; 783 788 extern const struct fb_videomode vesa_modes[]; 784 789 extern const struct fb_videomode cea_modes[64]; 790 + extern const struct dmt_videomode dmt_modes[]; 785 791 786 792 struct fb_modelist { 787 793 struct list_head list;