aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/fbmon.c
diff options
context:
space:
mode:
authorAntonino A. Daplas <adaplas@gmail.com>2006-06-26 03:26:29 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-06-26 12:58:29 -0400
commit3007683144b2d53008363f5a7b36a78c53710db4 (patch)
treedc738feee436ec164fb841f82d015f33e9d36e83 /drivers/video/fbmon.c
parent22f4a00fd5207a107fb81984f7b4cc09e5047b45 (diff)
[PATCH] fbdev: More accurate sync range extrapolation
The EDID block should specify the display's operating limits (vertical and horizontal sync ranges, and maximum dot clock). If not given by the EDID block, the ranges are extrapolated from the modelist. However, the computation used is only a rough approximation, and the resulting values may not reflect the actual capability of the display. This problem is frequently encountered when the EDID block has a single entry, the single mode entry will fail validation. To prevent this, calculate the values based on the same method used in fb_validate_mode(). Signed-off-by: Antonino Daplas <adaplas@pol.net> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/video/fbmon.c')
-rw-r--r--drivers/video/fbmon.c28
1 files changed, 24 insertions, 4 deletions
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c
index fbbcb7156a34..87b0224d2347 100644
--- a/drivers/video/fbmon.c
+++ b/drivers/video/fbmon.c
@@ -605,6 +605,7 @@ static int fb_get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs)
605 block = edid + DETAILED_TIMING_DESCRIPTIONS_START; 605 block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
606 606
607 DPRINTK(" Monitor Operating Limits: "); 607 DPRINTK(" Monitor Operating Limits: ");
608
608 for (i = 0; i < 4; i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) { 609 for (i = 0; i < 4; i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) {
609 if (edid_is_limits_block(block)) { 610 if (edid_is_limits_block(block)) {
610 specs->hfmin = H_MIN_RATE * 1000; 611 specs->hfmin = H_MIN_RATE * 1000;
@@ -618,11 +619,12 @@ static int fb_get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs)
618 break; 619 break;
619 } 620 }
620 } 621 }
621 622
622 /* estimate monitor limits based on modes supported */ 623 /* estimate monitor limits based on modes supported */
623 if (retval) { 624 if (retval) {
624 struct fb_videomode *modes; 625 struct fb_videomode *modes, *mode;
625 int num_modes, i, hz, hscan, pixclock; 626 int num_modes, i, hz, hscan, pixclock;
627 int vtotal, htotal;
626 628
627 modes = fb_create_modedb(edid, &num_modes); 629 modes = fb_create_modedb(edid, &num_modes);
628 if (!modes) { 630 if (!modes) {
@@ -632,20 +634,38 @@ static int fb_get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs)
632 634
633 retval = 0; 635 retval = 0;
634 for (i = 0; i < num_modes; i++) { 636 for (i = 0; i < num_modes; i++) {
635 hz = modes[i].refresh; 637 mode = &modes[i];
636 pixclock = PICOS2KHZ(modes[i].pixclock) * 1000; 638 pixclock = PICOS2KHZ(modes[i].pixclock) * 1000;
637 hscan = (modes[i].yres * 105 * hz + 5000)/100; 639 htotal = mode->xres + mode->right_margin + mode->hsync_len
640 + mode->left_margin;
641 vtotal = mode->yres + mode->lower_margin + mode->vsync_len
642 + mode->upper_margin;
643
644 if (mode->vmode & FB_VMODE_INTERLACED)
645 vtotal /= 2;
646
647 if (mode->vmode & FB_VMODE_DOUBLE)
648 vtotal *= 2;
649
650 hscan = (pixclock + htotal / 2) / htotal;
651 hscan = (hscan + 500) / 1000 * 1000;
652 hz = (hscan + vtotal / 2) / vtotal;
638 653
639 if (specs->dclkmax == 0 || specs->dclkmax < pixclock) 654 if (specs->dclkmax == 0 || specs->dclkmax < pixclock)
640 specs->dclkmax = pixclock; 655 specs->dclkmax = pixclock;
656
641 if (specs->dclkmin == 0 || specs->dclkmin > pixclock) 657 if (specs->dclkmin == 0 || specs->dclkmin > pixclock)
642 specs->dclkmin = pixclock; 658 specs->dclkmin = pixclock;
659
643 if (specs->hfmax == 0 || specs->hfmax < hscan) 660 if (specs->hfmax == 0 || specs->hfmax < hscan)
644 specs->hfmax = hscan; 661 specs->hfmax = hscan;
662
645 if (specs->hfmin == 0 || specs->hfmin > hscan) 663 if (specs->hfmin == 0 || specs->hfmin > hscan)
646 specs->hfmin = hscan; 664 specs->hfmin = hscan;
665
647 if (specs->vfmax == 0 || specs->vfmax < hz) 666 if (specs->vfmax == 0 || specs->vfmax < hz)
648 specs->vfmax = hz; 667 specs->vfmax = hz;
668
649 if (specs->vfmin == 0 || specs->vfmin > hz) 669 if (specs->vfmin == 0 || specs->vfmin > hz)
650 specs->vfmin = hz; 670 specs->vfmin = hz;
651 } 671 }