diff options
| author | Ondrej Zary <linux@rainbow-software.org> | 2010-05-26 17:42:27 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-27 12:12:42 -0400 |
| commit | 9966c4fea578bcf356c35cdf184cdacde495bc2c (patch) | |
| tree | a8e71bcc6c753403b589bf3240468fa05f674020 /drivers | |
| parent | 48baa18b250d5e36ed9f9bb04cdf812d74da08ca (diff) | |
add support for S3 Trio3D/1X/2X
Add support for S3 Trio3D/1X (86C360) and S3 Trio3D/2X (86C362 and 86C368)
cards to s3fb driver. Tested with 86C362 AGP and 86C368 PCI&AGP.
[akpm@linux-foundation.org: coding-style fixes]
Signed-off-by: Ondrej Zary <linux@rainbow-software.org>
Acked-by: Ondrej Zajicek <santiago@crfreenet.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers')
| -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 | }; |
