diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-12 12:21:39 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-12 12:21:39 -0400 |
commit | aa9f56b66d278aba2f278c75761b7e19fbaca97a (patch) | |
tree | f1a9a0e68b07a3a1a0643389cb5ff838366a2d32 /drivers/gpu/drm/drm_edid.c | |
parent | 58d4ea65b98f154f3326b038eecda32f90b46ea8 (diff) | |
parent | 31ce4bfdfd10bf5db9bf85c92bbe0cf2edbdcad8 (diff) |
Merge branch 'drm-core-next' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6
* 'drm-core-next' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6: (55 commits)
io-mapping: move asm include inside the config option
vgaarb: drop vga.h include
drm/radeon: Add probing of clocks from device-tree
drm/radeon: drop old and broken mesa warning
drm/radeon: Fix pci_map_page() error checking
drm: Remove count_lock for calling lastclose() after 58474713 (v2)
drm/radeon/kms: allow FG_ALPHA_VALUE on r5xx
drm/radeon/kms: another r6xx/r7xx CS checker fix
DRM: Replace kmalloc/memset combos with kzalloc
drm: expand gamma_set
drm/edid: Split mode lists out to their own header for readability
drm/edid: Rewrite mode parse to use the generic detailed block walk
drm/edid: Add detailed block walk for VTB extensions
drm/edid: Add detailed block walk for CEA extensions
drm: Remove unused fields from drm_display_info
drm: Use ENOENT consistently for the error return for an unmatched handle.
drm/radeon/kms: mark 3D power states as performance
drm: Only set DPMS once on the CRTC not after every encoder.
drm/radeon/kms: add additional quirk for Acer rv620 laptop
drm: Propagate error code from fb_create()
...
Fix up trivial conflicts in drivers/gpu/drm/drm_edid.c
Diffstat (limited to 'drivers/gpu/drm/drm_edid.c')
-rw-r--r-- | drivers/gpu/drm/drm_edid.c | 840 |
1 files changed, 273 insertions, 567 deletions
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index dce5c4a97f8d..96e963108225 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c | |||
@@ -33,6 +33,11 @@ | |||
33 | #include <linux/i2c-algo-bit.h> | 33 | #include <linux/i2c-algo-bit.h> |
34 | #include "drmP.h" | 34 | #include "drmP.h" |
35 | #include "drm_edid.h" | 35 | #include "drm_edid.h" |
36 | #include "drm_edid_modes.h" | ||
37 | |||
38 | #define version_greater(edid, maj, min) \ | ||
39 | (((edid)->version > (maj)) || \ | ||
40 | ((edid)->version == (maj) && (edid)->revision > (min))) | ||
36 | 41 | ||
37 | #define EDID_EST_TIMINGS 16 | 42 | #define EDID_EST_TIMINGS 16 |
38 | #define EDID_STD_TIMINGS 8 | 43 | #define EDID_STD_TIMINGS 8 |
@@ -62,6 +67,13 @@ | |||
62 | /* use +hsync +vsync for detailed mode */ | 67 | /* use +hsync +vsync for detailed mode */ |
63 | #define EDID_QUIRK_DETAILED_SYNC_PP (1 << 6) | 68 | #define EDID_QUIRK_DETAILED_SYNC_PP (1 << 6) |
64 | 69 | ||
70 | struct detailed_mode_closure { | ||
71 | struct drm_connector *connector; | ||
72 | struct edid *edid; | ||
73 | bool preferred; | ||
74 | u32 quirks; | ||
75 | int modes; | ||
76 | }; | ||
65 | 77 | ||
66 | #define LEVEL_DMT 0 | 78 | #define LEVEL_DMT 0 |
67 | #define LEVEL_GTF 1 | 79 | #define LEVEL_GTF 1 |
@@ -375,7 +387,6 @@ static u32 edid_get_quirks(struct edid *edid) | |||
375 | #define MODE_SIZE(m) ((m)->hdisplay * (m)->vdisplay) | 387 | #define MODE_SIZE(m) ((m)->hdisplay * (m)->vdisplay) |
376 | #define MODE_REFRESH_DIFF(m,r) (abs((m)->vrefresh - target_refresh)) | 388 | #define MODE_REFRESH_DIFF(m,r) (abs((m)->vrefresh - target_refresh)) |
377 | 389 | ||
378 | |||
379 | /** | 390 | /** |
380 | * edid_fixup_preferred - set preferred modes based on quirk list | 391 | * edid_fixup_preferred - set preferred modes based on quirk list |
381 | * @connector: has mode list to fix up | 392 | * @connector: has mode list to fix up |
@@ -422,245 +433,6 @@ static void edid_fixup_preferred(struct drm_connector *connector, | |||
422 | preferred_mode->type |= DRM_MODE_TYPE_PREFERRED; | 433 | preferred_mode->type |= DRM_MODE_TYPE_PREFERRED; |
423 | } | 434 | } |
424 | 435 | ||
425 | /* | ||
426 | * Add the Autogenerated from the DMT spec. | ||
427 | * This table is copied from xfree86/modes/xf86EdidModes.c. | ||
428 | * But the mode with Reduced blank feature is deleted. | ||
429 | */ | ||
430 | static struct drm_display_mode drm_dmt_modes[] = { | ||
431 | /* 640x350@85Hz */ | ||
432 | { DRM_MODE("640x350", DRM_MODE_TYPE_DRIVER, 31500, 640, 672, | ||
433 | 736, 832, 0, 350, 382, 385, 445, 0, | ||
434 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, | ||
435 | /* 640x400@85Hz */ | ||
436 | { DRM_MODE("640x400", DRM_MODE_TYPE_DRIVER, 31500, 640, 672, | ||
437 | 736, 832, 0, 400, 401, 404, 445, 0, | ||
438 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
439 | /* 720x400@85Hz */ | ||
440 | { DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 35500, 720, 756, | ||
441 | 828, 936, 0, 400, 401, 404, 446, 0, | ||
442 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
443 | /* 640x480@60Hz */ | ||
444 | { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656, | ||
445 | 752, 800, 0, 480, 489, 492, 525, 0, | ||
446 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, | ||
447 | /* 640x480@72Hz */ | ||
448 | { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 31500, 640, 664, | ||
449 | 704, 832, 0, 480, 489, 492, 520, 0, | ||
450 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, | ||
451 | /* 640x480@75Hz */ | ||
452 | { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 31500, 640, 656, | ||
453 | 720, 840, 0, 480, 481, 484, 500, 0, | ||
454 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, | ||
455 | /* 640x480@85Hz */ | ||
456 | { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 36000, 640, 696, | ||
457 | 752, 832, 0, 480, 481, 484, 509, 0, | ||
458 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, | ||
459 | /* 800x600@56Hz */ | ||
460 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 36000, 800, 824, | ||
461 | 896, 1024, 0, 600, 601, 603, 625, 0, | ||
462 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
463 | /* 800x600@60Hz */ | ||
464 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840, | ||
465 | 968, 1056, 0, 600, 601, 605, 628, 0, | ||
466 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
467 | /* 800x600@72Hz */ | ||
468 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 50000, 800, 856, | ||
469 | 976, 1040, 0, 600, 637, 643, 666, 0, | ||
470 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
471 | /* 800x600@75Hz */ | ||
472 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 49500, 800, 816, | ||
473 | 896, 1056, 0, 600, 601, 604, 625, 0, | ||
474 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
475 | /* 800x600@85Hz */ | ||
476 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 56250, 800, 832, | ||
477 | 896, 1048, 0, 600, 601, 604, 631, 0, | ||
478 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
479 | /* 848x480@60Hz */ | ||
480 | { DRM_MODE("848x480", DRM_MODE_TYPE_DRIVER, 33750, 848, 864, | ||
481 | 976, 1088, 0, 480, 486, 494, 517, 0, | ||
482 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
483 | /* 1024x768@43Hz, interlace */ | ||
484 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 44900, 1024, 1032, | ||
485 | 1208, 1264, 0, 768, 768, 772, 817, 0, | ||
486 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC | | ||
487 | DRM_MODE_FLAG_INTERLACE) }, | ||
488 | /* 1024x768@60Hz */ | ||
489 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048, | ||
490 | 1184, 1344, 0, 768, 771, 777, 806, 0, | ||
491 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, | ||
492 | /* 1024x768@70Hz */ | ||
493 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 75000, 1024, 1048, | ||
494 | 1184, 1328, 0, 768, 771, 777, 806, 0, | ||
495 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, | ||
496 | /* 1024x768@75Hz */ | ||
497 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 78750, 1024, 1040, | ||
498 | 1136, 1312, 0, 768, 769, 772, 800, 0, | ||
499 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
500 | /* 1024x768@85Hz */ | ||
501 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 94500, 1024, 1072, | ||
502 | 1168, 1376, 0, 768, 769, 772, 808, 0, | ||
503 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
504 | /* 1152x864@75Hz */ | ||
505 | { DRM_MODE("1152x864", DRM_MODE_TYPE_DRIVER, 108000, 1152, 1216, | ||
506 | 1344, 1600, 0, 864, 865, 868, 900, 0, | ||
507 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
508 | /* 1280x768@60Hz */ | ||
509 | { DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 79500, 1280, 1344, | ||
510 | 1472, 1664, 0, 768, 771, 778, 798, 0, | ||
511 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
512 | /* 1280x768@75Hz */ | ||
513 | { DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 102250, 1280, 1360, | ||
514 | 1488, 1696, 0, 768, 771, 778, 805, 0, | ||
515 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, | ||
516 | /* 1280x768@85Hz */ | ||
517 | { DRM_MODE("1280x768", DRM_MODE_TYPE_DRIVER, 117500, 1280, 1360, | ||
518 | 1496, 1712, 0, 768, 771, 778, 809, 0, | ||
519 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
520 | /* 1280x800@60Hz */ | ||
521 | { DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 83500, 1280, 1352, | ||
522 | 1480, 1680, 0, 800, 803, 809, 831, 0, | ||
523 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, | ||
524 | /* 1280x800@75Hz */ | ||
525 | { DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 106500, 1280, 1360, | ||
526 | 1488, 1696, 0, 800, 803, 809, 838, 0, | ||
527 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
528 | /* 1280x800@85Hz */ | ||
529 | { DRM_MODE("1280x800", DRM_MODE_TYPE_DRIVER, 122500, 1280, 1360, | ||
530 | 1496, 1712, 0, 800, 803, 809, 843, 0, | ||
531 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
532 | /* 1280x960@60Hz */ | ||
533 | { DRM_MODE("1280x960", DRM_MODE_TYPE_DRIVER, 108000, 1280, 1376, | ||
534 | 1488, 1800, 0, 960, 961, 964, 1000, 0, | ||
535 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
536 | /* 1280x960@85Hz */ | ||
537 | { DRM_MODE("1280x960", DRM_MODE_TYPE_DRIVER, 148500, 1280, 1344, | ||
538 | 1504, 1728, 0, 960, 961, 964, 1011, 0, | ||
539 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
540 | /* 1280x1024@60Hz */ | ||
541 | { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 108000, 1280, 1328, | ||
542 | 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, | ||
543 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
544 | /* 1280x1024@75Hz */ | ||
545 | { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 135000, 1280, 1296, | ||
546 | 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, | ||
547 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
548 | /* 1280x1024@85Hz */ | ||
549 | { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 157500, 1280, 1344, | ||
550 | 1504, 1728, 0, 1024, 1025, 1028, 1072, 0, | ||
551 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
552 | /* 1360x768@60Hz */ | ||
553 | { DRM_MODE("1360x768", DRM_MODE_TYPE_DRIVER, 85500, 1360, 1424, | ||
554 | 1536, 1792, 0, 768, 771, 777, 795, 0, | ||
555 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
556 | /* 1440x1050@60Hz */ | ||
557 | { DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 121750, 1400, 1488, | ||
558 | 1632, 1864, 0, 1050, 1053, 1057, 1089, 0, | ||
559 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
560 | /* 1440x1050@75Hz */ | ||
561 | { DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 156000, 1400, 1504, | ||
562 | 1648, 1896, 0, 1050, 1053, 1057, 1099, 0, | ||
563 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
564 | /* 1440x1050@85Hz */ | ||
565 | { DRM_MODE("1400x1050", DRM_MODE_TYPE_DRIVER, 179500, 1400, 1504, | ||
566 | 1656, 1912, 0, 1050, 1053, 1057, 1105, 0, | ||
567 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
568 | /* 1440x900@60Hz */ | ||
569 | { DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 106500, 1440, 1520, | ||
570 | 1672, 1904, 0, 900, 903, 909, 934, 0, | ||
571 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
572 | /* 1440x900@75Hz */ | ||
573 | { DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 136750, 1440, 1536, | ||
574 | 1688, 1936, 0, 900, 903, 909, 942, 0, | ||
575 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
576 | /* 1440x900@85Hz */ | ||
577 | { DRM_MODE("1440x900", DRM_MODE_TYPE_DRIVER, 157000, 1440, 1544, | ||
578 | 1696, 1952, 0, 900, 903, 909, 948, 0, | ||
579 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
580 | /* 1600x1200@60Hz */ | ||
581 | { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 162000, 1600, 1664, | ||
582 | 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, | ||
583 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
584 | /* 1600x1200@65Hz */ | ||
585 | { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 175500, 1600, 1664, | ||
586 | 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, | ||
587 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
588 | /* 1600x1200@70Hz */ | ||
589 | { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 189000, 1600, 1664, | ||
590 | 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, | ||
591 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
592 | /* 1600x1200@75Hz */ | ||
593 | { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 202500, 1600, 1664, | ||
594 | 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, | ||
595 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
596 | /* 1600x1200@85Hz */ | ||
597 | { DRM_MODE("1600x1200", DRM_MODE_TYPE_DRIVER, 229500, 1600, 1664, | ||
598 | 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, | ||
599 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
600 | /* 1680x1050@60Hz */ | ||
601 | { DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 146250, 1680, 1784, | ||
602 | 1960, 2240, 0, 1050, 1053, 1059, 1089, 0, | ||
603 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
604 | /* 1680x1050@75Hz */ | ||
605 | { DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 187000, 1680, 1800, | ||
606 | 1976, 2272, 0, 1050, 1053, 1059, 1099, 0, | ||
607 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
608 | /* 1680x1050@85Hz */ | ||
609 | { DRM_MODE("1680x1050", DRM_MODE_TYPE_DRIVER, 214750, 1680, 1808, | ||
610 | 1984, 2288, 0, 1050, 1053, 1059, 1105, 0, | ||
611 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
612 | /* 1792x1344@60Hz */ | ||
613 | { DRM_MODE("1792x1344", DRM_MODE_TYPE_DRIVER, 204750, 1792, 1920, | ||
614 | 2120, 2448, 0, 1344, 1345, 1348, 1394, 0, | ||
615 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
616 | /* 1729x1344@75Hz */ | ||
617 | { DRM_MODE("1792x1344", DRM_MODE_TYPE_DRIVER, 261000, 1792, 1888, | ||
618 | 2104, 2456, 0, 1344, 1345, 1348, 1417, 0, | ||
619 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
620 | /* 1853x1392@60Hz */ | ||
621 | { DRM_MODE("1856x1392", DRM_MODE_TYPE_DRIVER, 218250, 1856, 1952, | ||
622 | 2176, 2528, 0, 1392, 1393, 1396, 1439, 0, | ||
623 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
624 | /* 1856x1392@75Hz */ | ||
625 | { DRM_MODE("1856x1392", DRM_MODE_TYPE_DRIVER, 288000, 1856, 1984, | ||
626 | 2208, 2560, 0, 1392, 1395, 1399, 1500, 0, | ||
627 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
628 | /* 1920x1200@60Hz */ | ||
629 | { DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 193250, 1920, 2056, | ||
630 | 2256, 2592, 0, 1200, 1203, 1209, 1245, 0, | ||
631 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
632 | /* 1920x1200@75Hz */ | ||
633 | { DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 245250, 1920, 2056, | ||
634 | 2264, 2608, 0, 1200, 1203, 1209, 1255, 0, | ||
635 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
636 | /* 1920x1200@85Hz */ | ||
637 | { DRM_MODE("1920x1200", DRM_MODE_TYPE_DRIVER, 281250, 1920, 2064, | ||
638 | 2272, 2624, 0, 1200, 1203, 1209, 1262, 0, | ||
639 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
640 | /* 1920x1440@60Hz */ | ||
641 | { DRM_MODE("1920x1440", DRM_MODE_TYPE_DRIVER, 234000, 1920, 2048, | ||
642 | 2256, 2600, 0, 1440, 1441, 1444, 1500, 0, | ||
643 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
644 | /* 1920x1440@75Hz */ | ||
645 | { DRM_MODE("1920x1440", DRM_MODE_TYPE_DRIVER, 297000, 1920, 2064, | ||
646 | 2288, 2640, 0, 1440, 1441, 1444, 1500, 0, | ||
647 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
648 | /* 2560x1600@60Hz */ | ||
649 | { DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 348500, 2560, 2752, | ||
650 | 3032, 3504, 0, 1600, 1603, 1609, 1658, 0, | ||
651 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
652 | /* 2560x1600@75HZ */ | ||
653 | { DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 443250, 2560, 2768, | ||
654 | 3048, 3536, 0, 1600, 1603, 1609, 1672, 0, | ||
655 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
656 | /* 2560x1600@85HZ */ | ||
657 | { DRM_MODE("2560x1600", DRM_MODE_TYPE_DRIVER, 505250, 2560, 2768, | ||
658 | 3048, 3536, 0, 1600, 1603, 1609, 1682, 0, | ||
659 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, | ||
660 | }; | ||
661 | static const int drm_num_dmt_modes = | ||
662 | sizeof(drm_dmt_modes) / sizeof(struct drm_display_mode); | ||
663 | |||
664 | struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev, | 436 | struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev, |
665 | int hsize, int vsize, int fresh) | 437 | int hsize, int vsize, int fresh) |
666 | { | 438 | { |
@@ -685,6 +457,46 @@ EXPORT_SYMBOL(drm_mode_find_dmt); | |||
685 | typedef void detailed_cb(struct detailed_timing *timing, void *closure); | 457 | typedef void detailed_cb(struct detailed_timing *timing, void *closure); |
686 | 458 | ||
687 | static void | 459 | static void |
460 | cea_for_each_detailed_block(u8 *ext, detailed_cb *cb, void *closure) | ||
461 | { | ||
462 | int i, n = 0; | ||
463 | u8 rev = ext[0x01], d = ext[0x02]; | ||
464 | u8 *det_base = ext + d; | ||
465 | |||
466 | switch (rev) { | ||
467 | case 0: | ||
468 | /* can't happen */ | ||
469 | return; | ||
470 | case 1: | ||
471 | /* have to infer how many blocks we have, check pixel clock */ | ||
472 | for (i = 0; i < 6; i++) | ||
473 | if (det_base[18*i] || det_base[18*i+1]) | ||
474 | n++; | ||
475 | break; | ||
476 | default: | ||
477 | /* explicit count */ | ||
478 | n = min(ext[0x03] & 0x0f, 6); | ||
479 | break; | ||
480 | } | ||
481 | |||
482 | for (i = 0; i < n; i++) | ||
483 | cb((struct detailed_timing *)(det_base + 18 * i), closure); | ||
484 | } | ||
485 | |||
486 | static void | ||
487 | vtb_for_each_detailed_block(u8 *ext, detailed_cb *cb, void *closure) | ||
488 | { | ||
489 | unsigned int i, n = min((int)ext[0x02], 6); | ||
490 | u8 *det_base = ext + 5; | ||
491 | |||
492 | if (ext[0x01] != 1) | ||
493 | return; /* unknown version */ | ||
494 | |||
495 | for (i = 0; i < n; i++) | ||
496 | cb((struct detailed_timing *)(det_base + 18 * i), closure); | ||
497 | } | ||
498 | |||
499 | static void | ||
688 | drm_for_each_detailed_block(u8 *raw_edid, detailed_cb *cb, void *closure) | 500 | drm_for_each_detailed_block(u8 *raw_edid, detailed_cb *cb, void *closure) |
689 | { | 501 | { |
690 | int i; | 502 | int i; |
@@ -696,7 +508,19 @@ drm_for_each_detailed_block(u8 *raw_edid, detailed_cb *cb, void *closure) | |||
696 | for (i = 0; i < EDID_DETAILED_TIMINGS; i++) | 508 | for (i = 0; i < EDID_DETAILED_TIMINGS; i++) |
697 | cb(&(edid->detailed_timings[i]), closure); | 509 | cb(&(edid->detailed_timings[i]), closure); |
698 | 510 | ||
699 | /* XXX extension block walk */ | 511 | for (i = 1; i <= raw_edid[0x7e]; i++) { |
512 | u8 *ext = raw_edid + (i * EDID_LENGTH); | ||
513 | switch (*ext) { | ||
514 | case CEA_EXT: | ||
515 | cea_for_each_detailed_block(ext, cb, closure); | ||
516 | break; | ||
517 | case VTB_EXT: | ||
518 | vtb_for_each_detailed_block(ext, cb, closure); | ||
519 | break; | ||
520 | default: | ||
521 | break; | ||
522 | } | ||
523 | } | ||
700 | } | 524 | } |
701 | 525 | ||
702 | static void | 526 | static void |
@@ -1047,117 +871,6 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, | |||
1047 | return mode; | 871 | return mode; |
1048 | } | 872 | } |
1049 | 873 | ||
1050 | /* | ||
1051 | * Detailed mode info for the EDID "established modes" data to use. | ||
1052 | */ | ||
1053 | static struct drm_display_mode edid_est_modes[] = { | ||
1054 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840, | ||
1055 | 968, 1056, 0, 600, 601, 605, 628, 0, | ||
1056 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 800x600@60Hz */ | ||
1057 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 36000, 800, 824, | ||
1058 | 896, 1024, 0, 600, 601, 603, 625, 0, | ||
1059 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 800x600@56Hz */ | ||
1060 | { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 31500, 640, 656, | ||
1061 | 720, 840, 0, 480, 481, 484, 500, 0, | ||
1062 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 640x480@75Hz */ | ||
1063 | { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 31500, 640, 664, | ||
1064 | 704, 832, 0, 480, 489, 491, 520, 0, | ||
1065 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 640x480@72Hz */ | ||
1066 | { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 30240, 640, 704, | ||
1067 | 768, 864, 0, 480, 483, 486, 525, 0, | ||
1068 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 640x480@67Hz */ | ||
1069 | { DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25200, 640, 656, | ||
1070 | 752, 800, 0, 480, 490, 492, 525, 0, | ||
1071 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 640x480@60Hz */ | ||
1072 | { DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 35500, 720, 738, | ||
1073 | 846, 900, 0, 400, 421, 423, 449, 0, | ||
1074 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 720x400@88Hz */ | ||
1075 | { DRM_MODE("720x400", DRM_MODE_TYPE_DRIVER, 28320, 720, 738, | ||
1076 | 846, 900, 0, 400, 412, 414, 449, 0, | ||
1077 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 720x400@70Hz */ | ||
1078 | { DRM_MODE("1280x1024", DRM_MODE_TYPE_DRIVER, 135000, 1280, 1296, | ||
1079 | 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, | ||
1080 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 1280x1024@75Hz */ | ||
1081 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 78800, 1024, 1040, | ||
1082 | 1136, 1312, 0, 768, 769, 772, 800, 0, | ||
1083 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 1024x768@75Hz */ | ||
1084 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 75000, 1024, 1048, | ||
1085 | 1184, 1328, 0, 768, 771, 777, 806, 0, | ||
1086 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 1024x768@70Hz */ | ||
1087 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048, | ||
1088 | 1184, 1344, 0, 768, 771, 777, 806, 0, | ||
1089 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 1024x768@60Hz */ | ||
1090 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER,44900, 1024, 1032, | ||
1091 | 1208, 1264, 0, 768, 768, 776, 817, 0, | ||
1092 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_INTERLACE) }, /* 1024x768@43Hz */ | ||
1093 | { DRM_MODE("832x624", DRM_MODE_TYPE_DRIVER, 57284, 832, 864, | ||
1094 | 928, 1152, 0, 624, 625, 628, 667, 0, | ||
1095 | DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC) }, /* 832x624@75Hz */ | ||
1096 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 49500, 800, 816, | ||
1097 | 896, 1056, 0, 600, 601, 604, 625, 0, | ||
1098 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 800x600@75Hz */ | ||
1099 | { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 50000, 800, 856, | ||
1100 | 976, 1040, 0, 600, 637, 643, 666, 0, | ||
1101 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 800x600@72Hz */ | ||
1102 | { DRM_MODE("1152x864", DRM_MODE_TYPE_DRIVER, 108000, 1152, 1216, | ||
1103 | 1344, 1600, 0, 864, 865, 868, 900, 0, | ||
1104 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 1152x864@75Hz */ | ||
1105 | }; | ||
1106 | |||
1107 | /** | ||
1108 | * add_established_modes - get est. modes from EDID and add them | ||
1109 | * @edid: EDID block to scan | ||
1110 | * | ||
1111 | * Each EDID block contains a bitmap of the supported "established modes" list | ||
1112 | * (defined above). Tease them out and add them to the global modes list. | ||
1113 | */ | ||
1114 | static int add_established_modes(struct drm_connector *connector, struct edid *edid) | ||
1115 | { | ||
1116 | struct drm_device *dev = connector->dev; | ||
1117 | unsigned long est_bits = edid->established_timings.t1 | | ||
1118 | (edid->established_timings.t2 << 8) | | ||
1119 | ((edid->established_timings.mfg_rsvd & 0x80) << 9); | ||
1120 | int i, modes = 0; | ||
1121 | |||
1122 | for (i = 0; i <= EDID_EST_TIMINGS; i++) | ||
1123 | if (est_bits & (1<<i)) { | ||
1124 | struct drm_display_mode *newmode; | ||
1125 | newmode = drm_mode_duplicate(dev, &edid_est_modes[i]); | ||
1126 | if (newmode) { | ||
1127 | drm_mode_probed_add(connector, newmode); | ||
1128 | modes++; | ||
1129 | } | ||
1130 | } | ||
1131 | |||
1132 | return modes; | ||
1133 | } | ||
1134 | |||
1135 | /** | ||
1136 | * add_standard_modes - get std. modes from EDID and add them | ||
1137 | * @edid: EDID block to scan | ||
1138 | * | ||
1139 | * Standard modes can be calculated using the CVT standard. Grab them from | ||
1140 | * @edid, calculate them, and add them to the list. | ||
1141 | */ | ||
1142 | static int add_standard_modes(struct drm_connector *connector, struct edid *edid) | ||
1143 | { | ||
1144 | int i, modes = 0; | ||
1145 | |||
1146 | for (i = 0; i < EDID_STD_TIMINGS; i++) { | ||
1147 | struct drm_display_mode *newmode; | ||
1148 | |||
1149 | newmode = drm_mode_std(connector, edid, | ||
1150 | &edid->standard_timings[i], | ||
1151 | edid->revision); | ||
1152 | if (newmode) { | ||
1153 | drm_mode_probed_add(connector, newmode); | ||
1154 | modes++; | ||
1155 | } | ||
1156 | } | ||
1157 | |||
1158 | return modes; | ||
1159 | } | ||
1160 | |||
1161 | static bool | 874 | static bool |
1162 | mode_is_rb(struct drm_display_mode *mode) | 875 | mode_is_rb(struct drm_display_mode *mode) |
1163 | { | 876 | { |
@@ -1267,113 +980,33 @@ drm_gtf_modes_for_range(struct drm_connector *connector, struct edid *edid, | |||
1267 | return modes; | 980 | return modes; |
1268 | } | 981 | } |
1269 | 982 | ||
1270 | static int drm_cvt_modes(struct drm_connector *connector, | 983 | static void |
1271 | struct detailed_timing *timing) | 984 | do_inferred_modes(struct detailed_timing *timing, void *c) |
1272 | { | 985 | { |
1273 | int i, j, modes = 0; | 986 | struct detailed_mode_closure *closure = c; |
1274 | struct drm_display_mode *newmode; | 987 | struct detailed_non_pixel *data = &timing->data.other_data; |
1275 | struct drm_device *dev = connector->dev; | 988 | int gtf = (closure->edid->features & DRM_EDID_FEATURE_DEFAULT_GTF); |
1276 | struct cvt_timing *cvt; | ||
1277 | const int rates[] = { 60, 85, 75, 60, 50 }; | ||
1278 | const u8 empty[3] = { 0, 0, 0 }; | ||
1279 | |||
1280 | for (i = 0; i < 4; i++) { | ||
1281 | int uninitialized_var(width), height; | ||
1282 | cvt = &(timing->data.other_data.data.cvt[i]); | ||
1283 | 989 | ||
1284 | if (!memcmp(cvt->code, empty, 3)) | 990 | if (gtf && data->type == EDID_DETAIL_MONITOR_RANGE) |
1285 | continue; | 991 | closure->modes += drm_gtf_modes_for_range(closure->connector, |
992 | closure->edid, | ||
993 | timing); | ||
994 | } | ||
1286 | 995 | ||
1287 | height = (cvt->code[0] + ((cvt->code[1] & 0xf0) << 4) + 1) * 2; | 996 | static int |
1288 | switch (cvt->code[1] & 0x0c) { | 997 | add_inferred_modes(struct drm_connector *connector, struct edid *edid) |
1289 | case 0x00: | 998 | { |
1290 | width = height * 4 / 3; | 999 | struct detailed_mode_closure closure = { |
1291 | break; | 1000 | connector, edid, 0, 0, 0 |
1292 | case 0x04: | 1001 | }; |
1293 | width = height * 16 / 9; | ||
1294 | break; | ||
1295 | case 0x08: | ||
1296 | width = height * 16 / 10; | ||
1297 | break; | ||
1298 | case 0x0c: | ||
1299 | width = height * 15 / 9; | ||
1300 | break; | ||
1301 | } | ||
1302 | 1002 | ||
1303 | for (j = 1; j < 5; j++) { | 1003 | if (version_greater(edid, 1, 0)) |
1304 | if (cvt->code[2] & (1 << j)) { | 1004 | drm_for_each_detailed_block((u8 *)edid, do_inferred_modes, |
1305 | newmode = drm_cvt_mode(dev, width, height, | 1005 | &closure); |
1306 | rates[j], j == 0, | ||
1307 | false, false); | ||
1308 | if (newmode) { | ||
1309 | drm_mode_probed_add(connector, newmode); | ||
1310 | modes++; | ||
1311 | } | ||
1312 | } | ||
1313 | } | ||
1314 | } | ||
1315 | 1006 | ||
1316 | return modes; | 1007 | return closure.modes; |
1317 | } | 1008 | } |
1318 | 1009 | ||
1319 | static const struct { | ||
1320 | short w; | ||
1321 | short h; | ||
1322 | short r; | ||
1323 | short rb; | ||
1324 | } est3_modes[] = { | ||
1325 | /* byte 6 */ | ||
1326 | { 640, 350, 85, 0 }, | ||
1327 | { 640, 400, 85, 0 }, | ||
1328 | { 720, 400, 85, 0 }, | ||
1329 | { 640, 480, 85, 0 }, | ||
1330 | { 848, 480, 60, 0 }, | ||
1331 | { 800, 600, 85, 0 }, | ||
1332 | { 1024, 768, 85, 0 }, | ||
1333 | { 1152, 864, 75, 0 }, | ||
1334 | /* byte 7 */ | ||
1335 | { 1280, 768, 60, 1 }, | ||
1336 | { 1280, 768, 60, 0 }, | ||
1337 | { 1280, 768, 75, 0 }, | ||
1338 | { 1280, 768, 85, 0 }, | ||
1339 | { 1280, 960, 60, 0 }, | ||
1340 | { 1280, 960, 85, 0 }, | ||
1341 | { 1280, 1024, 60, 0 }, | ||
1342 | { 1280, 1024, 85, 0 }, | ||
1343 | /* byte 8 */ | ||
1344 | { 1360, 768, 60, 0 }, | ||
1345 | { 1440, 900, 60, 1 }, | ||
1346 | { 1440, 900, 60, 0 }, | ||
1347 | { 1440, 900, 75, 0 }, | ||
1348 | { 1440, 900, 85, 0 }, | ||
1349 | { 1400, 1050, 60, 1 }, | ||
1350 | { 1400, 1050, 60, 0 }, | ||
1351 | { 1400, 1050, 75, 0 }, | ||
1352 | /* byte 9 */ | ||
1353 | { 1400, 1050, 85, 0 }, | ||
1354 | { 1680, 1050, 60, 1 }, | ||
1355 | { 1680, 1050, 60, 0 }, | ||
1356 | { 1680, 1050, 75, 0 }, | ||
1357 | { 1680, 1050, 85, 0 }, | ||
1358 | { 1600, 1200, 60, 0 }, | ||
1359 | { 1600, 1200, 65, 0 }, | ||
1360 | { 1600, 1200, 70, 0 }, | ||
1361 | /* byte 10 */ | ||
1362 | { 1600, 1200, 75, 0 }, | ||
1363 | { 1600, 1200, 85, 0 }, | ||
1364 | { 1792, 1344, 60, 0 }, | ||
1365 | { 1792, 1344, 85, 0 }, | ||
1366 | { 1856, 1392, 60, 0 }, | ||
1367 | { 1856, 1392, 75, 0 }, | ||
1368 | { 1920, 1200, 60, 1 }, | ||
1369 | { 1920, 1200, 60, 0 }, | ||
1370 | /* byte 11 */ | ||
1371 | { 1920, 1200, 75, 0 }, | ||
1372 | { 1920, 1200, 85, 0 }, | ||
1373 | { 1920, 1440, 60, 0 }, | ||
1374 | { 1920, 1440, 75, 0 }, | ||
1375 | }; | ||
1376 | |||
1377 | static int | 1010 | static int |
1378 | drm_est3_modes(struct drm_connector *connector, struct detailed_timing *timing) | 1011 | drm_est3_modes(struct drm_connector *connector, struct detailed_timing *timing) |
1379 | { | 1012 | { |
@@ -1403,37 +1036,63 @@ drm_est3_modes(struct drm_connector *connector, struct detailed_timing *timing) | |||
1403 | return modes; | 1036 | return modes; |
1404 | } | 1037 | } |
1405 | 1038 | ||
1406 | static int add_detailed_modes(struct drm_connector *connector, | 1039 | static void |
1407 | struct detailed_timing *timing, | 1040 | do_established_modes(struct detailed_timing *timing, void *c) |
1408 | struct edid *edid, u32 quirks, int preferred) | ||
1409 | { | 1041 | { |
1410 | int i, modes = 0; | 1042 | struct detailed_mode_closure *closure = c; |
1411 | struct detailed_non_pixel *data = &timing->data.other_data; | 1043 | struct detailed_non_pixel *data = &timing->data.other_data; |
1412 | int gtf = (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF); | ||
1413 | struct drm_display_mode *newmode; | ||
1414 | struct drm_device *dev = connector->dev; | ||
1415 | 1044 | ||
1416 | if (timing->pixel_clock) { | 1045 | if (data->type == EDID_DETAIL_EST_TIMINGS) |
1417 | newmode = drm_mode_detailed(dev, edid, timing, quirks); | 1046 | closure->modes += drm_est3_modes(closure->connector, timing); |
1418 | if (!newmode) | 1047 | } |
1419 | return 0; | ||
1420 | 1048 | ||
1421 | if (preferred) | 1049 | /** |
1422 | newmode->type |= DRM_MODE_TYPE_PREFERRED; | 1050 | * add_established_modes - get est. modes from EDID and add them |
1051 | * @edid: EDID block to scan | ||
1052 | * | ||
1053 | * Each EDID block contains a bitmap of the supported "established modes" list | ||
1054 | * (defined above). Tease them out and add them to the global modes list. | ||
1055 | */ | ||
1056 | static int | ||
1057 | add_established_modes(struct drm_connector *connector, struct edid *edid) | ||
1058 | { | ||
1059 | struct drm_device *dev = connector->dev; | ||
1060 | unsigned long est_bits = edid->established_timings.t1 | | ||
1061 | (edid->established_timings.t2 << 8) | | ||
1062 | ((edid->established_timings.mfg_rsvd & 0x80) << 9); | ||
1063 | int i, modes = 0; | ||
1064 | struct detailed_mode_closure closure = { | ||
1065 | connector, edid, 0, 0, 0 | ||
1066 | }; | ||
1423 | 1067 | ||
1424 | drm_mode_probed_add(connector, newmode); | 1068 | for (i = 0; i <= EDID_EST_TIMINGS; i++) { |
1425 | return 1; | 1069 | if (est_bits & (1<<i)) { |
1070 | struct drm_display_mode *newmode; | ||
1071 | newmode = drm_mode_duplicate(dev, &edid_est_modes[i]); | ||
1072 | if (newmode) { | ||
1073 | drm_mode_probed_add(connector, newmode); | ||
1074 | modes++; | ||
1075 | } | ||
1076 | } | ||
1426 | } | 1077 | } |
1427 | 1078 | ||
1428 | /* other timing types */ | 1079 | if (version_greater(edid, 1, 0)) |
1429 | switch (data->type) { | 1080 | drm_for_each_detailed_block((u8 *)edid, |
1430 | case EDID_DETAIL_MONITOR_RANGE: | 1081 | do_established_modes, &closure); |
1431 | if (gtf) | 1082 | |
1432 | modes += drm_gtf_modes_for_range(connector, edid, | 1083 | return modes + closure.modes; |
1433 | timing); | 1084 | } |
1434 | break; | 1085 | |
1435 | case EDID_DETAIL_STD_MODES: | 1086 | static void |
1436 | /* Six modes per detailed section */ | 1087 | do_standard_modes(struct detailed_timing *timing, void *c) |
1088 | { | ||
1089 | struct detailed_mode_closure *closure = c; | ||
1090 | struct detailed_non_pixel *data = &timing->data.other_data; | ||
1091 | struct drm_connector *connector = closure->connector; | ||
1092 | struct edid *edid = closure->edid; | ||
1093 | |||
1094 | if (data->type == EDID_DETAIL_STD_MODES) { | ||
1095 | int i; | ||
1437 | for (i = 0; i < 6; i++) { | 1096 | for (i = 0; i < 6; i++) { |
1438 | struct std_timing *std; | 1097 | struct std_timing *std; |
1439 | struct drm_display_mode *newmode; | 1098 | struct drm_display_mode *newmode; |
@@ -1443,108 +1102,169 @@ static int add_detailed_modes(struct drm_connector *connector, | |||
1443 | edid->revision); | 1102 | edid->revision); |
1444 | if (newmode) { | 1103 | if (newmode) { |
1445 | drm_mode_probed_add(connector, newmode); | 1104 | drm_mode_probed_add(connector, newmode); |
1446 | modes++; | 1105 | closure->modes++; |
1447 | } | 1106 | } |
1448 | } | 1107 | } |
1449 | break; | ||
1450 | case EDID_DETAIL_CVT_3BYTE: | ||
1451 | modes += drm_cvt_modes(connector, timing); | ||
1452 | break; | ||
1453 | case EDID_DETAIL_EST_TIMINGS: | ||
1454 | modes += drm_est3_modes(connector, timing); | ||
1455 | break; | ||
1456 | default: | ||
1457 | break; | ||
1458 | } | 1108 | } |
1459 | |||
1460 | return modes; | ||
1461 | } | 1109 | } |
1462 | 1110 | ||
1463 | /** | 1111 | /** |
1464 | * add_detailed_info - get detailed mode info from EDID data | 1112 | * add_standard_modes - get std. modes from EDID and add them |
1465 | * @connector: attached connector | ||
1466 | * @edid: EDID block to scan | 1113 | * @edid: EDID block to scan |
1467 | * @quirks: quirks to apply | ||
1468 | * | 1114 | * |
1469 | * Some of the detailed timing sections may contain mode information. Grab | 1115 | * Standard modes can be calculated using the appropriate standard (DMT, |
1470 | * it and add it to the list. | 1116 | * GTF or CVT. Grab them from @edid and add them to the list. |
1471 | */ | 1117 | */ |
1472 | static int add_detailed_info(struct drm_connector *connector, | 1118 | static int |
1473 | struct edid *edid, u32 quirks) | 1119 | add_standard_modes(struct drm_connector *connector, struct edid *edid) |
1474 | { | 1120 | { |
1475 | int i, modes = 0; | 1121 | int i, modes = 0; |
1122 | struct detailed_mode_closure closure = { | ||
1123 | connector, edid, 0, 0, 0 | ||
1124 | }; | ||
1125 | |||
1126 | for (i = 0; i < EDID_STD_TIMINGS; i++) { | ||
1127 | struct drm_display_mode *newmode; | ||
1128 | |||
1129 | newmode = drm_mode_std(connector, edid, | ||
1130 | &edid->standard_timings[i], | ||
1131 | edid->revision); | ||
1132 | if (newmode) { | ||
1133 | drm_mode_probed_add(connector, newmode); | ||
1134 | modes++; | ||
1135 | } | ||
1136 | } | ||
1137 | |||
1138 | if (version_greater(edid, 1, 0)) | ||
1139 | drm_for_each_detailed_block((u8 *)edid, do_standard_modes, | ||
1140 | &closure); | ||
1141 | |||
1142 | /* XXX should also look for standard codes in VTB blocks */ | ||
1143 | |||
1144 | return modes + closure.modes; | ||
1145 | } | ||
1476 | 1146 | ||
1477 | for (i = 0; i < EDID_DETAILED_TIMINGS; i++) { | 1147 | static int drm_cvt_modes(struct drm_connector *connector, |
1478 | struct detailed_timing *timing = &edid->detailed_timings[i]; | 1148 | struct detailed_timing *timing) |
1479 | int preferred = (i == 0); | 1149 | { |
1150 | int i, j, modes = 0; | ||
1151 | struct drm_display_mode *newmode; | ||
1152 | struct drm_device *dev = connector->dev; | ||
1153 | struct cvt_timing *cvt; | ||
1154 | const int rates[] = { 60, 85, 75, 60, 50 }; | ||
1155 | const u8 empty[3] = { 0, 0, 0 }; | ||
1480 | 1156 | ||
1481 | if (preferred && edid->version == 1 && edid->revision < 4) | 1157 | for (i = 0; i < 4; i++) { |
1482 | preferred = (edid->features & DRM_EDID_FEATURE_PREFERRED_TIMING); | 1158 | int uninitialized_var(width), height; |
1159 | cvt = &(timing->data.other_data.data.cvt[i]); | ||
1483 | 1160 | ||
1484 | /* In 1.0, only timings are allowed */ | 1161 | if (!memcmp(cvt->code, empty, 3)) |
1485 | if (!timing->pixel_clock && edid->version == 1 && | ||
1486 | edid->revision == 0) | ||
1487 | continue; | 1162 | continue; |
1488 | 1163 | ||
1489 | modes += add_detailed_modes(connector, timing, edid, quirks, | 1164 | height = (cvt->code[0] + ((cvt->code[1] & 0xf0) << 4) + 1) * 2; |
1490 | preferred); | 1165 | switch (cvt->code[1] & 0x0c) { |
1166 | case 0x00: | ||
1167 | width = height * 4 / 3; | ||
1168 | break; | ||
1169 | case 0x04: | ||
1170 | width = height * 16 / 9; | ||
1171 | break; | ||
1172 | case 0x08: | ||
1173 | width = height * 16 / 10; | ||
1174 | break; | ||
1175 | case 0x0c: | ||
1176 | width = height * 15 / 9; | ||
1177 | break; | ||
1178 | } | ||
1179 | |||
1180 | for (j = 1; j < 5; j++) { | ||
1181 | if (cvt->code[2] & (1 << j)) { | ||
1182 | newmode = drm_cvt_mode(dev, width, height, | ||
1183 | rates[j], j == 0, | ||
1184 | false, false); | ||
1185 | if (newmode) { | ||
1186 | drm_mode_probed_add(connector, newmode); | ||
1187 | modes++; | ||
1188 | } | ||
1189 | } | ||
1190 | } | ||
1491 | } | 1191 | } |
1492 | 1192 | ||
1493 | return modes; | 1193 | return modes; |
1494 | } | 1194 | } |
1495 | 1195 | ||
1496 | /** | 1196 | static void |
1497 | * add_detailed_mode_eedid - get detailed mode info from addtional timing | 1197 | do_cvt_mode(struct detailed_timing *timing, void *c) |
1498 | * EDID block | ||
1499 | * @connector: attached connector | ||
1500 | * @edid: EDID block to scan(It is only to get addtional timing EDID block) | ||
1501 | * @quirks: quirks to apply | ||
1502 | * | ||
1503 | * Some of the detailed timing sections may contain mode information. Grab | ||
1504 | * it and add it to the list. | ||
1505 | */ | ||
1506 | static int add_detailed_info_eedid(struct drm_connector *connector, | ||
1507 | struct edid *edid, u32 quirks) | ||
1508 | { | 1198 | { |
1509 | int i, modes = 0; | 1199 | struct detailed_mode_closure *closure = c; |
1510 | char *edid_ext = NULL; | 1200 | struct detailed_non_pixel *data = &timing->data.other_data; |
1511 | struct detailed_timing *timing; | ||
1512 | int start_offset, end_offset; | ||
1513 | 1201 | ||
1514 | if (edid->version == 1 && edid->revision < 3) | 1202 | if (data->type == EDID_DETAIL_CVT_3BYTE) |
1515 | return 0; | 1203 | closure->modes += drm_cvt_modes(closure->connector, timing); |
1516 | if (!edid->extensions) | 1204 | } |
1517 | return 0; | ||
1518 | 1205 | ||
1519 | /* Find CEA extension */ | 1206 | static int |
1520 | for (i = 0; i < edid->extensions; i++) { | 1207 | add_cvt_modes(struct drm_connector *connector, struct edid *edid) |
1521 | edid_ext = (char *)edid + EDID_LENGTH * (i + 1); | 1208 | { |
1522 | if (edid_ext[0] == 0x02) | 1209 | struct detailed_mode_closure closure = { |
1523 | break; | 1210 | connector, edid, 0, 0, 0 |
1524 | } | 1211 | }; |
1525 | 1212 | ||
1526 | if (i == edid->extensions) | 1213 | if (version_greater(edid, 1, 2)) |
1527 | return 0; | 1214 | drm_for_each_detailed_block((u8 *)edid, do_cvt_mode, &closure); |
1528 | 1215 | ||
1529 | /* Get the start offset of detailed timing block */ | 1216 | /* XXX should also look for CVT codes in VTB blocks */ |
1530 | start_offset = edid_ext[2]; | ||
1531 | if (start_offset == 0) { | ||
1532 | /* If the start_offset is zero, it means that neither detailed | ||
1533 | * info nor data block exist. In such case it is also | ||
1534 | * unnecessary to parse the detailed timing info. | ||
1535 | */ | ||
1536 | return 0; | ||
1537 | } | ||
1538 | 1217 | ||
1539 | end_offset = EDID_LENGTH; | 1218 | return closure.modes; |
1540 | end_offset -= sizeof(struct detailed_timing); | 1219 | } |
1541 | for (i = start_offset; i < end_offset; | 1220 | |
1542 | i += sizeof(struct detailed_timing)) { | 1221 | static void |
1543 | timing = (struct detailed_timing *)(edid_ext + i); | 1222 | do_detailed_mode(struct detailed_timing *timing, void *c) |
1544 | modes += add_detailed_modes(connector, timing, edid, quirks, 0); | 1223 | { |
1224 | struct detailed_mode_closure *closure = c; | ||
1225 | struct drm_display_mode *newmode; | ||
1226 | |||
1227 | if (timing->pixel_clock) { | ||
1228 | newmode = drm_mode_detailed(closure->connector->dev, | ||
1229 | closure->edid, timing, | ||
1230 | closure->quirks); | ||
1231 | if (!newmode) | ||
1232 | return; | ||
1233 | |||
1234 | if (closure->preferred) | ||
1235 | newmode->type |= DRM_MODE_TYPE_PREFERRED; | ||
1236 | |||
1237 | drm_mode_probed_add(closure->connector, newmode); | ||
1238 | closure->modes++; | ||
1239 | closure->preferred = 0; | ||
1545 | } | 1240 | } |
1241 | } | ||
1546 | 1242 | ||
1547 | return modes; | 1243 | /* |
1244 | * add_detailed_modes - Add modes from detailed timings | ||
1245 | * @connector: attached connector | ||
1246 | * @edid: EDID block to scan | ||
1247 | * @quirks: quirks to apply | ||
1248 | */ | ||
1249 | static int | ||
1250 | add_detailed_modes(struct drm_connector *connector, struct edid *edid, | ||
1251 | u32 quirks) | ||
1252 | { | ||
1253 | struct detailed_mode_closure closure = { | ||
1254 | connector, | ||
1255 | edid, | ||
1256 | 1, | ||
1257 | quirks, | ||
1258 | 0 | ||
1259 | }; | ||
1260 | |||
1261 | if (closure.preferred && !version_greater(edid, 1, 3)) | ||
1262 | closure.preferred = | ||
1263 | (edid->features & DRM_EDID_FEATURE_PREFERRED_TIMING); | ||
1264 | |||
1265 | drm_for_each_detailed_block((u8 *)edid, do_detailed_mode, &closure); | ||
1266 | |||
1267 | return closure.modes; | ||
1548 | } | 1268 | } |
1549 | 1269 | ||
1550 | #define HDMI_IDENTIFIER 0x000C03 | 1270 | #define HDMI_IDENTIFIER 0x000C03 |
@@ -1640,35 +1360,21 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid) | |||
1640 | * - established timing codes | 1360 | * - established timing codes |
1641 | * - modes inferred from GTF or CVT range information | 1361 | * - modes inferred from GTF or CVT range information |
1642 | * | 1362 | * |
1643 | * We don't quite implement this yet, but we're close. | 1363 | * We get this pretty much right. |
1644 | * | 1364 | * |
1645 | * XXX order for additional mode types in extension blocks? | 1365 | * XXX order for additional mode types in extension blocks? |
1646 | */ | 1366 | */ |
1647 | num_modes += add_detailed_info(connector, edid, quirks); | 1367 | num_modes += add_detailed_modes(connector, edid, quirks); |
1648 | num_modes += add_detailed_info_eedid(connector, edid, quirks); | 1368 | num_modes += add_cvt_modes(connector, edid); |
1649 | num_modes += add_standard_modes(connector, edid); | 1369 | num_modes += add_standard_modes(connector, edid); |
1650 | num_modes += add_established_modes(connector, edid); | 1370 | num_modes += add_established_modes(connector, edid); |
1371 | num_modes += add_inferred_modes(connector, edid); | ||
1651 | 1372 | ||
1652 | if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75)) | 1373 | if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75)) |
1653 | edid_fixup_preferred(connector, quirks); | 1374 | edid_fixup_preferred(connector, quirks); |
1654 | 1375 | ||
1655 | connector->display_info.serration_vsync = (edid->input & DRM_EDID_INPUT_SERRATION_VSYNC) ? 1 : 0; | ||
1656 | connector->display_info.sync_on_green = (edid->input & DRM_EDID_INPUT_SYNC_ON_GREEN) ? 1 : 0; | ||
1657 | connector->display_info.composite_sync = (edid->input & DRM_EDID_INPUT_COMPOSITE_SYNC) ? 1 : 0; | ||
1658 | connector->display_info.separate_syncs = (edid->input & DRM_EDID_INPUT_SEPARATE_SYNCS) ? 1 : 0; | ||
1659 | connector->display_info.blank_to_black = (edid->input & DRM_EDID_INPUT_BLANK_TO_BLACK) ? 1 : 0; | ||
1660 | connector->display_info.video_level = (edid->input & DRM_EDID_INPUT_VIDEO_LEVEL) >> 5; | ||
1661 | connector->display_info.digital = (edid->input & DRM_EDID_INPUT_DIGITAL) ? 1 : 0; | ||
1662 | connector->display_info.width_mm = edid->width_cm * 10; | 1376 | connector->display_info.width_mm = edid->width_cm * 10; |
1663 | connector->display_info.height_mm = edid->height_cm * 10; | 1377 | connector->display_info.height_mm = edid->height_cm * 10; |
1664 | connector->display_info.gamma = edid->gamma; | ||
1665 | connector->display_info.gtf_supported = (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF) ? 1 : 0; | ||
1666 | connector->display_info.standard_color = (edid->features & DRM_EDID_FEATURE_STANDARD_COLOR) ? 1 : 0; | ||
1667 | connector->display_info.display_type = (edid->features & DRM_EDID_FEATURE_DISPLAY_TYPE) >> 3; | ||
1668 | connector->display_info.active_off_supported = (edid->features & DRM_EDID_FEATURE_PM_ACTIVE_OFF) ? 1 : 0; | ||
1669 | connector->display_info.suspend_supported = (edid->features & DRM_EDID_FEATURE_PM_SUSPEND) ? 1 : 0; | ||
1670 | connector->display_info.standby_supported = (edid->features & DRM_EDID_FEATURE_PM_STANDBY) ? 1 : 0; | ||
1671 | connector->display_info.gamma = edid->gamma; | ||
1672 | 1378 | ||
1673 | return num_modes; | 1379 | return num_modes; |
1674 | } | 1380 | } |