diff options
Diffstat (limited to 'drivers/video/cirrusfb.c')
-rw-r--r-- | drivers/video/cirrusfb.c | 577 |
1 files changed, 213 insertions, 364 deletions
diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c index e729fb279645..048b139f0e50 100644 --- a/drivers/video/cirrusfb.c +++ b/drivers/video/cirrusfb.c | |||
@@ -327,29 +327,7 @@ static const struct { | |||
327 | #endif /* CONFIG_ZORRO */ | 327 | #endif /* CONFIG_ZORRO */ |
328 | 328 | ||
329 | struct cirrusfb_regs { | 329 | struct cirrusfb_regs { |
330 | long freq; | 330 | int multiplexing; |
331 | long nom; | ||
332 | long den; | ||
333 | long div; | ||
334 | long multiplexing; | ||
335 | long mclk; | ||
336 | long divMCLK; | ||
337 | |||
338 | long HorizRes; /* The x resolution in pixel */ | ||
339 | long HorizTotal; | ||
340 | long HorizDispEnd; | ||
341 | long HorizBlankStart; | ||
342 | long HorizBlankEnd; | ||
343 | long HorizSyncStart; | ||
344 | long HorizSyncEnd; | ||
345 | |||
346 | long VertRes; /* the physical y resolution in scanlines */ | ||
347 | long VertTotal; | ||
348 | long VertDispEnd; | ||
349 | long VertSyncStart; | ||
350 | long VertSyncEnd; | ||
351 | long VertBlankStart; | ||
352 | long VertBlankEnd; | ||
353 | }; | 331 | }; |
354 | 332 | ||
355 | #ifdef CIRRUSFB_DEBUG | 333 | #ifdef CIRRUSFB_DEBUG |
@@ -367,110 +345,13 @@ struct cirrusfb_info { | |||
367 | 345 | ||
368 | struct cirrusfb_regs currentmode; | 346 | struct cirrusfb_regs currentmode; |
369 | int blank_mode; | 347 | int blank_mode; |
348 | u32 pseudo_palette[16]; | ||
370 | 349 | ||
371 | u32 pseudo_palette[16]; | ||
372 | |||
373 | #ifdef CONFIG_ZORRO | ||
374 | struct zorro_dev *zdev; | ||
375 | #endif | ||
376 | #ifdef CONFIG_PCI | ||
377 | struct pci_dev *pdev; | ||
378 | #endif | ||
379 | void (*unmap)(struct fb_info *info); | 350 | void (*unmap)(struct fb_info *info); |
380 | }; | 351 | }; |
381 | 352 | ||
382 | static unsigned cirrusfb_def_mode = 1; | 353 | static int noaccel __devinitdata; |
383 | static int noaccel; | 354 | static char *mode_option __devinitdata = "640x480@60"; |
384 | |||
385 | /* | ||
386 | * Predefined Video Modes | ||
387 | */ | ||
388 | |||
389 | static const struct { | ||
390 | const char *name; | ||
391 | struct fb_var_screeninfo var; | ||
392 | } cirrusfb_predefined[] = { | ||
393 | { | ||
394 | /* autodetect mode */ | ||
395 | .name = "Autodetect", | ||
396 | }, { | ||
397 | /* 640x480, 31.25 kHz, 60 Hz, 25 MHz PixClock */ | ||
398 | .name = "640x480", | ||
399 | .var = { | ||
400 | .xres = 640, | ||
401 | .yres = 480, | ||
402 | .xres_virtual = 640, | ||
403 | .yres_virtual = 480, | ||
404 | .bits_per_pixel = 8, | ||
405 | .red = { .length = 8 }, | ||
406 | .green = { .length = 8 }, | ||
407 | .blue = { .length = 8 }, | ||
408 | .width = -1, | ||
409 | .height = -1, | ||
410 | .pixclock = 40000, | ||
411 | .left_margin = 48, | ||
412 | .right_margin = 16, | ||
413 | .upper_margin = 32, | ||
414 | .lower_margin = 8, | ||
415 | .hsync_len = 96, | ||
416 | .vsync_len = 4, | ||
417 | .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | ||
418 | .vmode = FB_VMODE_NONINTERLACED | ||
419 | } | ||
420 | }, { | ||
421 | /* 800x600, 48 kHz, 76 Hz, 50 MHz PixClock */ | ||
422 | .name = "800x600", | ||
423 | .var = { | ||
424 | .xres = 800, | ||
425 | .yres = 600, | ||
426 | .xres_virtual = 800, | ||
427 | .yres_virtual = 600, | ||
428 | .bits_per_pixel = 8, | ||
429 | .red = { .length = 8 }, | ||
430 | .green = { .length = 8 }, | ||
431 | .blue = { .length = 8 }, | ||
432 | .width = -1, | ||
433 | .height = -1, | ||
434 | .pixclock = 20000, | ||
435 | .left_margin = 128, | ||
436 | .right_margin = 16, | ||
437 | .upper_margin = 24, | ||
438 | .lower_margin = 2, | ||
439 | .hsync_len = 96, | ||
440 | .vsync_len = 6, | ||
441 | .vmode = FB_VMODE_NONINTERLACED | ||
442 | } | ||
443 | }, { | ||
444 | /* | ||
445 | * Modeline from XF86Config: | ||
446 | * Mode "1024x768" 80 1024 1136 1340 1432 768 770 774 805 | ||
447 | */ | ||
448 | /* 1024x768, 55.8 kHz, 70 Hz, 80 MHz PixClock */ | ||
449 | .name = "1024x768", | ||
450 | .var = { | ||
451 | .xres = 1024, | ||
452 | .yres = 768, | ||
453 | .xres_virtual = 1024, | ||
454 | .yres_virtual = 768, | ||
455 | .bits_per_pixel = 8, | ||
456 | .red = { .length = 8 }, | ||
457 | .green = { .length = 8 }, | ||
458 | .blue = { .length = 8 }, | ||
459 | .width = -1, | ||
460 | .height = -1, | ||
461 | .pixclock = 12500, | ||
462 | .left_margin = 144, | ||
463 | .right_margin = 32, | ||
464 | .upper_margin = 30, | ||
465 | .lower_margin = 2, | ||
466 | .hsync_len = 192, | ||
467 | .vsync_len = 6, | ||
468 | .vmode = FB_VMODE_NONINTERLACED | ||
469 | } | ||
470 | } | ||
471 | }; | ||
472 | |||
473 | #define NUM_TOTAL_MODES ARRAY_SIZE(cirrusfb_predefined) | ||
474 | 355 | ||
475 | /****************************************************************************/ | 356 | /****************************************************************************/ |
476 | /**** BEGIN PROTOTYPES ******************************************************/ | 357 | /**** BEGIN PROTOTYPES ******************************************************/ |
@@ -514,10 +395,6 @@ static struct fb_ops cirrusfb_ops = { | |||
514 | .fb_imageblit = cirrusfb_imageblit, | 395 | .fb_imageblit = cirrusfb_imageblit, |
515 | }; | 396 | }; |
516 | 397 | ||
517 | /*--- Hardware Specific Routines -------------------------------------------*/ | ||
518 | static int cirrusfb_decode_var(const struct fb_var_screeninfo *var, | ||
519 | struct cirrusfb_regs *regs, | ||
520 | struct fb_info *info); | ||
521 | /*--- Internal routines ----------------------------------------------------*/ | 398 | /*--- Internal routines ----------------------------------------------------*/ |
522 | static void init_vgachip(struct fb_info *info); | 399 | static void init_vgachip(struct fb_info *info); |
523 | static void switch_monitor(struct cirrusfb_info *cinfo, int on); | 400 | static void switch_monitor(struct cirrusfb_info *cinfo, int on); |
@@ -546,9 +423,7 @@ static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel, | |||
546 | u_short width, u_short height, | 423 | u_short width, u_short height, |
547 | u_char color, u_short line_length); | 424 | u_char color, u_short line_length); |
548 | 425 | ||
549 | static void bestclock(long freq, long *best, | 426 | static void bestclock(long freq, int *nom, int *den, int *div); |
550 | long *nom, long *den, | ||
551 | long *div, long maxfreq); | ||
552 | 427 | ||
553 | #ifdef CIRRUSFB_DEBUG | 428 | #ifdef CIRRUSFB_DEBUG |
554 | static void cirrusfb_dump(void); | 429 | static void cirrusfb_dump(void); |
@@ -584,45 +459,28 @@ static int cirrusfb_release(struct fb_info *info, int user) | |||
584 | /****************************************************************************/ | 459 | /****************************************************************************/ |
585 | /**** BEGIN Hardware specific Routines **************************************/ | 460 | /**** BEGIN Hardware specific Routines **************************************/ |
586 | 461 | ||
587 | /* Get a good MCLK value */ | 462 | /* Check if the MCLK is not a better clock source */ |
588 | static long cirrusfb_get_mclk(long freq, int bpp, long *div) | 463 | static int cirrusfb_check_mclk(struct cirrusfb_info *cinfo, long freq) |
589 | { | 464 | { |
590 | long mclk; | 465 | long mclk = vga_rseq(cinfo->regbase, CL_SEQR1F) & 0x3f; |
591 | 466 | ||
592 | assert(div != NULL); | 467 | /* Read MCLK value */ |
593 | 468 | mclk = (14318 * mclk) >> 3; | |
594 | /* Calculate MCLK, in case VCLK is high enough to require > 50MHz. | 469 | DPRINTK("Read MCLK of %ld kHz\n", mclk); |
595 | * Assume a 64-bit data path for now. The formula is: | ||
596 | * ((B * PCLK * 2)/W) * 1.2 | ||
597 | * B = bytes per pixel, PCLK = pixclock, W = data width in bytes */ | ||
598 | mclk = ((bpp / 8) * freq * 2) / 4; | ||
599 | mclk = (mclk * 12) / 10; | ||
600 | if (mclk < 50000) | ||
601 | mclk = 50000; | ||
602 | DPRINTK("Use MCLK of %ld kHz\n", mclk); | ||
603 | |||
604 | /* Calculate value for SR1F. Multiply by 2 so we can round up. */ | ||
605 | mclk = ((mclk * 16) / 14318); | ||
606 | mclk = (mclk + 1) / 2; | ||
607 | DPRINTK("Set SR1F[5:0] to 0x%lx\n", mclk); | ||
608 | 470 | ||
609 | /* Determine if we should use MCLK instead of VCLK, and if so, what we | 471 | /* Determine if we should use MCLK instead of VCLK, and if so, what we |
610 | * should divide it by to get VCLK */ | 472 | * should divide it by to get VCLK |
611 | switch (freq) { | 473 | */ |
612 | case 24751 ... 25249: | 474 | |
613 | *div = 2; | 475 | if (abs(freq - mclk) < 250) { |
614 | DPRINTK("Using VCLK = MCLK/2\n"); | ||
615 | break; | ||
616 | case 49501 ... 50499: | ||
617 | *div = 1; | ||
618 | DPRINTK("Using VCLK = MCLK\n"); | 476 | DPRINTK("Using VCLK = MCLK\n"); |
619 | break; | 477 | return 1; |
620 | default: | 478 | } else if (abs(freq - (mclk / 2)) < 250) { |
621 | *div = 0; | 479 | DPRINTK("Using VCLK = MCLK/2\n"); |
622 | break; | 480 | return 2; |
623 | } | 481 | } |
624 | 482 | ||
625 | return mclk; | 483 | return 0; |
626 | } | 484 | } |
627 | 485 | ||
628 | static int cirrusfb_check_var(struct fb_var_screeninfo *var, | 486 | static int cirrusfb_check_var(struct fb_var_screeninfo *var, |
@@ -638,7 +496,6 @@ static int cirrusfb_check_var(struct fb_var_screeninfo *var, | |||
638 | break; /* 8 pixel per byte, only 1/4th of mem usable */ | 496 | break; /* 8 pixel per byte, only 1/4th of mem usable */ |
639 | case 8: | 497 | case 8: |
640 | case 16: | 498 | case 16: |
641 | case 24: | ||
642 | case 32: | 499 | case 32: |
643 | break; /* 1 pixel == 1 byte */ | 500 | break; /* 1 pixel == 1 byte */ |
644 | default: | 501 | default: |
@@ -713,7 +570,6 @@ static int cirrusfb_check_var(struct fb_var_screeninfo *var, | |||
713 | var->blue.length = 5; | 570 | var->blue.length = 5; |
714 | break; | 571 | break; |
715 | 572 | ||
716 | case 24: | ||
717 | case 32: | 573 | case 32: |
718 | if (isPReP) { | 574 | if (isPReP) { |
719 | var->red.offset = 8; | 575 | var->red.offset = 8; |
@@ -767,8 +623,6 @@ static int cirrusfb_decode_var(const struct fb_var_screeninfo *var, | |||
767 | long maxclock; | 623 | long maxclock; |
768 | int maxclockidx = var->bits_per_pixel >> 3; | 624 | int maxclockidx = var->bits_per_pixel >> 3; |
769 | struct cirrusfb_info *cinfo = info->par; | 625 | struct cirrusfb_info *cinfo = info->par; |
770 | int xres, hfront, hsync, hback; | ||
771 | int yres, vfront, vsync, vback; | ||
772 | 626 | ||
773 | switch (var->bits_per_pixel) { | 627 | switch (var->bits_per_pixel) { |
774 | case 1: | 628 | case 1: |
@@ -782,10 +636,9 @@ static int cirrusfb_decode_var(const struct fb_var_screeninfo *var, | |||
782 | break; | 636 | break; |
783 | 637 | ||
784 | case 16: | 638 | case 16: |
785 | case 24: | ||
786 | case 32: | 639 | case 32: |
787 | info->fix.line_length = var->xres_virtual * maxclockidx; | 640 | info->fix.line_length = var->xres_virtual * maxclockidx; |
788 | info->fix.visual = FB_VISUAL_DIRECTCOLOR; | 641 | info->fix.visual = FB_VISUAL_TRUECOLOR; |
789 | break; | 642 | break; |
790 | 643 | ||
791 | default: | 644 | default: |
@@ -827,90 +680,33 @@ static int cirrusfb_decode_var(const struct fb_var_screeninfo *var, | |||
827 | switch (var->bits_per_pixel) { | 680 | switch (var->bits_per_pixel) { |
828 | case 16: | 681 | case 16: |
829 | case 32: | 682 | case 32: |
830 | if (regs->HorizRes <= 800) | 683 | if (var->xres <= 800) |
831 | /* Xbh has this type of clock for 32-bit */ | 684 | /* Xbh has this type of clock for 32-bit */ |
832 | freq /= 2; | 685 | freq /= 2; |
833 | break; | 686 | break; |
834 | } | 687 | } |
835 | #endif | 688 | #endif |
836 | |||
837 | bestclock(freq, ®s->freq, ®s->nom, ®s->den, ®s->div, | ||
838 | maxclock); | ||
839 | regs->mclk = cirrusfb_get_mclk(freq, var->bits_per_pixel, | ||
840 | ®s->divMCLK); | ||
841 | |||
842 | xres = var->xres; | ||
843 | hfront = var->right_margin; | ||
844 | hsync = var->hsync_len; | ||
845 | hback = var->left_margin; | ||
846 | |||
847 | yres = var->yres; | ||
848 | vfront = var->lower_margin; | ||
849 | vsync = var->vsync_len; | ||
850 | vback = var->upper_margin; | ||
851 | |||
852 | if (var->vmode & FB_VMODE_DOUBLE) { | ||
853 | yres *= 2; | ||
854 | vfront *= 2; | ||
855 | vsync *= 2; | ||
856 | vback *= 2; | ||
857 | } else if (var->vmode & FB_VMODE_INTERLACED) { | ||
858 | yres = (yres + 1) / 2; | ||
859 | vfront = (vfront + 1) / 2; | ||
860 | vsync = (vsync + 1) / 2; | ||
861 | vback = (vback + 1) / 2; | ||
862 | } | ||
863 | regs->HorizRes = xres; | ||
864 | regs->HorizTotal = (xres + hfront + hsync + hback) / 8 - 5; | ||
865 | regs->HorizDispEnd = xres / 8 - 1; | ||
866 | regs->HorizBlankStart = xres / 8; | ||
867 | /* does not count with "-5" */ | ||
868 | regs->HorizBlankEnd = regs->HorizTotal + 5; | ||
869 | regs->HorizSyncStart = (xres + hfront) / 8 + 1; | ||
870 | regs->HorizSyncEnd = (xres + hfront + hsync) / 8 + 1; | ||
871 | |||
872 | regs->VertRes = yres; | ||
873 | regs->VertTotal = yres + vfront + vsync + vback - 2; | ||
874 | regs->VertDispEnd = yres - 1; | ||
875 | regs->VertBlankStart = yres; | ||
876 | regs->VertBlankEnd = regs->VertTotal; | ||
877 | regs->VertSyncStart = yres + vfront - 1; | ||
878 | regs->VertSyncEnd = yres + vfront + vsync - 1; | ||
879 | |||
880 | if (regs->VertRes >= 1024) { | ||
881 | regs->VertTotal /= 2; | ||
882 | regs->VertSyncStart /= 2; | ||
883 | regs->VertSyncEnd /= 2; | ||
884 | regs->VertDispEnd /= 2; | ||
885 | } | ||
886 | if (regs->multiplexing) { | ||
887 | regs->HorizTotal /= 2; | ||
888 | regs->HorizSyncStart /= 2; | ||
889 | regs->HorizSyncEnd /= 2; | ||
890 | regs->HorizDispEnd /= 2; | ||
891 | } | ||
892 | |||
893 | return 0; | 689 | return 0; |
894 | } | 690 | } |
895 | 691 | ||
896 | static void cirrusfb_set_mclk(const struct cirrusfb_info *cinfo, int val, | 692 | static void cirrusfb_set_mclk_as_source(const struct cirrusfb_info *cinfo, |
897 | int div) | 693 | int div) |
898 | { | 694 | { |
695 | unsigned char old1f, old1e; | ||
899 | assert(cinfo != NULL); | 696 | assert(cinfo != NULL); |
697 | old1f = vga_rseq(cinfo->regbase, CL_SEQR1F) & ~0x40; | ||
900 | 698 | ||
901 | if (div == 2) { | 699 | if (div) { |
902 | /* VCLK = MCLK/2 */ | 700 | DPRINTK("Set %s as pixclock source.\n", |
903 | unsigned char old = vga_rseq(cinfo->regbase, CL_SEQR1E); | 701 | (div == 2) ? "MCLK/2" : "MCLK"); |
904 | vga_wseq(cinfo->regbase, CL_SEQR1E, old | 0x1); | 702 | old1f |= 0x40; |
905 | vga_wseq(cinfo->regbase, CL_SEQR1F, 0x40 | (val & 0x3f)); | 703 | old1e = vga_rseq(cinfo->regbase, CL_SEQR1E) & ~0x1; |
906 | } else if (div == 1) { | 704 | if (div == 2) |
907 | /* VCLK = MCLK */ | 705 | old1e |= 1; |
908 | unsigned char old = vga_rseq(cinfo->regbase, CL_SEQR1E); | 706 | |
909 | vga_wseq(cinfo->regbase, CL_SEQR1E, old & ~0x1); | 707 | vga_wseq(cinfo->regbase, CL_SEQR1E, old1e); |
910 | vga_wseq(cinfo->regbase, CL_SEQR1F, 0x40 | (val & 0x3f)); | ||
911 | } else { | ||
912 | vga_wseq(cinfo->regbase, CL_SEQR1F, val & 0x3f); | ||
913 | } | 708 | } |
709 | vga_wseq(cinfo->regbase, CL_SEQR1F, old1f); | ||
914 | } | 710 | } |
915 | 711 | ||
916 | /************************************************************************* | 712 | /************************************************************************* |
@@ -927,6 +723,10 @@ static int cirrusfb_set_par_foo(struct fb_info *info) | |||
927 | unsigned char tmp; | 723 | unsigned char tmp; |
928 | int offset = 0, err; | 724 | int offset = 0, err; |
929 | const struct cirrusfb_board_info_rec *bi; | 725 | const struct cirrusfb_board_info_rec *bi; |
726 | int hdispend, hsyncstart, hsyncend, htotal; | ||
727 | int yres, vdispend, vsyncstart, vsyncend, vtotal; | ||
728 | long freq; | ||
729 | int nom, den, div; | ||
930 | 730 | ||
931 | DPRINTK("ENTER\n"); | 731 | DPRINTK("ENTER\n"); |
932 | DPRINTK("Requested mode: %dx%dx%d\n", | 732 | DPRINTK("Requested mode: %dx%dx%d\n", |
@@ -944,76 +744,117 @@ static int cirrusfb_set_par_foo(struct fb_info *info) | |||
944 | 744 | ||
945 | bi = &cirrusfb_board_info[cinfo->btype]; | 745 | bi = &cirrusfb_board_info[cinfo->btype]; |
946 | 746 | ||
747 | hsyncstart = var->xres + var->right_margin; | ||
748 | hsyncend = hsyncstart + var->hsync_len; | ||
749 | htotal = (hsyncend + var->left_margin) / 8 - 5; | ||
750 | hdispend = var->xres / 8 - 1; | ||
751 | hsyncstart = hsyncstart / 8 + 1; | ||
752 | hsyncend = hsyncend / 8 + 1; | ||
753 | |||
754 | yres = var->yres; | ||
755 | vsyncstart = yres + var->lower_margin; | ||
756 | vsyncend = vsyncstart + var->vsync_len; | ||
757 | vtotal = vsyncend + var->upper_margin; | ||
758 | vdispend = yres - 1; | ||
759 | |||
760 | if (var->vmode & FB_VMODE_DOUBLE) { | ||
761 | yres *= 2; | ||
762 | vsyncstart *= 2; | ||
763 | vsyncend *= 2; | ||
764 | vtotal *= 2; | ||
765 | } else if (var->vmode & FB_VMODE_INTERLACED) { | ||
766 | yres = (yres + 1) / 2; | ||
767 | vsyncstart = (vsyncstart + 1) / 2; | ||
768 | vsyncend = (vsyncend + 1) / 2; | ||
769 | vtotal = (vtotal + 1) / 2; | ||
770 | } | ||
771 | |||
772 | vtotal -= 2; | ||
773 | vsyncstart -= 1; | ||
774 | vsyncend -= 1; | ||
775 | |||
776 | if (yres >= 1024) { | ||
777 | vtotal /= 2; | ||
778 | vsyncstart /= 2; | ||
779 | vsyncend /= 2; | ||
780 | vdispend /= 2; | ||
781 | } | ||
782 | if (regs.multiplexing) { | ||
783 | htotal /= 2; | ||
784 | hsyncstart /= 2; | ||
785 | hsyncend /= 2; | ||
786 | hdispend /= 2; | ||
787 | } | ||
947 | /* unlock register VGA_CRTC_H_TOTAL..CRT7 */ | 788 | /* unlock register VGA_CRTC_H_TOTAL..CRT7 */ |
948 | vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, 0x20); /* previously: 0x00) */ | 789 | vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, 0x20); /* previously: 0x00) */ |
949 | 790 | ||
950 | /* if debugging is enabled, all parameters get output before writing */ | 791 | /* if debugging is enabled, all parameters get output before writing */ |
951 | DPRINTK("CRT0: %ld\n", regs.HorizTotal); | 792 | DPRINTK("CRT0: %d\n", htotal); |
952 | vga_wcrt(regbase, VGA_CRTC_H_TOTAL, regs.HorizTotal); | 793 | vga_wcrt(regbase, VGA_CRTC_H_TOTAL, htotal); |
953 | 794 | ||
954 | DPRINTK("CRT1: %ld\n", regs.HorizDispEnd); | 795 | DPRINTK("CRT1: %d\n", hdispend); |
955 | vga_wcrt(regbase, VGA_CRTC_H_DISP, regs.HorizDispEnd); | 796 | vga_wcrt(regbase, VGA_CRTC_H_DISP, hdispend); |
956 | 797 | ||
957 | DPRINTK("CRT2: %ld\n", regs.HorizBlankStart); | 798 | DPRINTK("CRT2: %d\n", var->xres / 8); |
958 | vga_wcrt(regbase, VGA_CRTC_H_BLANK_START, regs.HorizBlankStart); | 799 | vga_wcrt(regbase, VGA_CRTC_H_BLANK_START, var->xres / 8); |
959 | 800 | ||
960 | /* + 128: Compatible read */ | 801 | /* + 128: Compatible read */ |
961 | DPRINTK("CRT3: 128+%ld\n", regs.HorizBlankEnd % 32); | 802 | DPRINTK("CRT3: 128+%d\n", (htotal + 5) % 32); |
962 | vga_wcrt(regbase, VGA_CRTC_H_BLANK_END, | 803 | vga_wcrt(regbase, VGA_CRTC_H_BLANK_END, |
963 | 128 + (regs.HorizBlankEnd % 32)); | 804 | 128 + ((htotal + 5) % 32)); |
964 | 805 | ||
965 | DPRINTK("CRT4: %ld\n", regs.HorizSyncStart); | 806 | DPRINTK("CRT4: %d\n", hsyncstart); |
966 | vga_wcrt(regbase, VGA_CRTC_H_SYNC_START, regs.HorizSyncStart); | 807 | vga_wcrt(regbase, VGA_CRTC_H_SYNC_START, hsyncstart); |
967 | 808 | ||
968 | tmp = regs.HorizSyncEnd % 32; | 809 | tmp = hsyncend % 32; |
969 | if (regs.HorizBlankEnd & 32) | 810 | if ((htotal + 5) & 32) |
970 | tmp += 128; | 811 | tmp += 128; |
971 | DPRINTK("CRT5: %d\n", tmp); | 812 | DPRINTK("CRT5: %d\n", tmp); |
972 | vga_wcrt(regbase, VGA_CRTC_H_SYNC_END, tmp); | 813 | vga_wcrt(regbase, VGA_CRTC_H_SYNC_END, tmp); |
973 | 814 | ||
974 | DPRINTK("CRT6: %ld\n", regs.VertTotal & 0xff); | 815 | DPRINTK("CRT6: %d\n", vtotal & 0xff); |
975 | vga_wcrt(regbase, VGA_CRTC_V_TOTAL, (regs.VertTotal & 0xff)); | 816 | vga_wcrt(regbase, VGA_CRTC_V_TOTAL, vtotal & 0xff); |
976 | 817 | ||
977 | tmp = 16; /* LineCompare bit #9 */ | 818 | tmp = 16; /* LineCompare bit #9 */ |
978 | if (regs.VertTotal & 256) | 819 | if (vtotal & 256) |
979 | tmp |= 1; | 820 | tmp |= 1; |
980 | if (regs.VertDispEnd & 256) | 821 | if (vdispend & 256) |
981 | tmp |= 2; | 822 | tmp |= 2; |
982 | if (regs.VertSyncStart & 256) | 823 | if (vsyncstart & 256) |
983 | tmp |= 4; | 824 | tmp |= 4; |
984 | if (regs.VertBlankStart & 256) | 825 | if ((vdispend + 1) & 256) |
985 | tmp |= 8; | 826 | tmp |= 8; |
986 | if (regs.VertTotal & 512) | 827 | if (vtotal & 512) |
987 | tmp |= 32; | 828 | tmp |= 32; |
988 | if (regs.VertDispEnd & 512) | 829 | if (vdispend & 512) |
989 | tmp |= 64; | 830 | tmp |= 64; |
990 | if (regs.VertSyncStart & 512) | 831 | if (vsyncstart & 512) |
991 | tmp |= 128; | 832 | tmp |= 128; |
992 | DPRINTK("CRT7: %d\n", tmp); | 833 | DPRINTK("CRT7: %d\n", tmp); |
993 | vga_wcrt(regbase, VGA_CRTC_OVERFLOW, tmp); | 834 | vga_wcrt(regbase, VGA_CRTC_OVERFLOW, tmp); |
994 | 835 | ||
995 | tmp = 0x40; /* LineCompare bit #8 */ | 836 | tmp = 0x40; /* LineCompare bit #8 */ |
996 | if (regs.VertBlankStart & 512) | 837 | if ((vdispend + 1) & 512) |
997 | tmp |= 0x20; | 838 | tmp |= 0x20; |
998 | if (var->vmode & FB_VMODE_DOUBLE) | 839 | if (var->vmode & FB_VMODE_DOUBLE) |
999 | tmp |= 0x80; | 840 | tmp |= 0x80; |
1000 | DPRINTK("CRT9: %d\n", tmp); | 841 | DPRINTK("CRT9: %d\n", tmp); |
1001 | vga_wcrt(regbase, VGA_CRTC_MAX_SCAN, tmp); | 842 | vga_wcrt(regbase, VGA_CRTC_MAX_SCAN, tmp); |
1002 | 843 | ||
1003 | DPRINTK("CRT10: %ld\n", regs.VertSyncStart & 0xff); | 844 | DPRINTK("CRT10: %d\n", vsyncstart & 0xff); |
1004 | vga_wcrt(regbase, VGA_CRTC_V_SYNC_START, regs.VertSyncStart & 0xff); | 845 | vga_wcrt(regbase, VGA_CRTC_V_SYNC_START, vsyncstart & 0xff); |
1005 | 846 | ||
1006 | DPRINTK("CRT11: 64+32+%ld\n", regs.VertSyncEnd % 16); | 847 | DPRINTK("CRT11: 64+32+%d\n", vsyncend % 16); |
1007 | vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, regs.VertSyncEnd % 16 + 64 + 32); | 848 | vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, vsyncend % 16 + 64 + 32); |
1008 | 849 | ||
1009 | DPRINTK("CRT12: %ld\n", regs.VertDispEnd & 0xff); | 850 | DPRINTK("CRT12: %d\n", vdispend & 0xff); |
1010 | vga_wcrt(regbase, VGA_CRTC_V_DISP_END, regs.VertDispEnd & 0xff); | 851 | vga_wcrt(regbase, VGA_CRTC_V_DISP_END, vdispend & 0xff); |
1011 | 852 | ||
1012 | DPRINTK("CRT15: %ld\n", regs.VertBlankStart & 0xff); | 853 | DPRINTK("CRT15: %d\n", (vdispend + 1) & 0xff); |
1013 | vga_wcrt(regbase, VGA_CRTC_V_BLANK_START, regs.VertBlankStart & 0xff); | 854 | vga_wcrt(regbase, VGA_CRTC_V_BLANK_START, (vdispend + 1) & 0xff); |
1014 | 855 | ||
1015 | DPRINTK("CRT16: %ld\n", regs.VertBlankEnd & 0xff); | 856 | DPRINTK("CRT16: %d\n", vtotal & 0xff); |
1016 | vga_wcrt(regbase, VGA_CRTC_V_BLANK_END, regs.VertBlankEnd & 0xff); | 857 | vga_wcrt(regbase, VGA_CRTC_V_BLANK_END, vtotal & 0xff); |
1017 | 858 | ||
1018 | DPRINTK("CRT18: 0xff\n"); | 859 | DPRINTK("CRT18: 0xff\n"); |
1019 | vga_wcrt(regbase, VGA_CRTC_LINE_COMPARE, 0xff); | 860 | vga_wcrt(regbase, VGA_CRTC_LINE_COMPARE, 0xff); |
@@ -1021,38 +862,53 @@ static int cirrusfb_set_par_foo(struct fb_info *info) | |||
1021 | tmp = 0; | 862 | tmp = 0; |
1022 | if (var->vmode & FB_VMODE_INTERLACED) | 863 | if (var->vmode & FB_VMODE_INTERLACED) |
1023 | tmp |= 1; | 864 | tmp |= 1; |
1024 | if (regs.HorizBlankEnd & 64) | 865 | if ((htotal + 5) & 64) |
1025 | tmp |= 16; | 866 | tmp |= 16; |
1026 | if (regs.HorizBlankEnd & 128) | 867 | if ((htotal + 5) & 128) |
1027 | tmp |= 32; | 868 | tmp |= 32; |
1028 | if (regs.VertBlankEnd & 256) | 869 | if (vtotal & 256) |
1029 | tmp |= 64; | 870 | tmp |= 64; |
1030 | if (regs.VertBlankEnd & 512) | 871 | if (vtotal & 512) |
1031 | tmp |= 128; | 872 | tmp |= 128; |
1032 | 873 | ||
1033 | DPRINTK("CRT1a: %d\n", tmp); | 874 | DPRINTK("CRT1a: %d\n", tmp); |
1034 | vga_wcrt(regbase, CL_CRT1A, tmp); | 875 | vga_wcrt(regbase, CL_CRT1A, tmp); |
1035 | 876 | ||
877 | freq = PICOS2KHZ(var->pixclock); | ||
878 | bestclock(freq, &nom, &den, &div); | ||
879 | |||
1036 | /* set VCLK0 */ | 880 | /* set VCLK0 */ |
1037 | /* hardware RefClock: 14.31818 MHz */ | 881 | /* hardware RefClock: 14.31818 MHz */ |
1038 | /* formula: VClk = (OSC * N) / (D * (1+P)) */ | 882 | /* formula: VClk = (OSC * N) / (D * (1+P)) */ |
1039 | /* Example: VClk = (14.31818 * 91) / (23 * (1+1)) = 28.325 MHz */ | 883 | /* Example: VClk = (14.31818 * 91) / (23 * (1+1)) = 28.325 MHz */ |
1040 | 884 | ||
1041 | vga_wseq(regbase, CL_SEQRB, regs.nom); | 885 | if (cinfo->btype == BT_ALPINE) { |
1042 | tmp = regs.den << 1; | 886 | /* if freq is close to mclk or mclk/2 select mclk |
1043 | if (regs.div != 0) | 887 | * as clock source |
1044 | tmp |= 1; | 888 | */ |
889 | int divMCLK = cirrusfb_check_mclk(cinfo, freq); | ||
890 | if (divMCLK) { | ||
891 | nom = 0; | ||
892 | cirrusfb_set_mclk_as_source(cinfo, divMCLK); | ||
893 | } | ||
894 | } | ||
895 | if (nom) { | ||
896 | vga_wseq(regbase, CL_SEQRB, nom); | ||
897 | tmp = den << 1; | ||
898 | if (div != 0) | ||
899 | tmp |= 1; | ||
1045 | 900 | ||
1046 | /* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */ | 901 | /* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */ |
1047 | if ((cinfo->btype == BT_SD64) || | 902 | if ((cinfo->btype == BT_SD64) || |
1048 | (cinfo->btype == BT_ALPINE) || | 903 | (cinfo->btype == BT_ALPINE) || |
1049 | (cinfo->btype == BT_GD5480)) | 904 | (cinfo->btype == BT_GD5480)) |
1050 | tmp |= 0x80; | 905 | tmp |= 0x80; |
1051 | 906 | ||
1052 | DPRINTK("CL_SEQR1B: %ld\n", (long) tmp); | 907 | DPRINTK("CL_SEQR1B: %ld\n", (long) tmp); |
1053 | vga_wseq(regbase, CL_SEQR1B, tmp); | 908 | vga_wseq(regbase, CL_SEQR1B, tmp); |
909 | } | ||
1054 | 910 | ||
1055 | if (regs.VertRes >= 1024) | 911 | if (yres >= 1024) |
1056 | /* 1280x1024 */ | 912 | /* 1280x1024 */ |
1057 | vga_wcrt(regbase, VGA_CRTC_MODE, 0xc7); | 913 | vga_wcrt(regbase, VGA_CRTC_MODE, 0xc7); |
1058 | else | 914 | else |
@@ -1066,7 +922,7 @@ static int cirrusfb_set_par_foo(struct fb_info *info) | |||
1066 | /* don't know if it would hurt to also program this if no interlaced */ | 922 | /* don't know if it would hurt to also program this if no interlaced */ |
1067 | /* mode is used, but I feel better this way.. :-) */ | 923 | /* mode is used, but I feel better this way.. :-) */ |
1068 | if (var->vmode & FB_VMODE_INTERLACED) | 924 | if (var->vmode & FB_VMODE_INTERLACED) |
1069 | vga_wcrt(regbase, VGA_CRTC_REGS, regs.HorizTotal / 2); | 925 | vga_wcrt(regbase, VGA_CRTC_REGS, htotal / 2); |
1070 | else | 926 | else |
1071 | vga_wcrt(regbase, VGA_CRTC_REGS, 0x00); /* interlace control */ | 927 | vga_wcrt(regbase, VGA_CRTC_REGS, 0x00); /* interlace control */ |
1072 | 928 | ||
@@ -1240,7 +1096,6 @@ static int cirrusfb_set_par_foo(struct fb_info *info) | |||
1240 | 1096 | ||
1241 | case BT_ALPINE: | 1097 | case BT_ALPINE: |
1242 | DPRINTK(" (for GD543x)\n"); | 1098 | DPRINTK(" (for GD543x)\n"); |
1243 | cirrusfb_set_mclk(cinfo, regs.mclk, regs.divMCLK); | ||
1244 | /* We already set SRF and SR1F */ | 1099 | /* We already set SRF and SR1F */ |
1245 | break; | 1100 | break; |
1246 | 1101 | ||
@@ -1312,11 +1167,7 @@ static int cirrusfb_set_par_foo(struct fb_info *info) | |||
1312 | 1167 | ||
1313 | case BT_ALPINE: | 1168 | case BT_ALPINE: |
1314 | DPRINTK(" (for GD543x)\n"); | 1169 | DPRINTK(" (for GD543x)\n"); |
1315 | if (regs.HorizRes >= 1024) | 1170 | vga_wseq(regbase, CL_SEQR7, 0xa7); |
1316 | vga_wseq(regbase, CL_SEQR7, 0xa7); | ||
1317 | else | ||
1318 | vga_wseq(regbase, CL_SEQR7, 0xa3); | ||
1319 | cirrusfb_set_mclk(cinfo, regs.mclk, regs.divMCLK); | ||
1320 | break; | 1171 | break; |
1321 | 1172 | ||
1322 | case BT_GD5480: | 1173 | case BT_GD5480: |
@@ -1360,7 +1211,7 @@ static int cirrusfb_set_par_foo(struct fb_info *info) | |||
1360 | */ | 1211 | */ |
1361 | 1212 | ||
1362 | else if (var->bits_per_pixel == 32) { | 1213 | else if (var->bits_per_pixel == 32) { |
1363 | DPRINTK("cirrusfb: preparing for 24/32 bit deep display\n"); | 1214 | DPRINTK("cirrusfb: preparing for 32 bit deep display\n"); |
1364 | switch (cinfo->btype) { | 1215 | switch (cinfo->btype) { |
1365 | case BT_SD64: | 1216 | case BT_SD64: |
1366 | /* Extended Sequencer Mode: 256c col. mode */ | 1217 | /* Extended Sequencer Mode: 256c col. mode */ |
@@ -1394,7 +1245,6 @@ static int cirrusfb_set_par_foo(struct fb_info *info) | |||
1394 | case BT_ALPINE: | 1245 | case BT_ALPINE: |
1395 | DPRINTK(" (for GD543x)\n"); | 1246 | DPRINTK(" (for GD543x)\n"); |
1396 | vga_wseq(regbase, CL_SEQR7, 0xa9); | 1247 | vga_wseq(regbase, CL_SEQR7, 0xa9); |
1397 | cirrusfb_set_mclk(cinfo, regs.mclk, regs.divMCLK); | ||
1398 | break; | 1248 | break; |
1399 | 1249 | ||
1400 | case BT_GD5480: | 1250 | case BT_GD5480: |
@@ -1949,8 +1799,6 @@ static void init_vgachip(struct fb_info *info) | |||
1949 | /* misc... */ | 1799 | /* misc... */ |
1950 | WHDR(cinfo, 0); /* Hidden DAC register: - */ | 1800 | WHDR(cinfo, 0); /* Hidden DAC register: - */ |
1951 | 1801 | ||
1952 | printk(KERN_DEBUG "cirrusfb: This board has %ld bytes of DRAM memory\n", | ||
1953 | info->screen_size); | ||
1954 | DPRINTK("EXIT\n"); | 1802 | DPRINTK("EXIT\n"); |
1955 | return; | 1803 | return; |
1956 | } | 1804 | } |
@@ -2122,7 +1970,7 @@ static int release_io_ports; | |||
2122 | * based on the DRAM bandwidth bit and DRAM bank switching bit. This | 1970 | * based on the DRAM bandwidth bit and DRAM bank switching bit. This |
2123 | * works with 1MB, 2MB and 4MB configurations (which the Motorola boards | 1971 | * works with 1MB, 2MB and 4MB configurations (which the Motorola boards |
2124 | * seem to have. */ | 1972 | * seem to have. */ |
2125 | static unsigned int cirrusfb_get_memsize(u8 __iomem *regbase) | 1973 | static unsigned int __devinit cirrusfb_get_memsize(u8 __iomem *regbase) |
2126 | { | 1974 | { |
2127 | unsigned long mem; | 1975 | unsigned long mem; |
2128 | unsigned char SRF; | 1976 | unsigned char SRF; |
@@ -2188,8 +2036,7 @@ static void get_pci_addrs(const struct pci_dev *pdev, | |||
2188 | 2036 | ||
2189 | static void cirrusfb_pci_unmap(struct fb_info *info) | 2037 | static void cirrusfb_pci_unmap(struct fb_info *info) |
2190 | { | 2038 | { |
2191 | struct cirrusfb_info *cinfo = info->par; | 2039 | struct pci_dev *pdev = to_pci_dev(info->device); |
2192 | struct pci_dev *pdev = cinfo->pdev; | ||
2193 | 2040 | ||
2194 | iounmap(info->screen_base); | 2041 | iounmap(info->screen_base); |
2195 | #if 0 /* if system didn't claim this region, we would... */ | 2042 | #if 0 /* if system didn't claim this region, we would... */ |
@@ -2205,20 +2052,22 @@ static void cirrusfb_pci_unmap(struct fb_info *info) | |||
2205 | static void __devexit cirrusfb_zorro_unmap(struct fb_info *info) | 2052 | static void __devexit cirrusfb_zorro_unmap(struct fb_info *info) |
2206 | { | 2053 | { |
2207 | struct cirrusfb_info *cinfo = info->par; | 2054 | struct cirrusfb_info *cinfo = info->par; |
2208 | zorro_release_device(cinfo->zdev); | 2055 | struct zorro_dev *zdev = to_zorro_dev(info->device); |
2056 | |||
2057 | zorro_release_device(zdev); | ||
2209 | 2058 | ||
2210 | if (cinfo->btype == BT_PICASSO4) { | 2059 | if (cinfo->btype == BT_PICASSO4) { |
2211 | cinfo->regbase -= 0x600000; | 2060 | cinfo->regbase -= 0x600000; |
2212 | iounmap((void *)cinfo->regbase); | 2061 | iounmap((void *)cinfo->regbase); |
2213 | iounmap(info->screen_base); | 2062 | iounmap(info->screen_base); |
2214 | } else { | 2063 | } else { |
2215 | if (zorro_resource_start(cinfo->zdev) > 0x01000000) | 2064 | if (zorro_resource_start(zdev) > 0x01000000) |
2216 | iounmap(info->screen_base); | 2065 | iounmap(info->screen_base); |
2217 | } | 2066 | } |
2218 | } | 2067 | } |
2219 | #endif /* CONFIG_ZORRO */ | 2068 | #endif /* CONFIG_ZORRO */ |
2220 | 2069 | ||
2221 | static int cirrusfb_set_fbinfo(struct fb_info *info) | 2070 | static int __devinit cirrusfb_set_fbinfo(struct fb_info *info) |
2222 | { | 2071 | { |
2223 | struct cirrusfb_info *cinfo = info->par; | 2072 | struct cirrusfb_info *cinfo = info->par; |
2224 | struct fb_var_screeninfo *var = &info->var; | 2073 | struct fb_var_screeninfo *var = &info->var; |
@@ -2235,7 +2084,7 @@ static int cirrusfb_set_fbinfo(struct fb_info *info) | |||
2235 | if (cinfo->btype == BT_GD5480) { | 2084 | if (cinfo->btype == BT_GD5480) { |
2236 | if (var->bits_per_pixel == 16) | 2085 | if (var->bits_per_pixel == 16) |
2237 | info->screen_base += 1 * MB_; | 2086 | info->screen_base += 1 * MB_; |
2238 | if (var->bits_per_pixel == 24 || var->bits_per_pixel == 32) | 2087 | if (var->bits_per_pixel == 32) |
2239 | info->screen_base += 2 * MB_; | 2088 | info->screen_base += 2 * MB_; |
2240 | } | 2089 | } |
2241 | 2090 | ||
@@ -2262,7 +2111,7 @@ static int cirrusfb_set_fbinfo(struct fb_info *info) | |||
2262 | return 0; | 2111 | return 0; |
2263 | } | 2112 | } |
2264 | 2113 | ||
2265 | static int cirrusfb_register(struct fb_info *info) | 2114 | static int __devinit cirrusfb_register(struct fb_info *info) |
2266 | { | 2115 | { |
2267 | struct cirrusfb_info *cinfo = info->par; | 2116 | struct cirrusfb_info *cinfo = info->par; |
2268 | int err; | 2117 | int err; |
@@ -2278,23 +2127,27 @@ static int cirrusfb_register(struct fb_info *info) | |||
2278 | /* sanity checks */ | 2127 | /* sanity checks */ |
2279 | assert(btype != BT_NONE); | 2128 | assert(btype != BT_NONE); |
2280 | 2129 | ||
2130 | /* set all the vital stuff */ | ||
2131 | cirrusfb_set_fbinfo(info); | ||
2132 | |||
2281 | DPRINTK("cirrusfb: (RAM start set to: 0x%p)\n", info->screen_base); | 2133 | DPRINTK("cirrusfb: (RAM start set to: 0x%p)\n", info->screen_base); |
2282 | 2134 | ||
2283 | /* Make pretend we've set the var so our structures are in a "good" */ | 2135 | err = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8); |
2284 | /* state, even though we haven't written the mode to the hw yet... */ | 2136 | if (!err) { |
2285 | info->var = cirrusfb_predefined[cirrusfb_def_mode].var; | 2137 | DPRINTK("wrong initial video mode\n"); |
2138 | err = -EINVAL; | ||
2139 | goto err_dealloc_cmap; | ||
2140 | } | ||
2141 | |||
2286 | info->var.activate = FB_ACTIVATE_NOW; | 2142 | info->var.activate = FB_ACTIVATE_NOW; |
2287 | 2143 | ||
2288 | err = cirrusfb_decode_var(&info->var, &cinfo->currentmode, info); | 2144 | err = cirrusfb_decode_var(&info->var, &cinfo->currentmode, info); |
2289 | if (err < 0) { | 2145 | if (err < 0) { |
2290 | /* should never happen */ | 2146 | /* should never happen */ |
2291 | DPRINTK("choking on default var... umm, no good.\n"); | 2147 | DPRINTK("choking on default var... umm, no good.\n"); |
2292 | goto err_unmap_cirrusfb; | 2148 | goto err_dealloc_cmap; |
2293 | } | 2149 | } |
2294 | 2150 | ||
2295 | /* set all the vital stuff */ | ||
2296 | cirrusfb_set_fbinfo(info); | ||
2297 | |||
2298 | err = register_framebuffer(info); | 2151 | err = register_framebuffer(info); |
2299 | if (err < 0) { | 2152 | if (err < 0) { |
2300 | printk(KERN_ERR "cirrusfb: could not register " | 2153 | printk(KERN_ERR "cirrusfb: could not register " |
@@ -2307,7 +2160,6 @@ static int cirrusfb_register(struct fb_info *info) | |||
2307 | 2160 | ||
2308 | err_dealloc_cmap: | 2161 | err_dealloc_cmap: |
2309 | fb_dealloc_cmap(&info->cmap); | 2162 | fb_dealloc_cmap(&info->cmap); |
2310 | err_unmap_cirrusfb: | ||
2311 | cinfo->unmap(info); | 2163 | cinfo->unmap(info); |
2312 | framebuffer_release(info); | 2164 | framebuffer_release(info); |
2313 | return err; | 2165 | return err; |
@@ -2330,8 +2182,8 @@ static void __devexit cirrusfb_cleanup(struct fb_info *info) | |||
2330 | } | 2182 | } |
2331 | 2183 | ||
2332 | #ifdef CONFIG_PCI | 2184 | #ifdef CONFIG_PCI |
2333 | static int cirrusfb_pci_register(struct pci_dev *pdev, | 2185 | static int __devinit cirrusfb_pci_register(struct pci_dev *pdev, |
2334 | const struct pci_device_id *ent) | 2186 | const struct pci_device_id *ent) |
2335 | { | 2187 | { |
2336 | struct cirrusfb_info *cinfo; | 2188 | struct cirrusfb_info *cinfo; |
2337 | struct fb_info *info; | 2189 | struct fb_info *info; |
@@ -2353,7 +2205,6 @@ static int cirrusfb_pci_register(struct pci_dev *pdev, | |||
2353 | } | 2205 | } |
2354 | 2206 | ||
2355 | cinfo = info->par; | 2207 | cinfo = info->par; |
2356 | cinfo->pdev = pdev; | ||
2357 | cinfo->btype = btype = (enum cirrus_board) ent->driver_data; | 2208 | cinfo->btype = btype = (enum cirrus_board) ent->driver_data; |
2358 | 2209 | ||
2359 | DPRINTK(" Found PCI device, base address 0 is 0x%x, btype set to %d\n", | 2210 | DPRINTK(" Found PCI device, base address 0 is 0x%x, btype set to %d\n", |
@@ -2459,8 +2310,8 @@ static struct pci_driver cirrusfb_pci_driver = { | |||
2459 | #endif /* CONFIG_PCI */ | 2310 | #endif /* CONFIG_PCI */ |
2460 | 2311 | ||
2461 | #ifdef CONFIG_ZORRO | 2312 | #ifdef CONFIG_ZORRO |
2462 | static int cirrusfb_zorro_register(struct zorro_dev *z, | 2313 | static int __devinit cirrusfb_zorro_register(struct zorro_dev *z, |
2463 | const struct zorro_device_id *ent) | 2314 | const struct zorro_device_id *ent) |
2464 | { | 2315 | { |
2465 | struct cirrusfb_info *cinfo; | 2316 | struct cirrusfb_info *cinfo; |
2466 | struct fb_info *info; | 2317 | struct fb_info *info; |
@@ -2489,7 +2340,6 @@ static int cirrusfb_zorro_register(struct zorro_dev *z, | |||
2489 | assert(z); | 2340 | assert(z); |
2490 | assert(btype != BT_NONE); | 2341 | assert(btype != BT_NONE); |
2491 | 2342 | ||
2492 | cinfo->zdev = z; | ||
2493 | board_addr = zorro_resource_start(z); | 2343 | board_addr = zorro_resource_start(z); |
2494 | board_size = zorro_resource_len(z); | 2344 | board_size = zorro_resource_len(z); |
2495 | info->screen_size = size; | 2345 | info->screen_size = size; |
@@ -2621,17 +2471,17 @@ static int __init cirrusfb_setup(char *options) { | |||
2621 | return 0; | 2471 | return 0; |
2622 | 2472 | ||
2623 | while ((this_opt = strsep(&options, ",")) != NULL) { | 2473 | while ((this_opt = strsep(&options, ",")) != NULL) { |
2624 | if (!*this_opt) continue; | 2474 | if (!*this_opt) |
2475 | continue; | ||
2625 | 2476 | ||
2626 | DPRINTK("cirrusfb_setup: option '%s'\n", this_opt); | 2477 | DPRINTK("cirrusfb_setup: option '%s'\n", this_opt); |
2627 | 2478 | ||
2628 | for (i = 0; i < NUM_TOTAL_MODES; i++) { | ||
2629 | sprintf(s, "mode:%s", cirrusfb_predefined[i].name); | ||
2630 | if (strcmp(this_opt, s) == 0) | ||
2631 | cirrusfb_def_mode = i; | ||
2632 | } | ||
2633 | if (!strcmp(this_opt, "noaccel")) | 2479 | if (!strcmp(this_opt, "noaccel")) |
2634 | noaccel = 1; | 2480 | noaccel = 1; |
2481 | else if (!strncmp(this_opt, "mode:", 5)) | ||
2482 | mode_option = this_opt + 5; | ||
2483 | else | ||
2484 | mode_option = this_opt; | ||
2635 | } | 2485 | } |
2636 | return 0; | 2486 | return 0; |
2637 | } | 2487 | } |
@@ -2657,6 +2507,11 @@ static void __exit cirrusfb_exit(void) | |||
2657 | 2507 | ||
2658 | module_init(cirrusfb_init); | 2508 | module_init(cirrusfb_init); |
2659 | 2509 | ||
2510 | module_param(mode_option, charp, 0); | ||
2511 | MODULE_PARM_DESC(mode_option, "Initial video mode e.g. '648x480-8@60'"); | ||
2512 | module_param(noaccel, bool, 0); | ||
2513 | MODULE_PARM_DESC(noaccel, "Disable acceleration"); | ||
2514 | |||
2660 | #ifdef MODULE | 2515 | #ifdef MODULE |
2661 | module_exit(cirrusfb_exit); | 2516 | module_exit(cirrusfb_exit); |
2662 | #endif | 2517 | #endif |
@@ -3050,16 +2905,14 @@ static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel, | |||
3050 | * bestclock() - determine closest possible clock lower(?) than the | 2905 | * bestclock() - determine closest possible clock lower(?) than the |
3051 | * desired pixel clock | 2906 | * desired pixel clock |
3052 | **************************************************************************/ | 2907 | **************************************************************************/ |
3053 | static void bestclock(long freq, long *best, long *nom, | 2908 | static void bestclock(long freq, int *nom, int *den, int *div) |
3054 | long *den, long *div, long maxfreq) | ||
3055 | { | 2909 | { |
3056 | long n, h, d, f; | 2910 | int n, d; |
2911 | long h, diff; | ||
3057 | 2912 | ||
3058 | assert(best != NULL); | ||
3059 | assert(nom != NULL); | 2913 | assert(nom != NULL); |
3060 | assert(den != NULL); | 2914 | assert(den != NULL); |
3061 | assert(div != NULL); | 2915 | assert(div != NULL); |
3062 | assert(maxfreq > 0); | ||
3063 | 2916 | ||
3064 | *nom = 0; | 2917 | *nom = 0; |
3065 | *den = 0; | 2918 | *den = 0; |
@@ -3070,51 +2923,47 @@ static void bestclock(long freq, long *best, long *nom, | |||
3070 | if (freq < 8000) | 2923 | if (freq < 8000) |
3071 | freq = 8000; | 2924 | freq = 8000; |
3072 | 2925 | ||
3073 | if (freq > maxfreq) | 2926 | diff = freq; |
3074 | freq = maxfreq; | ||
3075 | |||
3076 | *best = 0; | ||
3077 | f = freq * 10; | ||
3078 | 2927 | ||
3079 | for (n = 32; n < 128; n++) { | 2928 | for (n = 32; n < 128; n++) { |
3080 | d = (143181 * n) / f; | 2929 | int s = 0; |
2930 | |||
2931 | d = (14318 * n) / freq; | ||
3081 | if ((d >= 7) && (d <= 63)) { | 2932 | if ((d >= 7) && (d <= 63)) { |
3082 | if (d > 31) | 2933 | int temp = d; |
3083 | d = (d / 2) * 2; | 2934 | |
3084 | h = (14318 * n) / d; | 2935 | if (temp > 31) { |
3085 | if (abs(h - freq) < abs(*best - freq)) { | 2936 | s = 1; |
3086 | *best = h; | 2937 | temp >>= 1; |
2938 | } | ||
2939 | h = ((14318 * n) / temp) >> s; | ||
2940 | h = h > freq ? h - freq : freq - h; | ||
2941 | if (h < diff) { | ||
2942 | diff = h; | ||
3087 | *nom = n; | 2943 | *nom = n; |
3088 | if (d < 32) { | 2944 | *den = temp; |
3089 | *den = d; | 2945 | *div = s; |
3090 | *div = 0; | ||
3091 | } else { | ||
3092 | *den = d / 2; | ||
3093 | *div = 1; | ||
3094 | } | ||
3095 | } | 2946 | } |
3096 | } | 2947 | } |
3097 | d = DIV_ROUND_UP(143181 * n, f); | 2948 | d++; |
3098 | if ((d >= 7) && (d <= 63)) { | 2949 | if ((d >= 7) && (d <= 63)) { |
3099 | if (d > 31) | 2950 | if (d > 31) { |
3100 | d = (d / 2) * 2; | 2951 | s = 1; |
3101 | h = (14318 * n) / d; | 2952 | d >>= 1; |
3102 | if (abs(h - freq) < abs(*best - freq)) { | 2953 | } |
3103 | *best = h; | 2954 | h = ((14318 * n) / d) >> s; |
2955 | h = h > freq ? h - freq : freq - h; | ||
2956 | if (h < diff) { | ||
2957 | diff = h; | ||
3104 | *nom = n; | 2958 | *nom = n; |
3105 | if (d < 32) { | 2959 | *den = d; |
3106 | *den = d; | 2960 | *div = s; |
3107 | *div = 0; | ||
3108 | } else { | ||
3109 | *den = d / 2; | ||
3110 | *div = 1; | ||
3111 | } | ||
3112 | } | 2961 | } |
3113 | } | 2962 | } |
3114 | } | 2963 | } |
3115 | 2964 | ||
3116 | DPRINTK("Best possible values for given frequency:\n"); | 2965 | DPRINTK("Best possible values for given frequency:\n"); |
3117 | DPRINTK(" best: %ld kHz nom: %ld den: %ld div: %ld\n", | 2966 | DPRINTK(" freq: %ld kHz nom: %d den: %d div: %d\n", |
3118 | freq, *nom, *den, *div); | 2967 | freq, *nom, *den, *div); |
3119 | 2968 | ||
3120 | DPRINTK("EXIT\n"); | 2969 | DPRINTK("EXIT\n"); |