7 #include <linux/kernel.h>
8 #include <linux/module.h>
11 #include <linux/pci.h>
14 #include <linux/string.h>
16 #define PCI_DEVICE_ID_IBM_GXT4500P 0x21c
17 #define PCI_DEVICE_ID_IBM_GXT6000P 0x170
22 #define CFG_ENDIAN0 0x40
26 #define CTRL_REG0 0x1004
27 #define CR0_HALT_DMA 0x4
28 #define CR0_RASTER_RESET 0x8
29 #define CR0_GEOM_RESET 0x10
30 #define CR0_MEM_CTRLER_RESET 0x20
33 #define FB_AB_CTRL 0x1100
34 #define FB_CD_CTRL 0x1104
35 #define FB_WID_CTRL 0x1108
36 #define FB_Z_CTRL 0x110c
37 #define FB_VGA_CTRL 0x1110
38 #define REFRESH_AB_CTRL 0x1114
39 #define REFRESH_CD_CTRL 0x1118
40 #define FB_OVL_CTRL 0x111c
41 #define FB_CTRL_TYPE 0x80000000
42 #define FB_CTRL_WIDTH_MASK 0x007f0000
43 #define FB_CTRL_WIDTH_SHIFT 16
44 #define FB_CTRL_START_SEG_MASK 0x00003fff
46 #define REFRESH_START 0x1098
47 #define REFRESH_SIZE 0x109c
50 #define DFA_FB_A 0x11e0
51 #define DFA_FB_B 0x11e4
52 #define DFA_FB_C 0x11e8
53 #define DFA_FB_D 0x11ec
54 #define DFA_FB_ENABLE 0x80000000
55 #define DFA_FB_BASE_MASK 0x03f00000
56 #define DFA_FB_STRIDE_1k 0x00000000
57 #define DFA_FB_STRIDE_2k 0x00000010
58 #define DFA_FB_STRIDE_4k 0x00000020
59 #define DFA_PIX_8BIT 0x00000000
60 #define DFA_PIX_16BIT_565 0x00000001
61 #define DFA_PIX_16BIT_1555 0x00000002
62 #define DFA_PIX_24BIT 0x00000004
63 #define DFA_PIX_32BIT 0x00000005
66 static const unsigned char pixsize[] = {
71 #define DTG_CONTROL 0x1900
72 #define DTG_CTL_SCREEN_REFRESH 2
73 #define DTG_CTL_ENABLE 1
74 #define DTG_HORIZ_EXTENT 0x1904
75 #define DTG_HORIZ_DISPLAY 0x1908
76 #define DTG_HSYNC_START 0x190c
77 #define DTG_HSYNC_END 0x1910
78 #define DTG_HSYNC_END_COMP 0x1914
79 #define DTG_VERT_EXTENT 0x1918
80 #define DTG_VERT_DISPLAY 0x191c
81 #define DTG_VSYNC_START 0x1920
82 #define DTG_VSYNC_END 0x1924
83 #define DTG_VERT_SHORT 0x1928
86 #define DISP_CTL 0x402c
87 #define DISP_CTL_OFF 2
88 #define SYNC_CTL 0x4034
89 #define SYNC_CTL_SYNC_ON_RGB 1
90 #define SYNC_CTL_SYNC_OFF 2
91 #define SYNC_CTL_HSYNC_INV 8
92 #define SYNC_CTL_VSYNC_INV 0x10
93 #define SYNC_CTL_HSYNC_OFF 0x20
94 #define SYNC_CTL_VSYNC_OFF 0x40
98 #define PLL_POSTDIV 0x4048
102 #define CURSOR_X 0x4078
103 #define CURSOR_Y 0x407c
104 #define CURSOR_HOTSPOT 0x4080
105 #define CURSOR_MODE 0x4084
106 #define CURSOR_MODE_OFF 0
107 #define CURSOR_MODE_4BPP 1
108 #define CURSOR_PIXMAP 0x5000
109 #define CURSOR_CMAP 0x7400
112 #define WAT_FMT 0x4100
113 #define WAT_FMT_24BIT 0
114 #define WAT_FMT_16BIT_565 1
115 #define WAT_FMT_16BIT_1555 2
116 #define WAT_FMT_32BIT 3
117 #define WAT_FMT_8BIT_332 9
118 #define WAT_FMT_8BIT 0xa
119 #define WAT_FMT_NO_CMAP 4
120 #define WAT_CMAP_OFFSET 0x4104
121 #define WAT_CTRL 0x4108
122 #define WAT_CTRL_SEL_B 1
123 #define WAT_CTRL_NO_INC 2
124 #define WAT_GAMMA_CTRL 0x410c
125 #define WAT_GAMMA_DISABLE 1
126 #define WAT_OVL_CTRL 0x430c
129 static const unsigned char watfmt[] = {
137 #define readreg(par, reg) readl((par)->regs + (reg))
138 #define writereg(par, reg, val) writel((val), (par)->regs + (reg))
156 static char *mode_option;
185 [
GXT6000P] = { .refclk_ps = 40000, .cardname =
"IBM GXT6000P" },
198 static const unsigned char mdivtab[] = {
199 0x3f, 0x00, 0x20, 0x10, 0x28, 0x14, 0x2a, 0x15, 0x0a,
200 0x25, 0x32, 0x19, 0x0c, 0x26, 0x13, 0x09, 0x04, 0x22, 0x11,
201 0x08, 0x24, 0x12, 0x29, 0x34, 0x1a, 0x2d, 0x36, 0x1b, 0x0d,
202 0x06, 0x23, 0x31, 0x38, 0x1c, 0x2e, 0x17, 0x0b, 0x05, 0x02,
203 0x21, 0x30, 0x18, 0x2c, 0x16, 0x2b, 0x35, 0x3a, 0x1d, 0x0e,
204 0x27, 0x33, 0x39, 0x3c, 0x1e, 0x2f, 0x37, 0x3b, 0x3d, 0x3e,
205 0x1f, 0x0f, 0x07, 0x03, 0x01,
208 static const unsigned char ndivtab[] = {
209 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0x78, 0xbc, 0x5e,
210 0x2f, 0x17, 0x0b, 0x85, 0xc2, 0xe1, 0x70, 0x38, 0x9c, 0x4e,
211 0xa7, 0xd3, 0xe9, 0xf4, 0xfa, 0xfd, 0xfe, 0x7f, 0xbf, 0xdf,
212 0xef, 0x77, 0x3b, 0x1d, 0x8e, 0xc7, 0xe3, 0x71, 0xb8, 0xdc,
213 0x6e, 0xb7, 0x5b, 0x2d, 0x16, 0x8b, 0xc5, 0xe2, 0xf1, 0xf8,
214 0xfc, 0x7e, 0x3f, 0x9f, 0xcf, 0x67, 0xb3, 0xd9, 0x6c, 0xb6,
215 0xdb, 0x6d, 0x36, 0x9b, 0x4d, 0x26, 0x13, 0x89, 0xc4, 0x62,
216 0xb1, 0xd8, 0xec, 0xf6, 0xfb, 0x7d, 0xbe, 0x5f, 0xaf, 0x57,
217 0x2b, 0x95, 0x4a, 0x25, 0x92, 0x49, 0xa4, 0x52, 0x29, 0x94,
218 0xca, 0x65, 0xb2, 0x59, 0x2c, 0x96, 0xcb, 0xe5, 0xf2, 0x79,
219 0x3c, 0x1e, 0x0f, 0x07, 0x83, 0x41, 0x20, 0x90, 0x48, 0x24,
220 0x12, 0x09, 0x84, 0x42, 0xa1, 0x50, 0x28, 0x14, 0x8a, 0x45,
221 0xa2, 0xd1, 0xe8, 0x74, 0xba, 0xdd, 0xee, 0xf7, 0x7b, 0x3d,
222 0x9e, 0x4f, 0x27, 0x93, 0xc9, 0xe4, 0x72, 0x39, 0x1c, 0x0e,
223 0x87, 0xc3, 0x61, 0x30, 0x18, 0x8c, 0xc6, 0x63, 0x31, 0x98,
224 0xcc, 0xe6, 0x73, 0xb9, 0x5c, 0x2e, 0x97, 0x4b, 0xa5, 0xd2,
228 static int calc_pll(
int period_ps,
struct gxt4500_par *par)
230 int m,
n, pdiv1, pdiv2, postdiv;
231 int pll_period, best_error,
t,
intf;
234 if (period_ps < 3333 || period_ps > 200000)
237 best_error = 1000000;
238 for (pdiv1 = 1; pdiv1 <= 8; ++pdiv1) {
239 for (pdiv2 = 1; pdiv2 <= pdiv1; ++pdiv2) {
240 postdiv = pdiv1 * pdiv2;
243 if (pll_period < 1666 || pll_period > 2857)
245 for (m = 1; m <= 64; ++
m) {
249 n = intf * postdiv / period_ps;
250 if (n < 3 || n > 160)
254 if (t >= 0 && t < best_error) {
264 if (best_error == 1000000)
285 if (calc_pll(var->
pixclock, par) < 0)
299 if (var->
green.length == 5)
314 static const struct fb_bitfield eightbits = {0, 8};
321 var->
red = eightbits;
322 var->
green = eightbits;
323 var->
blue = eightbits;
329 var->
green.length = 6;
330 var->
blue.length = 5;
334 var->
green.length = 5;
335 var->
blue.length = 5;
343 var->
green.offset = var->
red.length;
347 var->
blue.offset + var->
blue.length;
358 err = gxt4500_var_to_par(var, &par);
360 var->
pixclock = calc_pixclock(&par);
361 gxt4500_unpack_pixfmt(var, par.
pixfmt);
366 static int gxt4500_set_par(
struct fb_info *info)
372 unsigned int dfa_ctl, pixfmt, stride;
373 unsigned int wid_tiles,
i;
374 unsigned int prefetch_pix, htot;
378 err = gxt4500_var_to_par(var, par);
395 else if (par->
pll_n < 100)
436 prefetch_pix = 3300000 / var->
pixclock;
437 if (prefetch_pix >= htot)
438 prefetch_pix = htot - 1;
477 for (i = 0; i < 32; ++
i) {
496 info->
fix.line_length = stride * pixsize[
pixfmt];
503 static int gxt4500_setcolreg(
unsigned int reg,
unsigned int red,
512 cmap_entry = ((transp & 0xff00) << 16) | ((red & 0xff00) << 8) |
513 (green & 0xff00) | (blue >> 8);
521 val |= (reg << 11) | (reg << 6);
524 val |= (reg << 10) | (reg << 5);
530 val |= (reg << 16) | (reg << 8);
546 if (var->
xoffset + info->
var.xres > info->
var.xres_virtual ||
554 static int gxt4500_blank(
int blank,
struct fb_info *info)
585 .id =
"IBM GXT4500P",
593 static struct fb_ops gxt4500_ops = {
595 .fb_check_var = gxt4500_check_var,
596 .fb_set_par = gxt4500_set_par,
597 .fb_setcolreg = gxt4500_setcolreg,
598 .fb_pan_display = gxt4500_pan_display,
599 .fb_blank = gxt4500_blank,
610 unsigned long reg_phys, fb_phys;
618 dev_err(&pdev->
dev,
"gxt4500: cannot enable PCI device: %d\n",
626 dev_err(&pdev->
dev,
"gxt4500: cannot get registers\n");
633 dev_err(&pdev->
dev,
"gxt4500: cannot get framebuffer\n");
639 dev_err(&pdev->
dev,
"gxt4500: cannot alloc FB info record\n");
645 info->
fix = gxt4500_fix;
647 sizeof(info->
fix.id));
650 info->
fix.mmio_start = reg_phys;
653 dev_err(&pdev->
dev,
"gxt4500: cannot map registers\n");
657 info->
fix.smem_start = fb_phys;
661 dev_err(&pdev->
dev,
"gxt4500: cannot map framebuffer\n");
665 pci_set_drvdata(pdev, info);
668 pci_write_config_dword(pdev,
CFG_ENDIAN0, 0x333300);
670 info->
fbops = &gxt4500_ops;
675 dev_err(&pdev->
dev,
"gxt4500: cannot allocate cmap\n");
682 dev_err(&pdev->
dev,
"gxt4500: cannot find valid video mode\n");
686 if (gxt4500_set_par(info)) {
692 dev_err(&pdev->
dev,
"gxt4500: cannot register framebuffer\n");
718 struct fb_info *info = pci_get_drvdata(pdev);
748 .id_table = gxt4500_pci_tbl,
749 .probe = gxt4500_probe,
760 return pci_register_driver(&gxt4500_driver);
764 static void __exit gxt4500_exit(
void)
774 MODULE_PARM_DESC(mode_option,
"Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\"");