diff options
author | Antonino A. Daplas <adaplas@gmail.com> | 2005-09-09 16:09:58 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-09-09 17:03:39 -0400 |
commit | 96fe6a2109db29cd15b90a093c16e6cb4b19371a (patch) | |
tree | bd3c424f3f43e6b5a2ba6c235c7c25b3ba197f4c /drivers/video/modedb.c | |
parent | 5251bffc9b4ca699993c79166adf02faf1bbc043 (diff) |
[PATCH] fbdev: Add VESA Coordinated Video Timings (CVT) support
The Coordinated Video Timings (CVT) is the latest standard approved by VESA
concerning video timings generation. It addresses the limitation of GTF which
is designed mainly for CRT displays. CRT's have a high blanking requirement
(as much as 25% of the horizontal frame length) which artificially increases
the pixelclock. Digital displays, on the other hand, needs to conserve the
pixelclock as much as possible. The GTF also does not take into account the
different aspect ratios in its calculation.
The new function added is fb_find_mode_cvt(). It is called by fb_find_mode()
if it recognizes a mode option string formatted for CVT. The format is:
<xres>x<yres>[M][R][-<bpp>][<at-sign><refresh>][i][m]
The 'M' tells the function to calculate using CVT. On it's own, it will
compute a timing for CRT displays at 60Hz. If the 'R' is specified, 'reduced
blanking' computation will be used, best for flatpanels. The 'i' and the 'm'
is for 'interlaced mode' and 'with margins' respectively.
To determine if CVT was used, check for dmesg for something like this:
CVT Mode - <pix>M<n>[-R], ie: .480M3-R (800x600 reduced blanking)
where: pix - product of xres and yres, in MB
M - is a CVT mode
n - the aspect ratio (3 - 4:3; 4 - 5:4; 9 - 16:9, 15:9; A - 16:10)
-R - reduced blanking
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/modedb.c')
-rw-r--r-- | drivers/video/modedb.c | 62 |
1 files changed, 60 insertions, 2 deletions
diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c index 3edc9f49344b..47516c44a390 100644 --- a/drivers/video/modedb.c +++ b/drivers/video/modedb.c | |||
@@ -456,12 +456,22 @@ static int fb_try_mode(struct fb_var_screeninfo *var, struct fb_info *info, | |||
456 | * | 456 | * |
457 | * Valid mode specifiers for @mode_option: | 457 | * Valid mode specifiers for @mode_option: |
458 | * | 458 | * |
459 | * <xres>x<yres>[-<bpp>][@<refresh>] or | 459 | * <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m] or |
460 | * <name>[-<bpp>][@<refresh>] | 460 | * <name>[-<bpp>][@<refresh>] |
461 | * | 461 | * |
462 | * with <xres>, <yres>, <bpp> and <refresh> decimal numbers and | 462 | * with <xres>, <yres>, <bpp> and <refresh> decimal numbers and |
463 | * <name> a string. | 463 | * <name> a string. |
464 | * | 464 | * |
465 | * If 'M' is present after yres (and before refresh/bpp if present), | ||
466 | * the function will compute the timings using VESA(tm) Coordinated | ||
467 | * Video Timings (CVT). If 'R' is present after 'M', will compute with | ||
468 | * reduced blanking (for flatpanels). If 'i' is present, compute | ||
469 | * interlaced mode. If 'm' is present, add margins equal to 1.8% | ||
470 | * of xres rounded down to 8 pixels, and 1.8% of yres. The char | ||
471 | * 'i' and 'm' must be after 'M' and 'R'. Example: | ||
472 | * | ||
473 | * 1024x768MR-8@60m - Reduced blank with margins at 60Hz. | ||
474 | * | ||
465 | * NOTE: The passed struct @var is _not_ cleared! This allows you | 475 | * NOTE: The passed struct @var is _not_ cleared! This allows you |
466 | * to supply values for e.g. the grayscale and accel_flags fields. | 476 | * to supply values for e.g. the grayscale and accel_flags fields. |
467 | * | 477 | * |
@@ -495,7 +505,7 @@ int fb_find_mode(struct fb_var_screeninfo *var, | |||
495 | unsigned int namelen = strlen(name); | 505 | unsigned int namelen = strlen(name); |
496 | int res_specified = 0, bpp_specified = 0, refresh_specified = 0; | 506 | int res_specified = 0, bpp_specified = 0, refresh_specified = 0; |
497 | unsigned int xres = 0, yres = 0, bpp = default_bpp, refresh = 0; | 507 | unsigned int xres = 0, yres = 0, bpp = default_bpp, refresh = 0; |
498 | int yres_specified = 0; | 508 | int yres_specified = 0, cvt = 0, rb = 0, interlace = 0, margins = 0; |
499 | u32 best, diff; | 509 | u32 best, diff; |
500 | 510 | ||
501 | for (i = namelen-1; i >= 0; i--) { | 511 | for (i = namelen-1; i >= 0; i--) { |
@@ -506,6 +516,8 @@ int fb_find_mode(struct fb_var_screeninfo *var, | |||
506 | !yres_specified) { | 516 | !yres_specified) { |
507 | refresh = my_atoi(&name[i+1]); | 517 | refresh = my_atoi(&name[i+1]); |
508 | refresh_specified = 1; | 518 | refresh_specified = 1; |
519 | if (cvt || rb) | ||
520 | cvt = 0; | ||
509 | } else | 521 | } else |
510 | goto done; | 522 | goto done; |
511 | break; | 523 | break; |
@@ -514,6 +526,8 @@ int fb_find_mode(struct fb_var_screeninfo *var, | |||
514 | if (!bpp_specified && !yres_specified) { | 526 | if (!bpp_specified && !yres_specified) { |
515 | bpp = my_atoi(&name[i+1]); | 527 | bpp = my_atoi(&name[i+1]); |
516 | bpp_specified = 1; | 528 | bpp_specified = 1; |
529 | if (cvt || rb) | ||
530 | cvt = 0; | ||
517 | } else | 531 | } else |
518 | goto done; | 532 | goto done; |
519 | break; | 533 | break; |
@@ -526,6 +540,22 @@ int fb_find_mode(struct fb_var_screeninfo *var, | |||
526 | break; | 540 | break; |
527 | case '0'...'9': | 541 | case '0'...'9': |
528 | break; | 542 | break; |
543 | case 'M': | ||
544 | if (!yres_specified) | ||
545 | cvt = 1; | ||
546 | break; | ||
547 | case 'R': | ||
548 | if (!cvt) | ||
549 | rb = 1; | ||
550 | break; | ||
551 | case 'm': | ||
552 | if (!cvt) | ||
553 | margins = 1; | ||
554 | break; | ||
555 | case 'i': | ||
556 | if (!cvt) | ||
557 | interlace = 1; | ||
558 | break; | ||
529 | default: | 559 | default: |
530 | goto done; | 560 | goto done; |
531 | } | 561 | } |
@@ -535,6 +565,34 @@ int fb_find_mode(struct fb_var_screeninfo *var, | |||
535 | res_specified = 1; | 565 | res_specified = 1; |
536 | } | 566 | } |
537 | done: | 567 | done: |
568 | if (cvt) { | ||
569 | struct fb_videomode cvt_mode; | ||
570 | int ret; | ||
571 | |||
572 | DPRINTK("CVT mode %dx%d@%dHz%s%s%s\n", xres, yres, | ||
573 | (refresh) ? refresh : 60, (rb) ? " reduced blanking" : | ||
574 | "", (margins) ? " with margins" : "", (interlace) ? | ||
575 | " interlaced" : ""); | ||
576 | |||
577 | cvt_mode.xres = xres; | ||
578 | cvt_mode.yres = yres; | ||
579 | cvt_mode.refresh = (refresh) ? refresh : 60; | ||
580 | |||
581 | if (interlace) | ||
582 | cvt_mode.vmode |= FB_VMODE_INTERLACED; | ||
583 | else | ||
584 | cvt_mode.vmode &= ~FB_VMODE_INTERLACED; | ||
585 | |||
586 | ret = fb_find_mode_cvt(&cvt_mode, margins, rb); | ||
587 | |||
588 | if (!ret && !fb_try_mode(var, info, &cvt_mode, bpp)) { | ||
589 | DPRINTK("modedb CVT: CVT mode ok\n"); | ||
590 | return 1; | ||
591 | } | ||
592 | |||
593 | DPRINTK("CVT mode invalid, getting mode from database\n"); | ||
594 | } | ||
595 | |||
538 | DPRINTK("Trying specified video mode%s %ix%i\n", | 596 | DPRINTK("Trying specified video mode%s %ix%i\n", |
539 | refresh_specified ? "" : " (ignoring refresh rate)", xres, yres); | 597 | refresh_specified ? "" : " (ignoring refresh rate)", xres, yres); |
540 | 598 | ||