|
@@ -727,7 +727,7 @@ static int s3fb_set_par(struct fb_info *info)
|
|
|
if (par->chip == CHIP_988_VIRGE_VX) {
|
|
|
vga_wcrt(par->state.vgabase, 0x50, 0x00);
|
|
|
vga_wcrt(par->state.vgabase, 0x67, 0x50);
|
|
|
-
|
|
|
+ msleep(10); /* screen remains blank sometimes without this */
|
|
|
vga_wcrt(par->state.vgabase, 0x63, (mode <= 2) ? 0x90 : 0x09);
|
|
|
vga_wcrt(par->state.vgabase, 0x66, 0x90);
|
|
|
}
|
|
@@ -901,7 +901,8 @@ static int s3fb_set_par(struct fb_info *info)
|
|
|
|
|
|
/* Set Data Transfer Position */
|
|
|
hsstart = ((info->var.xres + info->var.right_margin) * hmul) / 8;
|
|
|
- value = clamp((htotal + hsstart + 1) / 2, hsstart + 4, htotal + 1);
|
|
|
+ /* + 2 is needed for Virge/VX, does no harm on other cards */
|
|
|
+ value = clamp((htotal + hsstart + 1) / 2 + 2, hsstart + 4, htotal + 1);
|
|
|
svga_wcrt_multi(par->state.vgabase, s3_dtpc_regs, value);
|
|
|
|
|
|
memset_io(info->screen_base, 0x00, screen_size);
|
|
@@ -1216,6 +1217,31 @@ static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_i
|
|
|
info->screen_size = 2 << 20;
|
|
|
break;
|
|
|
}
|
|
|
+ } else if (par->chip == CHIP_988_VIRGE_VX) {
|
|
|
+ switch ((regval & 0x60) >> 5) {
|
|
|
+ case 0: /* 2MB */
|
|
|
+ info->screen_size = 2 << 20;
|
|
|
+ break;
|
|
|
+ case 1: /* 4MB */
|
|
|
+ info->screen_size = 4 << 20;
|
|
|
+ break;
|
|
|
+ case 2: /* 6MB */
|
|
|
+ info->screen_size = 6 << 20;
|
|
|
+ break;
|
|
|
+ case 3: /* 8MB */
|
|
|
+ info->screen_size = 8 << 20;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ /* off-screen memory */
|
|
|
+ regval = vga_rcrt(par->state.vgabase, 0x37);
|
|
|
+ switch ((regval & 0x60) >> 5) {
|
|
|
+ case 1: /* 4MB */
|
|
|
+ info->screen_size -= 4 << 20;
|
|
|
+ break;
|
|
|
+ case 2: /* 2MB */
|
|
|
+ info->screen_size -= 2 << 20;
|
|
|
+ break;
|
|
|
+ }
|
|
|
} else
|
|
|
info->screen_size = s3_memsizes[regval >> 5] << 10;
|
|
|
info->fix.smem_len = info->screen_size;
|