Skip to content

Commit

Permalink
[PATCH] fbdev: More accurate sync range extrapolation
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Antonino A. Daplas authored and Linus Torvalds committed Jun 26, 2006
1 parent 22f4a00 commit 3007683
Showing 1 changed file with 24 additions and 4 deletions.
28 changes: 24 additions & 4 deletions drivers/video/fbmon.c
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,7 @@ static int fb_get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs)
block = edid + DETAILED_TIMING_DESCRIPTIONS_START;

DPRINTK(" Monitor Operating Limits: ");

for (i = 0; i < 4; i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) {
if (edid_is_limits_block(block)) {
specs->hfmin = H_MIN_RATE * 1000;
Expand All @@ -618,11 +619,12 @@ static int fb_get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs)
break;
}
}

/* estimate monitor limits based on modes supported */
if (retval) {
struct fb_videomode *modes;
struct fb_videomode *modes, *mode;
int num_modes, i, hz, hscan, pixclock;
int vtotal, htotal;

modes = fb_create_modedb(edid, &num_modes);
if (!modes) {
Expand All @@ -632,20 +634,38 @@ static int fb_get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs)

retval = 0;
for (i = 0; i < num_modes; i++) {
hz = modes[i].refresh;
mode = &modes[i];
pixclock = PICOS2KHZ(modes[i].pixclock) * 1000;
hscan = (modes[i].yres * 105 * hz + 5000)/100;
htotal = mode->xres + mode->right_margin + mode->hsync_len
+ mode->left_margin;
vtotal = mode->yres + mode->lower_margin + mode->vsync_len
+ mode->upper_margin;

if (mode->vmode & FB_VMODE_INTERLACED)
vtotal /= 2;

if (mode->vmode & FB_VMODE_DOUBLE)
vtotal *= 2;

hscan = (pixclock + htotal / 2) / htotal;
hscan = (hscan + 500) / 1000 * 1000;
hz = (hscan + vtotal / 2) / vtotal;

if (specs->dclkmax == 0 || specs->dclkmax < pixclock)
specs->dclkmax = pixclock;

if (specs->dclkmin == 0 || specs->dclkmin > pixclock)
specs->dclkmin = pixclock;

if (specs->hfmax == 0 || specs->hfmax < hscan)
specs->hfmax = hscan;

if (specs->hfmin == 0 || specs->hfmin > hscan)
specs->hfmin = hscan;

if (specs->vfmax == 0 || specs->vfmax < hz)
specs->vfmax = hz;

if (specs->vfmin == 0 || specs->vfmin > hz)
specs->vfmin = hz;
}
Expand Down

0 comments on commit 3007683

Please sign in to comment.