18 #include <linux/module.h>
21 #include <linux/pci.h>
22 #include <linux/slab.h>
87 static inline int is_oldclock(
int id)
94 static inline int is_oldprotect(
int id)
96 return is_oldclock(
id) ||
102 static inline int is_blade(
int id)
114 static inline int is_xp(
int id)
121 static inline int is3Dchip(
int id)
123 return is_blade(
id) || is_xp(
id) ||
129 static inline int iscyber(
int id)
181 #define point(x, y) ((y) << 16 | (x))
185 int v1 = (pitch >> 3) << 20;
186 int tmp = bpp == 24 ? 2 : (bpp >> 4);
187 int v2 = v1 | (tmp << 29);
189 writemmr(par, 0x21C0, v2);
190 writemmr(par, 0x21C4, v2);
191 writemmr(par, 0x21B8, v2);
192 writemmr(par, 0x21BC, v2);
193 writemmr(par, 0x21D0, v1);
194 writemmr(par, 0x21D4, v1);
195 writemmr(par, 0x21C8, v1);
196 writemmr(par, 0x21CC, v1);
197 writemmr(par, 0x216C, 0);
202 while (readmmr(par,
STATUS) & 0xFA800000)
209 writemmr(par,
COLOR, c);
211 writemmr(par,
CMD, 0x20000000 | 1 << 19 | 1 << 4 | 2 << 2);
214 writemmr(par,
DST2,
point(x + w - 1, y + h - 1));
220 unsigned size = ((w + 31) >> 5) *
h;
222 writemmr(par,
COLOR, c);
224 writemmr(par,
CMD, 0xa0000000 | 3 << 19);
227 writemmr(par,
DST2,
point(x + w - 1, y + h - 1));
241 if ((y1 > y2) || ((y1 == y2) && (x1 > x2)))
245 writemmr(par,
CMD, 0xE0000000 | 1 << 19 | 1 << 4 | 1 << 2 | direction);
247 writemmr(par,
SRC1, direction ? s2 : s1);
248 writemmr(par,
SRC2, direction ? s1 : s2);
249 writemmr(par,
DST1, direction ? d2 : d1);
250 writemmr(par,
DST2, direction ? d1 : d2);
259 unsigned char x = bpp == 24 ? 3 : (bpp >> 4);
260 int v1 = pitch << (bpp == 24 ? 20 : (18 +
x));
262 switch (pitch << (
bpp >> 3)) {
278 t_outb(par, x, 0x2125);
282 writemmr(par, 0x2154,
v1);
283 writemmr(par, 0x2150,
v1);
284 t_outb(par, 3, 0x2126);
292 while (t_inb(par,
STATUS) & 0x80) {
294 if (count == 10000000) {
300 t_outb(par, 0x00,
STATUS);
311 writemmr(par, 0x2127,
ROP_P);
312 writemmr(par, 0x2158, c);
313 writemmr(par,
DRAWFL, 0x4000);
316 t_outb(par, 0x01,
OLDCMD);
323 u32 x1_tmp, x2_tmp, y1_tmp, y2_tmp;
324 int direction = 0x0004;
326 if ((x1 < x2) && (y1 == y2)) {
344 writemmr(par,
DRAWFL, direction);
345 t_outb(par,
ROP_S, 0x2127);
349 t_outb(par, 0x01,
OLDCMD);
357 int tmp = bpp == 24 ? 2: (bpp >> 4);
359 writemmr(par, 0x2120, 0xF0000000);
360 writemmr(par, 0x2120, 0x40000000 | tmp);
361 writemmr(par, 0x2120, 0x80000000);
362 writemmr(par, 0x2144, 0x00000000);
363 writemmr(par, 0x2148, 0x00000000);
364 writemmr(par, 0x2150, 0x00000000);
365 writemmr(par, 0x2154, 0x00000000);
366 writemmr(par, 0x2120, 0x60000000 | (pitch << 16) | pitch);
367 writemmr(par, 0x216C, 0x00000000);
368 writemmr(par, 0x2170, 0x00000000);
369 writemmr(par, 0x217C, 0x00000000);
370 writemmr(par, 0x2120, 0x10000000);
371 writemmr(par, 0x2130, (2047 << 16) | 2047);
376 while (readmmr(par, 0x2164) & 0xF0000000)
383 writemmr(par, 0x2120, 0x80000000);
384 writemmr(par, 0x2120, 0x90000000 |
ROP_S);
386 writemmr(par, 0x2144, c);
389 writemmr(par,
DST2,
point(x + w - 1, y + h - 1));
391 writemmr(par, 0x2124, 0x80000000 | 3 << 22 | 1 << 10 | 1 << 9);
399 u32 s2 =
point(x1 + w - 1, y1 + h - 1);
401 u32 d2 =
point(x2 + w - 1, y2 + h - 1);
403 if ((y1 > y2) || ((y1 == y2) && (x1 > x2)))
406 writemmr(par, 0x2120, 0x80000000);
407 writemmr(par, 0x2120, 0x90000000 |
ROP_S);
409 writemmr(par,
SRC1, direction ? s2 : s1);
410 writemmr(par,
SRC2, direction ? s1 : s2);
411 writemmr(par,
DST1, direction ? d2 : d1);
412 writemmr(par,
DST2, direction ? d1 : d2);
413 writemmr(par, 0x2124,
414 0x80000000 | 1 << 22 | 1 << 10 | 1 << 7 | direction);
421 static void tgui_init_accel(
struct tridentfb_par *par,
int pitch,
int bpp)
423 unsigned char x = bpp == 24 ? 3 : (bpp >> 4);
426 writemmr(par, 0x2148, 0);
427 writemmr(par, 0x214C,
point(4095, 2047));
429 switch ((pitch * bpp) / 8) {
451 t_outb(par,
ROP_P, 0x2127);
453 writemmr(par,
DRAWFL, 0x4020);
463 u16 x1_tmp, x2_tmp, y1_tmp, y2_tmp;
465 if ((x1 < x2) && (y1 == y2)) {
483 writemmr(par,
DRAWFL, 0x4 | flags);
484 t_outb(par,
ROP_S, 0x2127);
494 static void tridentfb_fillrect(
struct fb_info *
info,
504 if (info->
var.bits_per_pixel == 8) {
516 static void tridentfb_imageblit(
struct fb_info *info,
526 if (info->
var.bits_per_pixel == 8) {
532 bgcol |= bgcol << 16;
546 static void tridentfb_copyarea(
struct fb_info *info,
560 static int tridentfb_sync(
struct fb_info *info)
575 return vga_mm_rcrt(par->
io_virt, reg);
581 vga_mm_wcrt(par->
io_virt, reg, val);
584 static inline unsigned char read3CE(
struct tridentfb_par *par,
587 return vga_mm_rgfx(par->
io_virt, reg);
594 vga_mm_wattr(par->
io_virt, reg, val);
600 vga_mm_wgfx(par->
io_virt, reg, val);
610 if (!is_oldprotect(par->
chip_id))
615 outb(
inb(0x3D5) | 0x01, 0x3D5);
621 vga_mm_rseq(par->
io_virt, 0x0B);
625 if (!is_oldprotect(par->
chip_id))
629 t_outb(par,
PCIReg, 0x3D4);
630 t_outb(par, t_inb(par, 0x3D5) & ~0x01, 0x3D5);
668 output(
"%dx%d flat panel found\n", x, y);
677 (read3X4(par,
AddColReg) & 0xCF) | ((width & 0x300) >> 4));
699 static void set_screen_start(
struct tridentfb_par *par,
int base)
706 tmp = read3X4(par,
CRTHiOrd) & 0xF8;
707 write3X4(par,
CRTHiOrd, tmp | ((base & 0xE0000) >> 17));
714 unsigned long fi,
d, di;
715 unsigned char best_m = 0, best_n = 0, best_k = 0;
716 unsigned char hi,
lo;
717 unsigned char shift = !is_oldclock(par->
chip_id) ? 2 : 1;
720 for (k = shift; k >= 0; k--)
721 for (m = 1; m < 32; m++) {
722 n = ((m + 2) << shift) - 8;
723 for (n = (n < 0 ? 0 : n); n < 122; n++) {
724 fi = ((14318
l * (n + 8)) / (m + 2)) >>
k;
726 if (di < d || (di == d && k == best_k)) {
737 if (is_oldclock(par->
chip_id)) {
738 lo = best_n | (best_m << 7);
739 hi = (best_m >> 1) | (best_k << 4);
742 hi = best_m | (best_k << 6);
749 t_outb(par, lo, 0x43C8);
750 t_outb(par, hi, 0x43C9);
752 debug(
"VCLK = %X %X\n", hi, lo);
756 static void set_number_of_lines(
struct tridentfb_par *par,
int lines)
761 else if (lines > 768)
763 else if (lines > 600)
765 else if (lines > 480)
778 if (crt || !iscyber(par->
chip_id))
780 return (read3CE(par,
FPConfig) & 0x10) ? 1 : 0;
786 unsigned char tmp, tmp2;
798 tmp = read3X4(par, SPR) & 0x0F;
830 tmp2 = vga_mm_rseq(par->
io_virt, 0xC1);
860 output(
"framebuffer size = %d Kb\n", k / Kb);
877 if (bpp != 8 && bpp != 16 && bpp != 32)
900 if (line_length <= 512)
902 else if (line_length <= 1024)
904 else if (line_length <= 2048)
906 else if (line_length <= 4096)
908 else if (line_length <= 8192)
931 var->
red.offset = 11;
932 var->
green.offset = 5;
933 var->
blue.offset = 0;
935 var->
green.length = 6;
936 var->
blue.length = 5;
939 var->
red.offset = 16;
940 var->
green.offset = 8;
941 var->
blue.offset = 0;
943 var->
green.length = 8;
944 var->
blue.length = 8;
955 ramdac = (bpp >= 16) ? 45000 : 90000;
991 * info->
var.bits_per_pixel / 32;
992 set_screen_start(par, offset);
1002 static inline void shadowmode_off(
struct tridentfb_par *par)
1008 static int tridentfb_set_par(
struct fb_info *info)
1011 u32 htotal, hdispend, hsyncstart, hsyncend, hblankstart, hblankend;
1012 u32 vtotal, vdispend, vsyncstart, vsyncend, vblankstart, vblankend;
1019 hdispend = var->
xres / 8 - 1;
1024 hblankstart = hdispend + 1;
1025 hblankend = htotal + 3;
1027 vdispend = var->
yres - 1;
1031 vblankstart = vdispend + 1;
1065 screen_stretch(par);
1085 (hsyncend & 0x1F) | ((hblankend & 0x20) << 2));
1091 if (vtotal & 0x100) tmp |= 0x01;
1092 if (vdispend & 0x100) tmp |= 0x02;
1093 if (vsyncstart & 0x100) tmp |= 0x04;
1094 if (vblankstart & 0x100) tmp |= 0x08;
1096 if (vtotal & 0x200) tmp |= 0x20;
1097 if (vdispend & 0x200) tmp |= 0x40;
1098 if (vsyncstart & 0x200) tmp |= 0x80;
1101 tmp = read3X4(par,
CRTHiOrd) & 0x07;
1103 if (vtotal & 0x400) tmp |= 0x80;
1104 if (vblankstart & 0x400) tmp |= 0x40;
1105 if (vsyncstart & 0x400) tmp |= 0x20;
1106 if (vdispend & 0x400) tmp |= 0x10;
1109 tmp = (htotal >> 8) & 0x01;
1110 tmp |= (hdispend >> 7) & 0x02;
1111 tmp |= (hsyncstart >> 5) & 0x08;
1112 tmp |= (hblankstart >> 4) & 0x10;
1116 if (vblankstart & 0x200) tmp |= 0x20;
1155 if (!is_oldprotect(par->
chip_id))
1168 vga_mm_wseq(par->
io_virt, 0, 3);
1169 vga_mm_wseq(par->
io_virt, 1, 1);
1171 vga_mm_wseq(par->
io_virt, 2, 0x0F);
1172 vga_mm_wseq(par->
io_virt, 3, 0);
1173 vga_mm_wseq(par->
io_virt, 4, 0x0E);
1184 set_vclk(par, vclk);
1186 write3CE(par, 0x5, 0x40);
1187 write3CE(par, 0x6, 0x05);
1188 write3CE(par, 0x7, 0x0F);
1191 writeAttr(par, 0x10, 0x41);
1192 writeAttr(par, 0x12, 0x0F);
1193 writeAttr(par, 0x13, 0);
1196 for (tmp = 0; tmp < 0x10; tmp++)
1197 writeAttr(par, tmp, tmp);
1223 set_number_of_lines(par, info->
var.yres);
1224 info->
fix.line_length = info->
var.xres_virtual * bpp / 8;
1225 set_lwidth(par, info->
fix.line_length / 8);
1231 info->
cmap.len = (bpp == 8) ? 256 : 16;
1237 static int tridentfb_setcolreg(
unsigned regno,
unsigned red,
unsigned green,
1241 int bpp = info->
var.bits_per_pixel;
1244 if (regno >= info->
cmap.len)
1255 }
else if (regno < 16) {
1259 col = (red & 0xF800) | ((green & 0xFC00) >> 5) |
1260 ((blue & 0xF800) >> 11);
1263 }
else if (bpp == 32)
1265 ((transp & 0xFF00) << 16) |
1266 ((red & 0xFF00) << 8) |
1267 ((green & 0xFF00)) |
1268 ((blue & 0xFF00) >> 8);
1275 static int tridentfb_blank(
int blank_mode,
struct fb_info *info)
1277 unsigned char PMCont, DPMSCont;
1283 t_outb(par, 0x04, 0x83C8);
1284 PMCont = t_inb(par, 0x83C6) & 0xFC;
1286 switch (blank_mode) {
1312 t_outb(par, 4, 0x83C8);
1313 t_outb(par, PMCont, 0x83C6);
1321 static struct fb_ops tridentfb_ops = {
1323 .fb_setcolreg = tridentfb_setcolreg,
1324 .fb_pan_display = tridentfb_pan_display,
1325 .fb_blank = tridentfb_blank,
1326 .fb_check_var = tridentfb_check_var,
1327 .fb_set_par = tridentfb_set_par,
1328 .fb_fillrect = tridentfb_fillrect,
1329 .fb_copyarea = tridentfb_copyarea,
1330 .fb_imageblit = tridentfb_imageblit,
1331 .fb_sync = tridentfb_sync,
1351 default_par = info->
par;
1353 chip_id =
id->device;
1391 chip3D = is3Dchip(chip_id);
1393 if (is_xp(chip_id)) {
1399 }
else if (is_blade(chip_id)) {
1402 default_par->
fill_rect = blade_fill_rect;
1403 default_par->
copy_rect = blade_copy_rect;
1406 }
else if (chip3D) {
1409 default_par->
fill_rect = image_fill_rect;
1410 default_par->
copy_rect = image_copy_rect;
1415 default_par->
fill_rect = tgui_fill_rect;
1416 default_par->
copy_rect = tgui_copy_rect;
1427 tridentfb_fix.
mmio_len,
"tridentfb")) {
1428 debug(
"request_region failed!\n");
1437 debug(
"ioremap failed\n");
1442 enable_mmio(default_par);
1446 tridentfb_fix.
smem_len = get_memsize(default_par);
1449 tridentfb_fix.
smem_len,
"tridentfb")) {
1450 debug(
"request_mem_region failed!\n");
1451 disable_mmio(info->
par);
1460 debug(
"ioremap failed\n");
1465 default_par->
flatpanel = is_flatpanel(default_par);
1468 nativex = get_nativex(default_par);
1470 info->
fix = tridentfb_fix;
1471 info->
fbops = &tridentfb_ops;
1482 if (is_blade(chip_id) && chip_id !=
BLADE3D)
1486 if (!info->
pixmap.addr) {
1491 info->
pixmap.size = 4096;
1492 info->
pixmap.buf_align = 4;
1493 info->
pixmap.scan_align = 1;
1494 info->
pixmap.access_align = 32;
1499 info->
pixmap.scan_align = 4;
1505 info->
pixmap.scan_align = 1;
1509 mode_option,
NULL, 0,
NULL, bpp)) {
1525 output(
"fb%d: %s frame buffer device %dx%d-%dbpp\n",
1527 info->
var.yres, info->
var.bits_per_pixel);
1529 pci_set_drvdata(dev, info);
1537 disable_mmio(info->
par);
1548 struct fb_info *info = pci_get_drvdata(dev);
1556 pci_set_drvdata(dev,
NULL);
1590 static struct pci_driver tridentfb_pci_driver = {
1591 .name =
"tridentfb",
1592 .id_table = trident_devices,
1593 .probe = trident_pci_probe,
1606 if (!options || !*options)
1608 while ((opt =
strsep(&options,
",")) !=
NULL) {
1611 if (!
strncmp(opt,
"noaccel", 7))
1613 else if (!
strncmp(opt,
"fp", 2))
1615 else if (!
strncmp(opt,
"crt", 3))
1617 else if (!
strncmp(opt,
"bpp=", 4))
1619 else if (!
strncmp(opt,
"center", 6))
1621 else if (!
strncmp(opt,
"stretch", 7))
1623 else if (!
strncmp(opt,
"memsize=", 8))
1625 else if (!
strncmp(opt,
"memdiff=", 8))
1627 else if (!
strncmp(opt,
"nativex=", 8))
1636 static int __init tridentfb_init(
void)
1643 tridentfb_setup(option);
1645 return pci_register_driver(&tridentfb_pci_driver);
1648 static void __exit tridentfb_exit(
void)