diff options
Diffstat (limited to 'drivers/video/s3fb.c')
-rw-r--r-- | drivers/video/s3fb.c | 101 |
1 files changed, 81 insertions, 20 deletions
diff --git a/drivers/video/s3fb.c b/drivers/video/s3fb.c index d4471b4c0374..dce8c97b4333 100644 --- a/drivers/video/s3fb.c +++ b/drivers/video/s3fb.c | |||
@@ -71,7 +71,8 @@ static const char * const s3_names[] = {"S3 Unknown", "S3 Trio32", "S3 Trio64", | |||
71 | "S3 Trio64UV+", "S3 Trio64V2/DX", "S3 Trio64V2/GX", | 71 | "S3 Trio64UV+", "S3 Trio64V2/DX", "S3 Trio64V2/GX", |
72 | "S3 Plato/PX", "S3 Aurora64VP", "S3 Virge", | 72 | "S3 Plato/PX", "S3 Aurora64VP", "S3 Virge", |
73 | "S3 Virge/VX", "S3 Virge/DX", "S3 Virge/GX", | 73 | "S3 Virge/VX", "S3 Virge/DX", "S3 Virge/GX", |
74 | "S3 Virge/GX2", "S3 Virge/GX2P", "S3 Virge/GX2P"}; | 74 | "S3 Virge/GX2", "S3 Virge/GX2P", "S3 Virge/GX2P", |
75 | "S3 Trio3D/1X", "S3 Trio3D/2X", "S3 Trio3D/2X"}; | ||
75 | 76 | ||
76 | #define CHIP_UNKNOWN 0x00 | 77 | #define CHIP_UNKNOWN 0x00 |
77 | #define CHIP_732_TRIO32 0x01 | 78 | #define CHIP_732_TRIO32 0x01 |
@@ -89,10 +90,14 @@ static const char * const s3_names[] = {"S3 Unknown", "S3 Trio32", "S3 Trio64", | |||
89 | #define CHIP_356_VIRGE_GX2 0x0D | 90 | #define CHIP_356_VIRGE_GX2 0x0D |
90 | #define CHIP_357_VIRGE_GX2P 0x0E | 91 | #define CHIP_357_VIRGE_GX2P 0x0E |
91 | #define CHIP_359_VIRGE_GX2P 0x0F | 92 | #define CHIP_359_VIRGE_GX2P 0x0F |
93 | #define CHIP_360_TRIO3D_1X 0x10 | ||
94 | #define CHIP_362_TRIO3D_2X 0x11 | ||
95 | #define CHIP_368_TRIO3D_2X 0x12 | ||
92 | 96 | ||
93 | #define CHIP_XXX_TRIO 0x80 | 97 | #define CHIP_XXX_TRIO 0x80 |
94 | #define CHIP_XXX_TRIO64V2_DXGX 0x81 | 98 | #define CHIP_XXX_TRIO64V2_DXGX 0x81 |
95 | #define CHIP_XXX_VIRGE_DXGX 0x82 | 99 | #define CHIP_XXX_VIRGE_DXGX 0x82 |
100 | #define CHIP_36X_TRIO3D_1X_2X 0x83 | ||
96 | 101 | ||
97 | #define CHIP_UNDECIDED_FLAG 0x80 | 102 | #define CHIP_UNDECIDED_FLAG 0x80 |
98 | #define CHIP_MASK 0xFF | 103 | #define CHIP_MASK 0xFF |
@@ -324,6 +329,7 @@ static void s3fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) | |||
324 | 329 | ||
325 | static void s3_set_pixclock(struct fb_info *info, u32 pixclock) | 330 | static void s3_set_pixclock(struct fb_info *info, u32 pixclock) |
326 | { | 331 | { |
332 | struct s3fb_info *par = info->par; | ||
327 | u16 m, n, r; | 333 | u16 m, n, r; |
328 | u8 regval; | 334 | u8 regval; |
329 | int rv; | 335 | int rv; |
@@ -339,7 +345,13 @@ static void s3_set_pixclock(struct fb_info *info, u32 pixclock) | |||
339 | vga_w(NULL, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD); | 345 | vga_w(NULL, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD); |
340 | 346 | ||
341 | /* Set S3 clock registers */ | 347 | /* Set S3 clock registers */ |
342 | vga_wseq(NULL, 0x12, ((n - 2) | (r << 5))); | 348 | if (par->chip == CHIP_360_TRIO3D_1X || |
349 | par->chip == CHIP_362_TRIO3D_2X || | ||
350 | par->chip == CHIP_368_TRIO3D_2X) { | ||
351 | vga_wseq(NULL, 0x12, (n - 2) | ((r & 3) << 6)); /* n and two bits of r */ | ||
352 | vga_wseq(NULL, 0x29, r >> 2); /* remaining highest bit of r */ | ||
353 | } else | ||
354 | vga_wseq(NULL, 0x12, (n - 2) | (r << 5)); | ||
343 | vga_wseq(NULL, 0x13, m - 2); | 355 | vga_wseq(NULL, 0x13, m - 2); |
344 | 356 | ||
345 | udelay(1000); | 357 | udelay(1000); |
@@ -456,7 +468,7 @@ static int s3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | |||
456 | static int s3fb_set_par(struct fb_info *info) | 468 | static int s3fb_set_par(struct fb_info *info) |
457 | { | 469 | { |
458 | struct s3fb_info *par = info->par; | 470 | struct s3fb_info *par = info->par; |
459 | u32 value, mode, hmul, offset_value, screen_size, multiplex; | 471 | u32 value, mode, hmul, offset_value, screen_size, multiplex, dbytes; |
460 | u32 bpp = info->var.bits_per_pixel; | 472 | u32 bpp = info->var.bits_per_pixel; |
461 | 473 | ||
462 | if (bpp != 0) { | 474 | if (bpp != 0) { |
@@ -518,7 +530,7 @@ static int s3fb_set_par(struct fb_info *info) | |||
518 | svga_wcrt_mask(0x33, 0x00, 0x08); /* no DDR ? */ | 530 | svga_wcrt_mask(0x33, 0x00, 0x08); /* no DDR ? */ |
519 | svga_wcrt_mask(0x43, 0x00, 0x01); /* no DDR ? */ | 531 | svga_wcrt_mask(0x43, 0x00, 0x01); /* no DDR ? */ |
520 | 532 | ||
521 | svga_wcrt_mask(0x5D, 0x00, 0x28); // Clear strange HSlen bits | 533 | svga_wcrt_mask(0x5D, 0x00, 0x28); /* Clear strange HSlen bits */ |
522 | 534 | ||
523 | /* svga_wcrt_mask(0x58, 0x03, 0x03); */ | 535 | /* svga_wcrt_mask(0x58, 0x03, 0x03); */ |
524 | 536 | ||
@@ -530,10 +542,14 @@ static int s3fb_set_par(struct fb_info *info) | |||
530 | pr_debug("fb%d: offset register : %d\n", info->node, offset_value); | 542 | pr_debug("fb%d: offset register : %d\n", info->node, offset_value); |
531 | svga_wcrt_multi(s3_offset_regs, offset_value); | 543 | svga_wcrt_multi(s3_offset_regs, offset_value); |
532 | 544 | ||
533 | vga_wcrt(NULL, 0x54, 0x18); /* M parameter */ | 545 | if (par->chip != CHIP_360_TRIO3D_1X && |
534 | vga_wcrt(NULL, 0x60, 0xff); /* N parameter */ | 546 | par->chip != CHIP_362_TRIO3D_2X && |
535 | vga_wcrt(NULL, 0x61, 0xff); /* L parameter */ | 547 | par->chip != CHIP_368_TRIO3D_2X) { |
536 | vga_wcrt(NULL, 0x62, 0xff); /* L parameter */ | 548 | vga_wcrt(NULL, 0x54, 0x18); /* M parameter */ |
549 | vga_wcrt(NULL, 0x60, 0xff); /* N parameter */ | ||
550 | vga_wcrt(NULL, 0x61, 0xff); /* L parameter */ | ||
551 | vga_wcrt(NULL, 0x62, 0xff); /* L parameter */ | ||
552 | } | ||
537 | 553 | ||
538 | vga_wcrt(NULL, 0x3A, 0x35); | 554 | vga_wcrt(NULL, 0x3A, 0x35); |
539 | svga_wattr(0x33, 0x00); | 555 | svga_wattr(0x33, 0x00); |
@@ -570,6 +586,16 @@ static int s3fb_set_par(struct fb_info *info) | |||
570 | vga_wcrt(NULL, 0x66, 0x90); | 586 | vga_wcrt(NULL, 0x66, 0x90); |
571 | } | 587 | } |
572 | 588 | ||
589 | if (par->chip == CHIP_360_TRIO3D_1X || | ||
590 | par->chip == CHIP_362_TRIO3D_2X || | ||
591 | par->chip == CHIP_368_TRIO3D_2X) { | ||
592 | dbytes = info->var.xres * ((bpp+7)/8); | ||
593 | vga_wcrt(NULL, 0x91, (dbytes + 7) / 8); | ||
594 | vga_wcrt(NULL, 0x90, (((dbytes + 7) / 8) >> 8) | 0x80); | ||
595 | |||
596 | vga_wcrt(NULL, 0x66, 0x81); | ||
597 | } | ||
598 | |||
573 | svga_wcrt_mask(0x31, 0x00, 0x40); | 599 | svga_wcrt_mask(0x31, 0x00, 0x40); |
574 | multiplex = 0; | 600 | multiplex = 0; |
575 | hmul = 1; | 601 | hmul = 1; |
@@ -615,11 +641,13 @@ static int s3fb_set_par(struct fb_info *info) | |||
615 | break; | 641 | break; |
616 | case 3: | 642 | case 3: |
617 | pr_debug("fb%d: 8 bit pseudocolor\n", info->node); | 643 | pr_debug("fb%d: 8 bit pseudocolor\n", info->node); |
618 | if (info->var.pixclock > 20000) { | 644 | svga_wcrt_mask(0x50, 0x00, 0x30); |
619 | svga_wcrt_mask(0x50, 0x00, 0x30); | 645 | if (info->var.pixclock > 20000 || |
646 | par->chip == CHIP_360_TRIO3D_1X || | ||
647 | par->chip == CHIP_362_TRIO3D_2X || | ||
648 | par->chip == CHIP_368_TRIO3D_2X) | ||
620 | svga_wcrt_mask(0x67, 0x00, 0xF0); | 649 | svga_wcrt_mask(0x67, 0x00, 0xF0); |
621 | } else { | 650 | else { |
622 | svga_wcrt_mask(0x50, 0x00, 0x30); | ||
623 | svga_wcrt_mask(0x67, 0x10, 0xF0); | 651 | svga_wcrt_mask(0x67, 0x10, 0xF0); |
624 | multiplex = 1; | 652 | multiplex = 1; |
625 | } | 653 | } |
@@ -634,7 +662,10 @@ static int s3fb_set_par(struct fb_info *info) | |||
634 | } else { | 662 | } else { |
635 | svga_wcrt_mask(0x50, 0x10, 0x30); | 663 | svga_wcrt_mask(0x50, 0x10, 0x30); |
636 | svga_wcrt_mask(0x67, 0x30, 0xF0); | 664 | svga_wcrt_mask(0x67, 0x30, 0xF0); |
637 | hmul = 2; | 665 | if (par->chip != CHIP_360_TRIO3D_1X && |
666 | par->chip != CHIP_362_TRIO3D_2X && | ||
667 | par->chip != CHIP_368_TRIO3D_2X) | ||
668 | hmul = 2; | ||
638 | } | 669 | } |
639 | break; | 670 | break; |
640 | case 5: | 671 | case 5: |
@@ -647,7 +678,10 @@ static int s3fb_set_par(struct fb_info *info) | |||
647 | } else { | 678 | } else { |
648 | svga_wcrt_mask(0x50, 0x10, 0x30); | 679 | svga_wcrt_mask(0x50, 0x10, 0x30); |
649 | svga_wcrt_mask(0x67, 0x50, 0xF0); | 680 | svga_wcrt_mask(0x67, 0x50, 0xF0); |
650 | hmul = 2; | 681 | if (par->chip != CHIP_360_TRIO3D_1X && |
682 | par->chip != CHIP_362_TRIO3D_2X && | ||
683 | par->chip != CHIP_368_TRIO3D_2X) | ||
684 | hmul = 2; | ||
651 | } | 685 | } |
652 | break; | 686 | break; |
653 | case 6: | 687 | case 6: |
@@ -866,6 +900,17 @@ static int __devinit s3_identification(int chip) | |||
866 | return CHIP_385_VIRGE_GX; | 900 | return CHIP_385_VIRGE_GX; |
867 | } | 901 | } |
868 | 902 | ||
903 | if (chip == CHIP_36X_TRIO3D_1X_2X) { | ||
904 | switch (vga_rcrt(NULL, 0x2f)) { | ||
905 | case 0x00: | ||
906 | return CHIP_360_TRIO3D_1X; | ||
907 | case 0x01: | ||
908 | return CHIP_362_TRIO3D_2X; | ||
909 | case 0x02: | ||
910 | return CHIP_368_TRIO3D_2X; | ||
911 | } | ||
912 | } | ||
913 | |||
869 | return CHIP_UNKNOWN; | 914 | return CHIP_UNKNOWN; |
870 | } | 915 | } |
871 | 916 | ||
@@ -930,17 +975,32 @@ static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_i | |||
930 | vga_wcrt(NULL, 0x38, 0x48); | 975 | vga_wcrt(NULL, 0x38, 0x48); |
931 | vga_wcrt(NULL, 0x39, 0xA5); | 976 | vga_wcrt(NULL, 0x39, 0xA5); |
932 | 977 | ||
933 | /* Find how many physical memory there is on card */ | 978 | /* Identify chip type */ |
934 | /* 0x36 register is accessible even if other registers are locked */ | ||
935 | regval = vga_rcrt(NULL, 0x36); | ||
936 | info->screen_size = s3_memsizes[regval >> 5] << 10; | ||
937 | info->fix.smem_len = info->screen_size; | ||
938 | |||
939 | par->chip = id->driver_data & CHIP_MASK; | 979 | par->chip = id->driver_data & CHIP_MASK; |
940 | par->rev = vga_rcrt(NULL, 0x2f); | 980 | par->rev = vga_rcrt(NULL, 0x2f); |
941 | if (par->chip & CHIP_UNDECIDED_FLAG) | 981 | if (par->chip & CHIP_UNDECIDED_FLAG) |
942 | par->chip = s3_identification(par->chip); | 982 | par->chip = s3_identification(par->chip); |
943 | 983 | ||
984 | /* Find how many physical memory there is on card */ | ||
985 | /* 0x36 register is accessible even if other registers are locked */ | ||
986 | regval = vga_rcrt(NULL, 0x36); | ||
987 | if (par->chip == CHIP_360_TRIO3D_1X || | ||
988 | par->chip == CHIP_362_TRIO3D_2X || | ||
989 | par->chip == CHIP_368_TRIO3D_2X) { | ||
990 | switch ((regval & 0xE0) >> 5) { | ||
991 | case 0: /* 8MB -- only 4MB usable for display */ | ||
992 | case 1: /* 4MB with 32-bit bus */ | ||
993 | case 2: /* 4MB */ | ||
994 | info->screen_size = 4 << 20; | ||
995 | break; | ||
996 | case 6: /* 2MB */ | ||
997 | info->screen_size = 2 << 20; | ||
998 | break; | ||
999 | } | ||
1000 | } else | ||
1001 | info->screen_size = s3_memsizes[regval >> 5] << 10; | ||
1002 | info->fix.smem_len = info->screen_size; | ||
1003 | |||
944 | /* Find MCLK frequency */ | 1004 | /* Find MCLK frequency */ |
945 | regval = vga_rseq(NULL, 0x10); | 1005 | regval = vga_rseq(NULL, 0x10); |
946 | par->mclk_freq = ((vga_rseq(NULL, 0x11) + 2) * 14318) / ((regval & 0x1F) + 2); | 1006 | par->mclk_freq = ((vga_rseq(NULL, 0x11) + 2) * 14318) / ((regval & 0x1F) + 2); |
@@ -1131,6 +1191,7 @@ static struct pci_device_id s3_devices[] __devinitdata = { | |||
1131 | {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A10), .driver_data = CHIP_356_VIRGE_GX2}, | 1191 | {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A10), .driver_data = CHIP_356_VIRGE_GX2}, |
1132 | {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A11), .driver_data = CHIP_357_VIRGE_GX2P}, | 1192 | {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A11), .driver_data = CHIP_357_VIRGE_GX2P}, |
1133 | {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A12), .driver_data = CHIP_359_VIRGE_GX2P}, | 1193 | {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A12), .driver_data = CHIP_359_VIRGE_GX2P}, |
1194 | {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A13), .driver_data = CHIP_36X_TRIO3D_1X_2X}, | ||
1134 | 1195 | ||
1135 | {0, 0, 0, 0, 0, 0, 0} | 1196 | {0, 0, 0, 0, 0, 0, 0} |
1136 | }; | 1197 | }; |