16 #include <linux/compiler.h>
18 #include <linux/device.h>
19 #include <linux/errno.h>
23 #include <linux/kernel.h>
25 #include <linux/module.h>
26 #include <linux/pci.h>
28 #include <linux/string.h>
36 #define TGA_BUS_PCI(dev) (dev->bus == &pci_bus_type)
38 #define TGA_BUS_PCI(dev) 0
42 #define TGA_BUS_TC(dev) (dev->bus == &tc_bus_type)
44 #define TGA_BUS_TC(dev) 0
52 static int tgafb_set_par(
struct fb_info *);
53 static void tgafb_set_pll(
struct tga_par *,
int);
54 static int tgafb_setcolreg(
unsigned,
unsigned,
unsigned,
unsigned,
56 static int tgafb_blank(
int,
struct fb_info *);
57 static void tgafb_init_fix(
struct fb_info *);
67 static const char *mode_option;
68 static const char *mode_option_pci =
"640x480@60";
69 static const char *mode_option_tc =
"1280x1024@72";
79 static struct fb_ops tgafb_ops = {
81 .fb_check_var = tgafb_check_var,
82 .fb_set_par = tgafb_set_par,
83 .fb_setcolreg = tgafb_setcolreg,
84 .fb_blank = tgafb_blank,
85 .fb_pan_display = tgafb_pan_display,
86 .fb_fillrect = tgafb_fillrect,
87 .fb_copyarea = tgafb_copyarea,
88 .fb_imageblit = tgafb_imageblit,
108 .id_table = tgafb_pci_table,
109 .probe = tgafb_pci_register,
116 return tgafb_register(&pdev->
dev);
120 tgafb_pci_unregister(
struct pci_dev *pdev)
122 tgafb_unregister(&pdev->
dev);
134 {
"DEC ",
"PMAGD-AA" },
135 {
"DEC ",
"PMAGD " },
140 static struct tc_driver tgafb_tc_driver = {
141 .id_table = tgafb_tc_table,
145 .probe = tgafb_tc_register,
153 int status = tgafb_register(dev);
160 tgafb_tc_unregister(
struct device *dev)
163 tgafb_unregister(dev);
186 var->
red.length = var->
green.length = var->
blue.length = 8;
188 var->
red.offset = 16;
189 var->
green.offset = 8;
190 var->
blue.offset = 0;
215 tgafb_set_par(
struct fb_info *info)
217 static unsigned int const deep_presets[4] = {
223 static unsigned int const rasterop_presets[4] = {
229 static unsigned int const mode_presets[4] = {
235 static unsigned int const base_addr_presets[4] = {
273 par->
pll_freq = pll_freq = 1000000000 / info->
var.pixclock;
285 TGA_WRITE_REG(par, deep_presets[tga_type] |
294 TGA_WRITE_REG(par, mode_presets[tga_type],
TGA_MODE_REG);
298 tgafb_set_pll(par, pll_freq);
324 for (i = 0; i < 256 * 3; i += 4) {
346 BT459_LOAD_ADDR(par, 0x0000);
349 for (i = 0; i < 256 * 3; i += 4) {
375 BT463_LOAD_ADDR(par, 0x0000);
378 #ifdef CONFIG_HW_CONSOLE
379 for (i = 0; i < 16; i++) {
386 for (i = 0; i < 512 * 3; i += 4) {
388 for (i = 0; i < 528 * 3; i += 4) {
408 for (i = 0; i < 16; i++) {
422 #define DIFFCHECK(X) \
425 int delta = f - (TGA_PLL_BASE_FREQ * (X)) / (r << shift); \
428 if (delta < min_diff) \
429 min_diff = delta, vm = m, va = a, vr = r; \
434 tgafb_set_pll(
struct tga_par *par,
int f)
437 int r,
a,
m,
vm = 34,
va = 1, vr = 30;
439 for (r = 0 ; r < 12 ; r++)
455 for (r = 0 ; r < 10 ; r++)
462 else if (f <= 200000) {
486 for (n = base < 7 ? 7 : base; n < base + target && n < 449; n++) {
487 m = ((n + 3) / 7) - 1;
502 for (r = 0; r < 8; r++)
504 for (r = 0; r < 8 ; r++)
506 for (r = 0; r < 7 ; r++)
522 tgafb_setcolreg(
unsigned regno,
unsigned red,
unsigned green,
unsigned blue,
542 BT459_LOAD_ADDR(par, regno);
549 u32 value = (regno << 16) | (regno << 8) | regno;
552 BT463_LOAD_ADDR(par, regno);
569 tgafb_blank(
int blank,
struct fb_info *info)
572 u32 vhcr, vvcr, vvvr;
630 u32 fgcolor, bgcolor, dx, dy,
width,
height, vxres, vyres, pixelmask;
631 unsigned long rincr, line_length, shift,
pos, is8bpp;
633 const unsigned char *
data;
637 is8bpp = info->
var.bits_per_pixel == 8;
643 vxres = info->
var.xres_virtual;
644 vyres = info->
var.yres_virtual;
645 line_length = info->
fix.line_length;
646 rincr = (
width + 7) / 8;
652 if (dx > vxres || dy > vyres)
654 if (dx +
width > vxres)
668 fgcolor |= fgcolor << 8;
669 fgcolor |= fgcolor << 16;
670 bgcolor |= bgcolor << 8;
671 bgcolor |= bgcolor << 16;
683 pos = dy * line_length;
690 shift = (
pos & 7) >> 2;
694 data = (
const unsigned char *) image->
data;
702 if (
width + shift <= 32) {
703 unsigned long bwidth;
709 pixelmask = (2ul << (
width - 1)) - 1;
714 bwidth = (
width + 7) / 8;
721 for (
j = 0;
j < bwidth; ++
j)
722 mask |= bitrev8(
data[
j]) << (j * 8);
731 }
else if (shift == 0) {
732 unsigned long pos0 =
pos;
734 unsigned long bincr = (is8bpp ? 8 : 8*4);
735 unsigned long bwidth;
745 bwidth = (
width / 8) & -4;
747 for (
j = 0;
j < bwidth;
j += 4) {
749 mask |= bitrev8(
data[
j+0]) << (0 * 8);
750 mask |= bitrev8(
data[
j+1]) << (1 * 8);
751 mask |= bitrev8(
data[
j+2]) << (2 * 8);
752 mask |= bitrev8(
data[
j+3]) << (3 * 8);
760 pixelmask = (1ul << (
width & 31)) - 1;
765 pos = pos0 + bwidth*bincr;
766 data = data0 + bwidth;
767 bwidth = ((
width & 31) + 7) / 8;
771 for (
j = 0;
j < bwidth; ++
j)
772 mask |= bitrev8(
data[
j]) << (j * 8);
781 unsigned long pos0 =
pos;
782 const unsigned char *data0 =
data;
783 unsigned long bincr = (is8bpp ? 8 : 8*4);
784 unsigned long bwidth;
791 pixelmask = 0xffff << shift;
795 bwidth = (
width / 8) & -2;
797 for (
j = 0;
j < bwidth;
j += 2) {
799 mask |= bitrev8(
data[
j+0]) << (0 * 8);
800 mask |= bitrev8(
data[
j+1]) << (1 * 8);
809 pixelmask = ((1ul << (
width & 15)) - 1) << shift;
814 pos = pos0 + bwidth*bincr;
815 data = data0 + bwidth;
816 bwidth = (
width & 15) > 8;
821 mask |= bitrev8(
data[1]) << 8;
840 tgafb_clut_imageblit(
struct fb_info *info,
const struct fb_image *image)
845 unsigned long pos, line_length,
i,
j;
846 const unsigned char *
data;
847 void __iomem *regs_base, *fb_base;
853 vxres = info->
var.xres_virtual;
854 vyres = info->
var.yres_virtual;
855 line_length = info->
fix.line_length;
858 if (dx > vxres || dy > vyres)
860 if (dx +
width > vxres)
862 if (dy + height > vyres)
868 pos = dy * line_length + (dx * 4);
872 for (i = 0; i <
height; i++) {
873 for (j = 0; j <
width; j++) {
892 unsigned int is8bpp = info->
var.bits_per_pixel == 8;
895 if (image->
depth == 1) {
896 tgafb_mono_imageblit(info, image);
904 if (image->
depth == info->
var.bits_per_pixel) {
910 if (!is8bpp && image->
depth == 8) {
911 tgafb_clut_imageblit(info, image);
930 int is8bpp = info->
var.bits_per_pixel == 8;
931 u32 dx, dy,
width, height, vxres, vyres, color;
932 unsigned long pos,
align, line_length, i, j;
940 vxres = info->
var.xres_virtual;
941 vyres = info->
var.yres_virtual;
942 line_length = info->
fix.line_length;
947 if (dx > vxres || dy > vyres || !
width || !height)
949 if (dx +
width > vxres)
951 if (dy + height > vyres)
954 pos = dy * line_length + dx * (is8bpp ? 1 : 4);
969 color |= color << 16;
999 if (
width == line_length)
1005 align = (pos & 3) << 16;
1008 if (
width <= 2048) {
1013 for (i = 0; i <
height; ++
i) {
1018 unsigned long Bpp = (is8bpp ? 1 : 4);
1019 unsigned long nwidth =
width & -2048;
1022 fdata = (2048 - 1) |
align;
1025 for (i = 0; i <
height; ++
i) {
1026 for (j = 0; j < nwidth; j += 2048)
1062 unsigned long dpos, spos, i, n64;
1069 n64 = (height *
width) / 64;
1072 spos = (sy +
height) * width;
1073 dpos = (dy +
height) * width;
1075 for (i = 0; i < n64; ++
i) {
1087 for (i = 0; i < n64; ++
i) {
1110 unsigned long i, n16;
1117 n16 = (height *
width) / 16;
1120 src = tga_fb + (sy +
height) * width * 4;
1121 dst = tga_fb + (dy +
height) * width * 4;
1123 for (i = 0; i < n16; ++
i) {
1132 src = tga_fb + sy * width * 4;
1133 dst = tga_fb + dy * width * 4;
1135 for (i = 0; i < n16; ++
i) {
1155 unsigned long i, copied,
left;
1156 unsigned long dpos, spos, dalign, salign, yincr;
1157 u32 smask_first, dmask_first, dmask_last;
1158 int pixel_shift, need_prime, need_second;
1159 unsigned long n64, n32, xincr_first;
1163 yincr = line_length;
1172 dpos = dy * line_length + dx;
1173 spos = sy * line_length +
sx;
1181 if (dalign >= salign)
1182 pixel_shift = dalign - salign;
1184 pixel_shift = 8 - (salign - dalign);
1188 need_prime = (salign > dalign);
1194 copied = 32 - (dalign + (dpos & 31));
1197 xincr_first = (copied + 7) & -8;
1198 smask_first = dmask_first = (1ul << copied) - 1;
1199 smask_first <<= salign;
1200 dmask_first <<= dalign + need_prime*8;
1201 if (need_prime && copied > 24)
1203 left = width - copied;
1206 if (copied > width) {
1208 t = (1ul <<
width) - 1;
1209 t <<= dalign + need_prime*8;
1216 n64 = need_second = 0;
1217 if ((dpos & 63) == (spos & 63)
1218 && (height == 1 || line_length % 64 == 0)) {
1220 need_second = (dpos + xincr_first) & 63;
1221 if ((need_second & 32) != need_second)
1223 if (
left >= need_second + 64) {
1224 left -= need_second;
1237 dmask_last = (1ul <<
left) - 1;
1247 for (i = 0; i <
height; ++
i) {
1252 sfb = tga_fb + spos;
1253 dfb = tga_fb + dpos;
1272 if (n64 && (((
unsigned long)sfb | (
unsigned long)dfb) & 63))
1274 "tgafb: misaligned copy64 (s:%p, d:%p)\n",
1277 for (j = 0; j < n64; ++
j) {
1286 for (j = 0; j < n32; ++
j) {
1317 unsigned long i,
left, yincr;
1318 unsigned long depos, sepos, dealign, sealign;
1319 u32 mask_first, mask_last;
1324 yincr = line_length;
1333 depos = dy * line_length + dx +
width;
1334 sepos = sy * line_length + sx +
width;
1335 dealign = depos & 7;
1336 sealign = sepos & 7;
1343 if (dealign != sealign) {
1350 mask_first = (1ul << dealign) - 1;
1351 left = width - dealign;
1354 if (dealign > width) {
1355 mask_first ^= (1ul << (dealign -
width)) - 1;
1364 mask_last = -1 << (32 -
left);
1374 for (i = 0; i <
height; ++
i) {
1379 sfb = tga_fb + sepos;
1380 dfb = tga_fb + depos;
1388 for (j = 0; j < n32; ++
j) {
1418 unsigned long line_length,
bpp;
1422 width = area->
width;
1426 vxres = info->
var.xres_virtual;
1427 vyres = info->
var.yres_virtual;
1428 line_length = info->
fix.line_length;
1431 if (dx > vxres || sx > vxres || dy > vyres || sy > vyres)
1435 if (dx + width > vxres)
1437 if (dy + height > vyres)
1438 height = vyres - dy;
1441 if (sx + width > vxres || sy + height > vyres)
1444 bpp = info->
var.bits_per_pixel;
1447 if (width * (bpp >> 3) == line_length) {
1449 copyarea_line_8bpp(info, dy, sy, height, width);
1451 copyarea_line_32bpp(info, dy, sy, height, width);
1462 else if (dy == sy && dx > sx && dx < sx + width)
1463 copyarea_backward_8bpp(info, dx, dy, sx, sy, height,
1464 width, line_length, area);
1466 copyarea_foreward_8bpp(info, dx, dy, sx, sy, height,
1467 width, line_length);
1476 tgafb_init_fix(
struct fb_info *info)
1482 const char *tga_type_name =
NULL;
1487 tga_type_name =
"Digital ZLXp-E1";
1489 tga_type_name =
"Digital ZLX-E1";
1493 tga_type_name =
"Digital ZLXp-E2";
1495 tga_type_name =
"Digital ZLX-E2";
1499 tga_type_name =
"Digital ZLXp-E3";
1501 tga_type_name =
"Digital ZLX-E3";
1504 tga_type_name =
"Unknown";
1511 info->
fix.type_aux = 0;
1518 info->
fix.smem_len = info->
fix.line_length * par->
yres;
1520 info->
fix.mmio_len = 512;
1522 info->
fix.xpanstep = 0;
1523 info->
fix.ypanstep = 0;
1524 info->
fix.ywrapstep = 0;
1533 info->
var.red.length = 8;
1534 info->
var.green.length = 8;
1535 info->
var.blue.length = 8;
1536 info->
var.red.offset = 16;
1537 info->
var.green.offset = 8;
1538 info->
var.blue.offset = 0;
1545 tgafb_set_par(info);
1550 tgafb_register(
struct device *dev)
1554 "1280x1024@72", 0, 1280, 1024, 7645, 224, 28, 33, 3, 160, 3,
1558 static unsigned int const fb_offset_presets[4] = {
1567 const char *mode_option_tga =
NULL;
1570 unsigned int modedbsize_tga = 0;
1600 bar0_start =
to_tc_dev(dev)->resource.start;
1601 bar0_len =
to_tc_dev(dev)->resource.end - bar0_start + 1;
1616 tga_type = (
readl(mem_base) >> 12) & 0x0f;
1630 info->
fbops = &tgafb_ops;
1636 mode_option_tga = mode_option_pci;
1639 mode_option_tga = mode_option_tc;
1640 modedb_tga = &modedb_tc;
1644 mode_option ? mode_option : mode_option_tga,
1645 modedb_tga, modedbsize_tga,
NULL,
1647 if (ret == 0 || ret == 4) {
1659 tgafb_set_par(info);
1660 tgafb_init_fix(info);
1669 pr_info(
"tgafb: DC21030 [TGA] detected, rev=0x%02x\n",
1671 pr_info(
"tgafb: at PCI bus %d, device %d, function %d\n",
1677 pr_info(
"tgafb: SFB+ detected, rev=0x%02x\n",
1679 pr_info(
"fb%d: %s frame buffer device at 0x%lx\n",
1680 info->
node, info->
fix.id, (
long)bar0_start);
1696 tgafb_unregister(
struct device *dev)
1717 bar0_start =
to_tc_dev(dev)->resource.start;
1718 bar0_len =
to_tc_dev(dev)->resource.end - bar0_start + 1;
1733 tgafb_setup(
char *
arg)
1738 while ((this_opt =
strsep(&arg,
","))) {
1741 if (!
strncmp(this_opt,
"mode:", 5))
1742 mode_option = this_opt+5;
1745 "tgafb: unknown parameter %s\n",
1763 tgafb_setup(option);
1765 status = pci_register_driver(&tgafb_pci_driver);