14 #include <linux/module.h>
15 #include <linux/kernel.h>
16 #include <linux/errno.h>
17 #include <linux/string.h>
19 #include <linux/slab.h>
23 #include <linux/pci.h>
25 #include <linux/i2c.h>
89 #define DACSPEED16 163
90 #define DACSPEED24_SG 136
91 #define DACSPEED24_SD 128
105 vga_mm_w(par->
regs, port, val);
109 return vga_mm_r(par->
regs, port);
113 vga_mm_w_fast(par->
regs, port, reg, val);
117 vga_mm_w(par->
regs, port, reg);
118 return vga_mm_r(par->
regs, port+1);
123 vga_mm_w_fast(par->
regs, port, reg, (val & mask)
124 | (i740inreg(par, port, reg) & ~mask));
127 #define REG_DDC_DRIVE 0x62
128 #define REG_DDC_STATE 0x63
129 #define DDC_SCL (1 << 3)
130 #define DDC_SDA (1 << 2)
132 static void i740fb_ddc_setscl(
void *
data,
int val)
140 static void i740fb_ddc_setsda(
void *
data,
int val)
148 static int i740fb_ddc_getscl(
void *
data)
157 static int i740fb_ddc_getsda(
void *
data)
176 par->
ddc_algo.setsda = i740fb_ddc_setsda;
177 par->
ddc_algo.setscl = i740fb_ddc_setscl;
178 par->
ddc_algo.getsda = i740fb_ddc_getsda;
179 par->
ddc_algo.getscl = i740fb_ddc_getscl;
200 static int i740fb_release(
struct fb_info *info,
int user)
346 #define I740_RFREQ 1000000
347 #define TARGET_MAX_N 30
348 #define I740_FFIX (1 << 8)
349 #define I740_RFREQ_FIX (I740_RFREQ / I740_FFIX)
350 #define I740_REF_FREQ (6667 * I740_FFIX / 100)
351 #define I740_MAX_VCO_FREQ (450 * I740_FFIX)
359 int m_best = 0, n_best = 0, p_best = 0, d_best = 0;
377 /
n) + ((1 << p_best) / 2)) / (1 << p_best);
379 f_err = (freq - f_out);
381 if (
abs(f_err) < err_max) {
387 }
while ((
abs(f_err) >= err_target) &&
390 if (
abs(f_err) < err_target) {
400 ((p_best << 4) | (d_best ? 4 : 0) |
REF_DIV_1);
412 u32 yres, lower, vslen, upper, ytotal;
413 u32 vxres, xoffset, vyres, yoffset;
418 dev_dbg(info->
device,
"decode_var: xres: %i, yres: %i, xres_v: %i, xres_v: %i\n",
420 dev_dbg(info->
device,
" xoff: %i, yoff: %i, bpp: %i, graysc: %i\n",
423 dev_dbg(info->
device,
" activate: %i, nonstd: %i, vmode: %i\n",
425 dev_dbg(info->
device,
" pixclock: %i, hsynclen:%i, vsynclen:%i\n",
427 dev_dbg(info->
device,
" left: %i, right: %i, up:%i, lower:%i\n",
437 dev_err(info->
device,
"requested pixclock %i MHz out of range (max. %i MHz at 8bpp)\n",
446 dev_err(info->
device,
"requested pixclock %i MHz out of range (max. %i MHz at 15/16bpp)\n",
454 if ((1000000 / var->
pixclock) > dacspeed24) {
455 dev_err(info->
device,
"requested pixclock %i MHz out of range (max. %i MHz at 24bpp)\n",
456 1000000 / var->
pixclock, dacspeed24);
463 dev_err(info->
device,
"requested pixclock %i MHz out of range (max. %i MHz at 32bpp)\n",
478 if (xres + xoffset > vxres)
479 xoffset = vxres - xres;
491 if (yres + yoffset > vyres)
492 yoffset = vyres - yres;
498 mem = vxres * vyres * ((bpp + 1) / 8);
500 dev_err(info->
device,
"not enough video memory (%d KB requested, %ld KB available)\n",
505 if (yoffset + yres > vyres)
506 yoffset = vyres - yres;
508 xtotal = xres + right + hslen +
left;
509 ytotal = yres + lower + vslen + upper;
516 | ((((xres + right + hslen) >> 3) & 0x20) << 2);
537 if ((yres-1) & 0x100)
539 if ((yres-1) & 0x200)
544 if ((yres + lower - 1) & 0x100)
546 if ((yres + lower - 1) & 0x200) {
553 ((yres + lower - 1 + vslen) & 0x0F) & ~0x10;
564 for (i = 0x00; i < 0x10; i++)
592 base = (yoffset * vxres + (xoffset & ~7)) >> 2;
663 i740_calc_fifo(par, 1000000 / var->
pixclock, bpp);
672 var->
red.offset = var->
green.offset = var->
blue.offset = 0;
673 var->
red.length = var->
green.length = var->
blue.length = 8;
676 switch (var->
green.length) {
679 var->
red.offset = 10;
680 var->
green.offset = 5;
681 var->
blue.offset = 0;
683 var->
green.length = 5;
684 var->
blue.length = 5;
687 var->
red.offset = 11;
688 var->
green.offset = 5;
689 var->
blue.offset = 0;
690 var->
red.length = var->
blue.length = 5;
695 var->
red.offset = 16;
696 var->
green.offset = 8;
697 var->
blue.offset = 0;
698 var->
red.length = var->
green.length = var->
blue.length = 8;
702 var->
red.offset = 16;
703 var->
green.offset = 8;
704 var->
blue.offset = 0;
706 var->
red.length = var->
green.length = var->
blue.length = 8;
725 static void vga_protect(
struct i740fb_par *par)
734 static void vga_unprotect(
struct i740fb_par *par)
743 static int i740fb_set_par(
struct fb_info *info)
749 i = i740fb_decode_var(&info->
var, par, info);
770 i740outb(par, 0x3C0, 0x00);
848 for (i = 0; i < 256; i++) {
860 info->
fix.line_length =
861 info->
var.xres_virtual * info->
var.bits_per_pixel / 8;
862 if (info->
var.bits_per_pixel == 8)
870 static int i740fb_setcolreg(
unsigned regno,
unsigned red,
unsigned green,
876 dev_dbg(info->
device,
"setcolreg: regno: %i, red=%d, green=%d, blue=%d, transp=%d, bpp=%d\n",
877 regno, red, green, blue, transp, info->
var.bits_per_pixel);
879 switch (info->
fix.visual) {
891 r = (red >> (16 - info->
var.red.length))
892 << info->
var.red.offset;
893 b = (blue >> (16 - info->
var.blue.length))
894 << info->
var.blue.offset;
895 g = (green >> (16 - info->
var.green.length))
896 << info->
var.green.offset;
913 dev_dbg(info->
device,
"pan_display: xoffset: %i yoffset: %i base: %i\n",
916 switch (info->
var.bits_per_pixel) {
944 (base & 0x0000FF00) >> 8);
946 (base & 0x3FC00000) >> 22);
953 static int i740fb_blank(
int blank_mode,
struct fb_info *info)
960 switch (blank_mode) {
982 i740outb(par,
SRX, 0x01);
983 SEQ01 |= i740inb(par,
SRX + 1) & ~0x20;
984 i740outb(par,
SRX, 0x01);
985 i740outb(par,
SRX + 1, SEQ01);
994 static struct fb_ops i740fb_ops = {
996 .fb_open = i740fb_open,
997 .fb_release = i740fb_release,
998 .fb_check_var = i740fb_check_var,
999 .fb_set_par = i740fb_set_par,
1000 .fb_setcolreg = i740fb_setcolreg,
1001 .fb_blank = i740fb_blank,
1002 .fb_pan_display = i740fb_pan_display,
1021 dev_err(&(dev->
dev),
"cannot allocate framebuffer\n");
1029 info->
var.bits_per_pixel = 8;
1030 info->
fbops = &i740fb_ops;
1036 goto err_enable_device;
1042 goto err_request_regions;
1075 info->
fix = i740fb_fix;
1082 if (i740fb_setup_ddc_bus(info) == 0) {
1090 "error getting mode database\n");
1103 if (!i740fb_check_var(&info->
var, info))
1110 if (!mode_option && !found)
1111 mode_option =
"640x480-8@60";
1117 NULL, info->
var.bits_per_pixel);
1118 if (!ret || ret == 4) {
1129 info->
var.yres_virtual = info->
fix.smem_len * 8 /
1130 (info->
var.bits_per_pixel * info->
var.xres_virtual);
1138 goto err_alloc_cmap;
1144 goto err_reg_framebuffer;
1149 pci_set_drvdata(dev, info);
1159 err_reg_framebuffer:
1170 err_request_regions:
1179 struct fb_info *info = pci_get_drvdata(dev);
1185 if (par->mtrr_reg >= 0) {
1198 pci_set_drvdata(dev,
NULL);
1206 struct fb_info *info = pci_get_drvdata(dev);
1237 struct fb_info *info = pci_get_drvdata(dev);
1251 i740fb_set_par(info);
1260 #define i740fb_suspend NULL
1261 #define i740fb_resume NULL
1264 #define I740_ID_PCI 0x00d1
1265 #define I740_ID_AGP 0x7800
1276 .id_table = i740fb_id_table,
1277 .probe = i740fb_probe,
1288 if (!options || !*options)
1291 while ((opt =
strsep(&options,
",")) !=
NULL) {
1295 else if (!
strncmp(opt,
"mtrr:", 5))
1313 i740fb_setup(option);
1316 return pci_register_driver(&i740fb_driver);
1319 static void __exit i740fb_exit(
void)
1336 MODULE_PARM_DESC(mtrr,
"Enable write-combining with MTRR (1=enable, 0=disable, default=1)");