提交 9966c4fe 编写于 作者: O Ondrej Zary 提交者: Linus Torvalds

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: NOndrej Zary <linux@rainbow-software.org>
Acked-by: NOndrej Zajicek <santiago@crfreenet.org>
Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
上级 48baa18b
...@@ -71,7 +71,8 @@ static const char * const s3_names[] = {"S3 Unknown", "S3 Trio32", "S3 Trio64", ...@@ -71,7 +71,8 @@ static const char * const s3_names[] = {"S3 Unknown", "S3 Trio32", "S3 Trio64",
"S3 Trio64UV+", "S3 Trio64V2/DX", "S3 Trio64V2/GX", "S3 Trio64UV+", "S3 Trio64V2/DX", "S3 Trio64V2/GX",
"S3 Plato/PX", "S3 Aurora64VP", "S3 Virge", "S3 Plato/PX", "S3 Aurora64VP", "S3 Virge",
"S3 Virge/VX", "S3 Virge/DX", "S3 Virge/GX", "S3 Virge/VX", "S3 Virge/DX", "S3 Virge/GX",
"S3 Virge/GX2", "S3 Virge/GX2P", "S3 Virge/GX2P"}; "S3 Virge/GX2", "S3 Virge/GX2P", "S3 Virge/GX2P",
"S3 Trio3D/1X", "S3 Trio3D/2X", "S3 Trio3D/2X"};
#define CHIP_UNKNOWN 0x00 #define CHIP_UNKNOWN 0x00
#define CHIP_732_TRIO32 0x01 #define CHIP_732_TRIO32 0x01
...@@ -89,10 +90,14 @@ static const char * const s3_names[] = {"S3 Unknown", "S3 Trio32", "S3 Trio64", ...@@ -89,10 +90,14 @@ static const char * const s3_names[] = {"S3 Unknown", "S3 Trio32", "S3 Trio64",
#define CHIP_356_VIRGE_GX2 0x0D #define CHIP_356_VIRGE_GX2 0x0D
#define CHIP_357_VIRGE_GX2P 0x0E #define CHIP_357_VIRGE_GX2P 0x0E
#define CHIP_359_VIRGE_GX2P 0x0F #define CHIP_359_VIRGE_GX2P 0x0F
#define CHIP_360_TRIO3D_1X 0x10
#define CHIP_362_TRIO3D_2X 0x11
#define CHIP_368_TRIO3D_2X 0x12
#define CHIP_XXX_TRIO 0x80 #define CHIP_XXX_TRIO 0x80
#define CHIP_XXX_TRIO64V2_DXGX 0x81 #define CHIP_XXX_TRIO64V2_DXGX 0x81
#define CHIP_XXX_VIRGE_DXGX 0x82 #define CHIP_XXX_VIRGE_DXGX 0x82
#define CHIP_36X_TRIO3D_1X_2X 0x83
#define CHIP_UNDECIDED_FLAG 0x80 #define CHIP_UNDECIDED_FLAG 0x80
#define CHIP_MASK 0xFF #define CHIP_MASK 0xFF
...@@ -324,6 +329,7 @@ static void s3fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) ...@@ -324,6 +329,7 @@ static void s3fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
static void s3_set_pixclock(struct fb_info *info, u32 pixclock) static void s3_set_pixclock(struct fb_info *info, u32 pixclock)
{ {
struct s3fb_info *par = info->par;
u16 m, n, r; u16 m, n, r;
u8 regval; u8 regval;
int rv; int rv;
...@@ -339,7 +345,13 @@ static void s3_set_pixclock(struct fb_info *info, u32 pixclock) ...@@ -339,7 +345,13 @@ static void s3_set_pixclock(struct fb_info *info, u32 pixclock)
vga_w(NULL, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD); vga_w(NULL, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD);
/* Set S3 clock registers */ /* Set S3 clock registers */
vga_wseq(NULL, 0x12, ((n - 2) | (r << 5))); if (par->chip == CHIP_360_TRIO3D_1X ||
par->chip == CHIP_362_TRIO3D_2X ||
par->chip == CHIP_368_TRIO3D_2X) {
vga_wseq(NULL, 0x12, (n - 2) | ((r & 3) << 6)); /* n and two bits of r */
vga_wseq(NULL, 0x29, r >> 2); /* remaining highest bit of r */
} else
vga_wseq(NULL, 0x12, (n - 2) | (r << 5));
vga_wseq(NULL, 0x13, m - 2); vga_wseq(NULL, 0x13, m - 2);
udelay(1000); udelay(1000);
...@@ -456,7 +468,7 @@ static int s3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) ...@@ -456,7 +468,7 @@ static int s3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
static int s3fb_set_par(struct fb_info *info) static int s3fb_set_par(struct fb_info *info)
{ {
struct s3fb_info *par = info->par; struct s3fb_info *par = info->par;
u32 value, mode, hmul, offset_value, screen_size, multiplex; u32 value, mode, hmul, offset_value, screen_size, multiplex, dbytes;
u32 bpp = info->var.bits_per_pixel; u32 bpp = info->var.bits_per_pixel;
if (bpp != 0) { if (bpp != 0) {
...@@ -518,7 +530,7 @@ static int s3fb_set_par(struct fb_info *info) ...@@ -518,7 +530,7 @@ static int s3fb_set_par(struct fb_info *info)
svga_wcrt_mask(0x33, 0x00, 0x08); /* no DDR ? */ svga_wcrt_mask(0x33, 0x00, 0x08); /* no DDR ? */
svga_wcrt_mask(0x43, 0x00, 0x01); /* no DDR ? */ svga_wcrt_mask(0x43, 0x00, 0x01); /* no DDR ? */
svga_wcrt_mask(0x5D, 0x00, 0x28); // Clear strange HSlen bits svga_wcrt_mask(0x5D, 0x00, 0x28); /* Clear strange HSlen bits */
/* svga_wcrt_mask(0x58, 0x03, 0x03); */ /* svga_wcrt_mask(0x58, 0x03, 0x03); */
...@@ -530,10 +542,14 @@ static int s3fb_set_par(struct fb_info *info) ...@@ -530,10 +542,14 @@ static int s3fb_set_par(struct fb_info *info)
pr_debug("fb%d: offset register : %d\n", info->node, offset_value); pr_debug("fb%d: offset register : %d\n", info->node, offset_value);
svga_wcrt_multi(s3_offset_regs, offset_value); svga_wcrt_multi(s3_offset_regs, offset_value);
vga_wcrt(NULL, 0x54, 0x18); /* M parameter */ if (par->chip != CHIP_360_TRIO3D_1X &&
vga_wcrt(NULL, 0x60, 0xff); /* N parameter */ par->chip != CHIP_362_TRIO3D_2X &&
vga_wcrt(NULL, 0x61, 0xff); /* L parameter */ par->chip != CHIP_368_TRIO3D_2X) {
vga_wcrt(NULL, 0x62, 0xff); /* L parameter */ vga_wcrt(NULL, 0x54, 0x18); /* M parameter */
vga_wcrt(NULL, 0x60, 0xff); /* N parameter */
vga_wcrt(NULL, 0x61, 0xff); /* L parameter */
vga_wcrt(NULL, 0x62, 0xff); /* L parameter */
}
vga_wcrt(NULL, 0x3A, 0x35); vga_wcrt(NULL, 0x3A, 0x35);
svga_wattr(0x33, 0x00); svga_wattr(0x33, 0x00);
...@@ -570,6 +586,16 @@ static int s3fb_set_par(struct fb_info *info) ...@@ -570,6 +586,16 @@ static int s3fb_set_par(struct fb_info *info)
vga_wcrt(NULL, 0x66, 0x90); vga_wcrt(NULL, 0x66, 0x90);
} }
if (par->chip == CHIP_360_TRIO3D_1X ||
par->chip == CHIP_362_TRIO3D_2X ||
par->chip == CHIP_368_TRIO3D_2X) {
dbytes = info->var.xres * ((bpp+7)/8);
vga_wcrt(NULL, 0x91, (dbytes + 7) / 8);
vga_wcrt(NULL, 0x90, (((dbytes + 7) / 8) >> 8) | 0x80);
vga_wcrt(NULL, 0x66, 0x81);
}
svga_wcrt_mask(0x31, 0x00, 0x40); svga_wcrt_mask(0x31, 0x00, 0x40);
multiplex = 0; multiplex = 0;
hmul = 1; hmul = 1;
...@@ -615,11 +641,13 @@ static int s3fb_set_par(struct fb_info *info) ...@@ -615,11 +641,13 @@ static int s3fb_set_par(struct fb_info *info)
break; break;
case 3: case 3:
pr_debug("fb%d: 8 bit pseudocolor\n", info->node); pr_debug("fb%d: 8 bit pseudocolor\n", info->node);
if (info->var.pixclock > 20000) { svga_wcrt_mask(0x50, 0x00, 0x30);
svga_wcrt_mask(0x50, 0x00, 0x30); if (info->var.pixclock > 20000 ||
par->chip == CHIP_360_TRIO3D_1X ||
par->chip == CHIP_362_TRIO3D_2X ||
par->chip == CHIP_368_TRIO3D_2X)
svga_wcrt_mask(0x67, 0x00, 0xF0); svga_wcrt_mask(0x67, 0x00, 0xF0);
} else { else {
svga_wcrt_mask(0x50, 0x00, 0x30);
svga_wcrt_mask(0x67, 0x10, 0xF0); svga_wcrt_mask(0x67, 0x10, 0xF0);
multiplex = 1; multiplex = 1;
} }
...@@ -634,7 +662,10 @@ static int s3fb_set_par(struct fb_info *info) ...@@ -634,7 +662,10 @@ static int s3fb_set_par(struct fb_info *info)
} else { } else {
svga_wcrt_mask(0x50, 0x10, 0x30); svga_wcrt_mask(0x50, 0x10, 0x30);
svga_wcrt_mask(0x67, 0x30, 0xF0); svga_wcrt_mask(0x67, 0x30, 0xF0);
hmul = 2; if (par->chip != CHIP_360_TRIO3D_1X &&
par->chip != CHIP_362_TRIO3D_2X &&
par->chip != CHIP_368_TRIO3D_2X)
hmul = 2;
} }
break; break;
case 5: case 5:
...@@ -647,7 +678,10 @@ static int s3fb_set_par(struct fb_info *info) ...@@ -647,7 +678,10 @@ static int s3fb_set_par(struct fb_info *info)
} else { } else {
svga_wcrt_mask(0x50, 0x10, 0x30); svga_wcrt_mask(0x50, 0x10, 0x30);
svga_wcrt_mask(0x67, 0x50, 0xF0); svga_wcrt_mask(0x67, 0x50, 0xF0);
hmul = 2; if (par->chip != CHIP_360_TRIO3D_1X &&
par->chip != CHIP_362_TRIO3D_2X &&
par->chip != CHIP_368_TRIO3D_2X)
hmul = 2;
} }
break; break;
case 6: case 6:
...@@ -866,6 +900,17 @@ static int __devinit s3_identification(int chip) ...@@ -866,6 +900,17 @@ static int __devinit s3_identification(int chip)
return CHIP_385_VIRGE_GX; return CHIP_385_VIRGE_GX;
} }
if (chip == CHIP_36X_TRIO3D_1X_2X) {
switch (vga_rcrt(NULL, 0x2f)) {
case 0x00:
return CHIP_360_TRIO3D_1X;
case 0x01:
return CHIP_362_TRIO3D_2X;
case 0x02:
return CHIP_368_TRIO3D_2X;
}
}
return CHIP_UNKNOWN; return CHIP_UNKNOWN;
} }
...@@ -930,17 +975,32 @@ static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_i ...@@ -930,17 +975,32 @@ static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_i
vga_wcrt(NULL, 0x38, 0x48); vga_wcrt(NULL, 0x38, 0x48);
vga_wcrt(NULL, 0x39, 0xA5); vga_wcrt(NULL, 0x39, 0xA5);
/* Find how many physical memory there is on card */ /* Identify chip type */
/* 0x36 register is accessible even if other registers are locked */
regval = vga_rcrt(NULL, 0x36);
info->screen_size = s3_memsizes[regval >> 5] << 10;
info->fix.smem_len = info->screen_size;
par->chip = id->driver_data & CHIP_MASK; par->chip = id->driver_data & CHIP_MASK;
par->rev = vga_rcrt(NULL, 0x2f); par->rev = vga_rcrt(NULL, 0x2f);
if (par->chip & CHIP_UNDECIDED_FLAG) if (par->chip & CHIP_UNDECIDED_FLAG)
par->chip = s3_identification(par->chip); par->chip = s3_identification(par->chip);
/* Find how many physical memory there is on card */
/* 0x36 register is accessible even if other registers are locked */
regval = vga_rcrt(NULL, 0x36);
if (par->chip == CHIP_360_TRIO3D_1X ||
par->chip == CHIP_362_TRIO3D_2X ||
par->chip == CHIP_368_TRIO3D_2X) {
switch ((regval & 0xE0) >> 5) {
case 0: /* 8MB -- only 4MB usable for display */
case 1: /* 4MB with 32-bit bus */
case 2: /* 4MB */
info->screen_size = 4 << 20;
break;
case 6: /* 2MB */
info->screen_size = 2 << 20;
break;
}
} else
info->screen_size = s3_memsizes[regval >> 5] << 10;
info->fix.smem_len = info->screen_size;
/* Find MCLK frequency */ /* Find MCLK frequency */
regval = vga_rseq(NULL, 0x10); regval = vga_rseq(NULL, 0x10);
par->mclk_freq = ((vga_rseq(NULL, 0x11) + 2) * 14318) / ((regval & 0x1F) + 2); 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,6 +1191,7 @@ static struct pci_device_id s3_devices[] __devinitdata = {
{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A10), .driver_data = CHIP_356_VIRGE_GX2}, {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A10), .driver_data = CHIP_356_VIRGE_GX2},
{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A11), .driver_data = CHIP_357_VIRGE_GX2P}, {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A11), .driver_data = CHIP_357_VIRGE_GX2P},
{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A12), .driver_data = CHIP_359_VIRGE_GX2P}, {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A12), .driver_data = CHIP_359_VIRGE_GX2P},
{PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A13), .driver_data = CHIP_36X_TRIO3D_1X_2X},
{0, 0, 0, 0, 0, 0, 0} {0, 0, 0, 0, 0, 0, 0}
}; };
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册