diff options
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 | ||
