0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089 #include "matroxfb_misc.h"
0090 #include <linux/interrupt.h>
0091 #include <linux/matroxfb.h>
0092
0093 void matroxfb_DAC_out(const struct matrox_fb_info *minfo, int reg, int val)
0094 {
0095 DBG_REG(__func__)
0096 mga_outb(M_RAMDAC_BASE+M_X_INDEX, reg);
0097 mga_outb(M_RAMDAC_BASE+M_X_DATAREG, val);
0098 }
0099
0100 int matroxfb_DAC_in(const struct matrox_fb_info *minfo, int reg)
0101 {
0102 DBG_REG(__func__)
0103 mga_outb(M_RAMDAC_BASE+M_X_INDEX, reg);
0104 return mga_inb(M_RAMDAC_BASE+M_X_DATAREG);
0105 }
0106
0107 void matroxfb_var2my(struct fb_var_screeninfo* var, struct my_timming* mt) {
0108 unsigned int pixclock = var->pixclock;
0109
0110 DBG(__func__)
0111
0112 if (!pixclock) pixclock = 10000;
0113 mt->pixclock = 1000000000 / pixclock;
0114 if (mt->pixclock < 1) mt->pixclock = 1;
0115 mt->mnp = -1;
0116 mt->dblscan = var->vmode & FB_VMODE_DOUBLE;
0117 mt->interlaced = var->vmode & FB_VMODE_INTERLACED;
0118 mt->HDisplay = var->xres;
0119 mt->HSyncStart = mt->HDisplay + var->right_margin;
0120 mt->HSyncEnd = mt->HSyncStart + var->hsync_len;
0121 mt->HTotal = mt->HSyncEnd + var->left_margin;
0122 mt->VDisplay = var->yres;
0123 mt->VSyncStart = mt->VDisplay + var->lower_margin;
0124 mt->VSyncEnd = mt->VSyncStart + var->vsync_len;
0125 mt->VTotal = mt->VSyncEnd + var->upper_margin;
0126 mt->sync = var->sync;
0127 }
0128
0129 int matroxfb_PLL_calcclock(const struct matrox_pll_features* pll, unsigned int freq, unsigned int fmax,
0130 unsigned int* in, unsigned int* feed, unsigned int* post) {
0131 unsigned int bestdiff = ~0;
0132 unsigned int bestvco = 0;
0133 unsigned int fxtal = pll->ref_freq;
0134 unsigned int fwant;
0135 unsigned int p;
0136
0137 DBG(__func__)
0138
0139 fwant = freq;
0140
0141 #ifdef DEBUG
0142 printk(KERN_ERR "post_shift_max: %d\n", pll->post_shift_max);
0143 printk(KERN_ERR "ref_freq: %d\n", pll->ref_freq);
0144 printk(KERN_ERR "freq: %d\n", freq);
0145 printk(KERN_ERR "vco_freq_min: %d\n", pll->vco_freq_min);
0146 printk(KERN_ERR "in_div_min: %d\n", pll->in_div_min);
0147 printk(KERN_ERR "in_div_max: %d\n", pll->in_div_max);
0148 printk(KERN_ERR "feed_div_min: %d\n", pll->feed_div_min);
0149 printk(KERN_ERR "feed_div_max: %d\n", pll->feed_div_max);
0150 printk(KERN_ERR "fmax: %d\n", fmax);
0151 #endif
0152 for (p = 1; p <= pll->post_shift_max; p++) {
0153 if (fwant * 2 > fmax)
0154 break;
0155 fwant *= 2;
0156 }
0157 if (fwant < pll->vco_freq_min) fwant = pll->vco_freq_min;
0158 if (fwant > fmax) fwant = fmax;
0159 for (; p-- > 0; fwant >>= 1, bestdiff >>= 1) {
0160 unsigned int m;
0161
0162 if (fwant < pll->vco_freq_min) break;
0163 for (m = pll->in_div_min; m <= pll->in_div_max; m++) {
0164 unsigned int diff, fvco;
0165 unsigned int n;
0166
0167 n = (fwant * (m + 1) + (fxtal >> 1)) / fxtal - 1;
0168 if (n > pll->feed_div_max)
0169 break;
0170 if (n < pll->feed_div_min)
0171 n = pll->feed_div_min;
0172 fvco = (fxtal * (n + 1)) / (m + 1);
0173 if (fvco < fwant)
0174 diff = fwant - fvco;
0175 else
0176 diff = fvco - fwant;
0177 if (diff < bestdiff) {
0178 bestdiff = diff;
0179 *post = p;
0180 *in = m;
0181 *feed = n;
0182 bestvco = fvco;
0183 }
0184 }
0185 }
0186 dprintk(KERN_ERR "clk: %02X %02X %02X %d %d %d\n", *in, *feed, *post, fxtal, bestvco, fwant);
0187 return bestvco;
0188 }
0189
0190 int matroxfb_vgaHWinit(struct matrox_fb_info *minfo, struct my_timming *m)
0191 {
0192 unsigned int hd, hs, he, hbe, ht;
0193 unsigned int vd, vs, ve, vt, lc;
0194 unsigned int wd;
0195 unsigned int divider;
0196 int i;
0197 struct matrox_hw_state * const hw = &minfo->hw;
0198
0199 DBG(__func__)
0200
0201 hw->SEQ[0] = 0x00;
0202 hw->SEQ[1] = 0x01;
0203 hw->SEQ[2] = 0x0F;
0204 hw->SEQ[3] = 0x00;
0205 hw->SEQ[4] = 0x0E;
0206
0207 if (m->dblscan) {
0208 m->VTotal <<= 1;
0209 m->VDisplay <<= 1;
0210 m->VSyncStart <<= 1;
0211 m->VSyncEnd <<= 1;
0212 }
0213 if (m->interlaced) {
0214 m->VTotal >>= 1;
0215 m->VDisplay >>= 1;
0216 m->VSyncStart >>= 1;
0217 m->VSyncEnd >>= 1;
0218 }
0219
0220
0221 hw->GCTL[0] = 0x00;
0222 hw->GCTL[1] = 0x00;
0223 hw->GCTL[2] = 0x00;
0224 hw->GCTL[3] = 0x00;
0225 hw->GCTL[4] = 0x00;
0226 hw->GCTL[5] = 0x40;
0227 hw->GCTL[6] = 0x05;
0228 hw->GCTL[7] = 0x0F;
0229 hw->GCTL[8] = 0xFF;
0230
0231
0232 for (i = 0; i < 16; i++)
0233 hw->ATTR[i] = i;
0234 hw->ATTR[16] = 0x41;
0235 hw->ATTR[17] = 0xFF;
0236 hw->ATTR[18] = 0x0F;
0237 hw->ATTR[19] = 0x00;
0238 hw->ATTR[20] = 0x00;
0239
0240 hd = m->HDisplay >> 3;
0241 hs = m->HSyncStart >> 3;
0242 he = m->HSyncEnd >> 3;
0243 ht = m->HTotal >> 3;
0244
0245
0246
0247 divider = minfo->curr.final_bppShift;
0248 while (divider & 3) {
0249 hd >>= 1;
0250 hs >>= 1;
0251 he >>= 1;
0252 ht >>= 1;
0253 divider <<= 1;
0254 }
0255 divider = divider / 4;
0256
0257 while (divider > 8) {
0258 hd <<= 1;
0259 hs <<= 1;
0260 he <<= 1;
0261 ht <<= 1;
0262 divider >>= 1;
0263 }
0264 hd = hd - 1;
0265 hs = hs - 1;
0266 he = he - 1;
0267 ht = ht - 1;
0268 vd = m->VDisplay - 1;
0269 vs = m->VSyncStart - 1;
0270 ve = m->VSyncEnd - 1;
0271 vt = m->VTotal - 2;
0272 lc = vd;
0273
0274 if (((ht & 0x07) == 0x06) || ((ht & 0x0F) == 0x04))
0275 ht++;
0276 hbe = ht;
0277 wd = minfo->fbcon.var.xres_virtual * minfo->curr.final_bppShift / 64;
0278
0279 hw->CRTCEXT[0] = 0;
0280 hw->CRTCEXT[5] = 0;
0281 if (m->interlaced) {
0282 hw->CRTCEXT[0] = 0x80;
0283 hw->CRTCEXT[5] = (hs + he - ht) >> 1;
0284 if (!m->dblscan)
0285 wd <<= 1;
0286 vt &= ~1;
0287 }
0288 hw->CRTCEXT[0] |= (wd & 0x300) >> 4;
0289 hw->CRTCEXT[1] = (((ht - 4) & 0x100) >> 8) |
0290 ((hd & 0x100) >> 7) |
0291 ((hs & 0x100) >> 6) |
0292 (hbe & 0x040);
0293
0294 if (minfo->outputs[1].src == MATROXFB_SRC_CRTC1)
0295 hw->CRTCEXT[1] |= 0x88;
0296 hw->CRTCEXT[2] = ((vt & 0xC00) >> 10) |
0297 ((vd & 0x400) >> 8) |
0298 ((vd & 0xC00) >> 7) |
0299 ((vs & 0xC00) >> 5) |
0300 ((lc & 0x400) >> 3);
0301 hw->CRTCEXT[3] = (divider - 1) | 0x80;
0302 hw->CRTCEXT[4] = 0;
0303
0304 hw->CRTC[0] = ht-4;
0305 hw->CRTC[1] = hd;
0306 hw->CRTC[2] = hd;
0307 hw->CRTC[3] = (hbe & 0x1F) | 0x80;
0308 hw->CRTC[4] = hs;
0309 hw->CRTC[5] = ((hbe & 0x20) << 2) | (he & 0x1F);
0310 hw->CRTC[6] = vt & 0xFF;
0311 hw->CRTC[7] = ((vt & 0x100) >> 8) |
0312 ((vd & 0x100) >> 7) |
0313 ((vs & 0x100) >> 6) |
0314 ((vd & 0x100) >> 5) |
0315 ((lc & 0x100) >> 4) |
0316 ((vt & 0x200) >> 4) |
0317 ((vd & 0x200) >> 3) |
0318 ((vs & 0x200) >> 2);
0319 hw->CRTC[8] = 0x00;
0320 hw->CRTC[9] = ((vd & 0x200) >> 4) |
0321 ((lc & 0x200) >> 3);
0322 if (m->dblscan && !m->interlaced)
0323 hw->CRTC[9] |= 0x80;
0324 for (i = 10; i < 16; i++)
0325 hw->CRTC[i] = 0x00;
0326 hw->CRTC[16] = vs ;
0327 hw->CRTC[17] = (ve & 0x0F) | 0x20;
0328 hw->CRTC[18] = vd ;
0329 hw->CRTC[19] = wd ;
0330 hw->CRTC[20] = 0x00;
0331 hw->CRTC[21] = vd ;
0332 hw->CRTC[22] = (vt + 1) ;
0333 hw->CRTC[23] = 0xC3;
0334 hw->CRTC[24] = lc;
0335 return 0;
0336 };
0337
0338 void matroxfb_vgaHWrestore(struct matrox_fb_info *minfo)
0339 {
0340 int i;
0341 struct matrox_hw_state * const hw = &minfo->hw;
0342 CRITFLAGS
0343
0344 DBG(__func__)
0345
0346 dprintk(KERN_INFO "MiscOutReg: %02X\n", hw->MiscOutReg);
0347 dprintk(KERN_INFO "SEQ regs: ");
0348 for (i = 0; i < 5; i++)
0349 dprintk("%02X:", hw->SEQ[i]);
0350 dprintk("\n");
0351 dprintk(KERN_INFO "GDC regs: ");
0352 for (i = 0; i < 9; i++)
0353 dprintk("%02X:", hw->GCTL[i]);
0354 dprintk("\n");
0355 dprintk(KERN_INFO "CRTC regs: ");
0356 for (i = 0; i < 25; i++)
0357 dprintk("%02X:", hw->CRTC[i]);
0358 dprintk("\n");
0359 dprintk(KERN_INFO "ATTR regs: ");
0360 for (i = 0; i < 21; i++)
0361 dprintk("%02X:", hw->ATTR[i]);
0362 dprintk("\n");
0363
0364 CRITBEGIN
0365
0366 mga_inb(M_ATTR_RESET);
0367 mga_outb(M_ATTR_INDEX, 0);
0368 mga_outb(M_MISC_REG, hw->MiscOutReg);
0369 for (i = 1; i < 5; i++)
0370 mga_setr(M_SEQ_INDEX, i, hw->SEQ[i]);
0371 mga_setr(M_CRTC_INDEX, 17, hw->CRTC[17] & 0x7F);
0372 for (i = 0; i < 25; i++)
0373 mga_setr(M_CRTC_INDEX, i, hw->CRTC[i]);
0374 for (i = 0; i < 9; i++)
0375 mga_setr(M_GRAPHICS_INDEX, i, hw->GCTL[i]);
0376 for (i = 0; i < 21; i++) {
0377 mga_inb(M_ATTR_RESET);
0378 mga_outb(M_ATTR_INDEX, i);
0379 mga_outb(M_ATTR_INDEX, hw->ATTR[i]);
0380 }
0381 mga_outb(M_PALETTE_MASK, 0xFF);
0382 mga_outb(M_DAC_REG, 0x00);
0383 for (i = 0; i < 768; i++)
0384 mga_outb(M_DAC_VAL, hw->DACpal[i]);
0385 mga_inb(M_ATTR_RESET);
0386 mga_outb(M_ATTR_INDEX, 0x20);
0387
0388 CRITEND
0389 }
0390
0391 static void get_pins(unsigned char __iomem* pins, struct matrox_bios* bd) {
0392 unsigned int b0 = readb(pins);
0393
0394 if (b0 == 0x2E && readb(pins+1) == 0x41) {
0395 unsigned int pins_len = readb(pins+2);
0396 unsigned int i;
0397 unsigned char cksum;
0398 unsigned char* dst = bd->pins;
0399
0400 if (pins_len < 3 || pins_len > 128) {
0401 return;
0402 }
0403 *dst++ = 0x2E;
0404 *dst++ = 0x41;
0405 *dst++ = pins_len;
0406 cksum = 0x2E + 0x41 + pins_len;
0407 for (i = 3; i < pins_len; i++) {
0408 cksum += *dst++ = readb(pins+i);
0409 }
0410 if (cksum) {
0411 return;
0412 }
0413 bd->pins_len = pins_len;
0414 } else if (b0 == 0x40 && readb(pins+1) == 0x00) {
0415 unsigned int i;
0416 unsigned char* dst = bd->pins;
0417
0418 *dst++ = 0x40;
0419 *dst++ = 0;
0420 for (i = 2; i < 0x40; i++) {
0421 *dst++ = readb(pins+i);
0422 }
0423 bd->pins_len = 0x40;
0424 }
0425 }
0426
0427 static void get_bios_version(unsigned char __iomem * vbios, struct matrox_bios* bd) {
0428 unsigned int pcir_offset;
0429
0430 pcir_offset = readb(vbios + 24) | (readb(vbios + 25) << 8);
0431 if (pcir_offset >= 26 && pcir_offset < 0xFFE0 &&
0432 readb(vbios + pcir_offset ) == 'P' &&
0433 readb(vbios + pcir_offset + 1) == 'C' &&
0434 readb(vbios + pcir_offset + 2) == 'I' &&
0435 readb(vbios + pcir_offset + 3) == 'R') {
0436 unsigned char h;
0437
0438 h = readb(vbios + pcir_offset + 0x12);
0439 bd->version.vMaj = (h >> 4) & 0xF;
0440 bd->version.vMin = h & 0xF;
0441 bd->version.vRev = readb(vbios + pcir_offset + 0x13);
0442 } else {
0443 unsigned char h;
0444
0445 h = readb(vbios + 5);
0446 bd->version.vMaj = (h >> 4) & 0xF;
0447 bd->version.vMin = h & 0xF;
0448 bd->version.vRev = 0;
0449 }
0450 }
0451
0452 static void get_bios_output(unsigned char __iomem* vbios, struct matrox_bios* bd) {
0453 unsigned char b;
0454
0455 b = readb(vbios + 0x7FF1);
0456 if (b == 0xFF) {
0457 b = 0;
0458 }
0459 bd->output.state = b;
0460 }
0461
0462 static void get_bios_tvout(unsigned char __iomem* vbios, struct matrox_bios* bd) {
0463 unsigned int i;
0464
0465
0466 bd->output.tvout = 0;
0467 if (readb(vbios + 0x1D) != 'I' ||
0468 readb(vbios + 0x1E) != 'B' ||
0469 readb(vbios + 0x1F) != 'M' ||
0470 readb(vbios + 0x20) != ' ') {
0471 return;
0472 }
0473 for (i = 0x2D; i < 0x2D + 128; i++) {
0474 unsigned char b = readb(vbios + i);
0475
0476 if (b == '(' && readb(vbios + i + 1) == 'V') {
0477 if (readb(vbios + i + 6) == 'T' &&
0478 readb(vbios + i + 7) == 'V' &&
0479 readb(vbios + i + 8) == 'O') {
0480 bd->output.tvout = 1;
0481 }
0482 return;
0483 }
0484 if (b == 0)
0485 break;
0486 }
0487 }
0488
0489 static void parse_bios(unsigned char __iomem* vbios, struct matrox_bios* bd) {
0490 unsigned int pins_offset;
0491
0492 if (readb(vbios) != 0x55 || readb(vbios + 1) != 0xAA) {
0493 return;
0494 }
0495 bd->bios_valid = 1;
0496 get_bios_version(vbios, bd);
0497 get_bios_output(vbios, bd);
0498 get_bios_tvout(vbios, bd);
0499 #if defined(__powerpc__)
0500
0501
0502
0503
0504
0505
0506
0507
0508 for ( pins_offset = 0 ; pins_offset <= 0xFF80 ; pins_offset++ ) {
0509 unsigned char header[3];
0510
0511 header[0] = readb(vbios + pins_offset);
0512 header[1] = readb(vbios + pins_offset + 1);
0513 header[2] = readb(vbios + pins_offset + 2);
0514 if ( (header[0] == 0x2E) && (header[1] == 0x41)
0515 && ((header[2] == 0x40) || (header[2] == 0x80)) ) {
0516 printk(KERN_INFO "PInS data found at offset %u\n",
0517 pins_offset);
0518 get_pins(vbios + pins_offset, bd);
0519 break;
0520 }
0521 }
0522 #else
0523 pins_offset = readb(vbios + 0x7FFC) | (readb(vbios + 0x7FFD) << 8);
0524 if (pins_offset <= 0xFF80) {
0525 get_pins(vbios + pins_offset, bd);
0526 }
0527 #endif
0528 }
0529
0530 static int parse_pins1(struct matrox_fb_info *minfo,
0531 const struct matrox_bios *bd)
0532 {
0533 unsigned int maxdac;
0534
0535 switch (bd->pins[22]) {
0536 case 0: maxdac = 175000; break;
0537 case 1: maxdac = 220000; break;
0538 default: maxdac = 240000; break;
0539 }
0540 if (get_unaligned_le16(bd->pins + 24)) {
0541 maxdac = get_unaligned_le16(bd->pins + 24) * 10;
0542 }
0543 minfo->limits.pixel.vcomax = maxdac;
0544 minfo->values.pll.system = get_unaligned_le16(bd->pins + 28) ?
0545 get_unaligned_le16(bd->pins + 28) * 10 : 50000;
0546
0547 minfo->features.pll.ref_freq = 14318;
0548 minfo->values.reg.mctlwtst = 0x00030101;
0549 return 0;
0550 }
0551
0552 static void default_pins1(struct matrox_fb_info *minfo)
0553 {
0554
0555 minfo->limits.pixel.vcomax = 220000;
0556 minfo->values.pll.system = 50000;
0557 minfo->features.pll.ref_freq = 14318;
0558 minfo->values.reg.mctlwtst = 0x00030101;
0559 }
0560
0561 static int parse_pins2(struct matrox_fb_info *minfo,
0562 const struct matrox_bios *bd)
0563 {
0564 minfo->limits.pixel.vcomax =
0565 minfo->limits.system.vcomax = (bd->pins[41] == 0xFF) ? 230000 : ((bd->pins[41] + 100) * 1000);
0566 minfo->values.reg.mctlwtst = ((bd->pins[51] & 0x01) ? 0x00000001 : 0) |
0567 ((bd->pins[51] & 0x02) ? 0x00000100 : 0) |
0568 ((bd->pins[51] & 0x04) ? 0x00010000 : 0) |
0569 ((bd->pins[51] & 0x08) ? 0x00020000 : 0);
0570 minfo->values.pll.system = (bd->pins[43] == 0xFF) ? 50000 : ((bd->pins[43] + 100) * 1000);
0571 minfo->features.pll.ref_freq = 14318;
0572 return 0;
0573 }
0574
0575 static void default_pins2(struct matrox_fb_info *minfo)
0576 {
0577
0578 minfo->limits.pixel.vcomax =
0579 minfo->limits.system.vcomax = 230000;
0580 minfo->values.reg.mctlwtst = 0x00030101;
0581 minfo->values.pll.system = 50000;
0582 minfo->features.pll.ref_freq = 14318;
0583 }
0584
0585 static int parse_pins3(struct matrox_fb_info *minfo,
0586 const struct matrox_bios *bd)
0587 {
0588 minfo->limits.pixel.vcomax =
0589 minfo->limits.system.vcomax = (bd->pins[36] == 0xFF) ? 230000 : ((bd->pins[36] + 100) * 1000);
0590 minfo->values.reg.mctlwtst = get_unaligned_le32(bd->pins + 48) == 0xFFFFFFFF ?
0591 0x01250A21 : get_unaligned_le32(bd->pins + 48);
0592
0593 minfo->values.reg.memrdbk = ((bd->pins[57] << 21) & 0x1E000000) |
0594 ((bd->pins[57] << 22) & 0x00C00000) |
0595 ((bd->pins[56] << 1) & 0x000001E0) |
0596 ( bd->pins[56] & 0x0000000F);
0597 minfo->values.reg.opt = (bd->pins[54] & 7) << 10;
0598 minfo->values.reg.opt2 = bd->pins[58] << 12;
0599 minfo->features.pll.ref_freq = (bd->pins[52] & 0x20) ? 14318 : 27000;
0600 return 0;
0601 }
0602
0603 static void default_pins3(struct matrox_fb_info *minfo)
0604 {
0605
0606 minfo->limits.pixel.vcomax =
0607 minfo->limits.system.vcomax = 230000;
0608 minfo->values.reg.mctlwtst = 0x01250A21;
0609 minfo->values.reg.memrdbk = 0x00000000;
0610 minfo->values.reg.opt = 0x00000C00;
0611 minfo->values.reg.opt2 = 0x00000000;
0612 minfo->features.pll.ref_freq = 27000;
0613 }
0614
0615 static int parse_pins4(struct matrox_fb_info *minfo,
0616 const struct matrox_bios *bd)
0617 {
0618 minfo->limits.pixel.vcomax = (bd->pins[ 39] == 0xFF) ? 230000 : bd->pins[ 39] * 4000;
0619 minfo->limits.system.vcomax = (bd->pins[ 38] == 0xFF) ? minfo->limits.pixel.vcomax : bd->pins[ 38] * 4000;
0620 minfo->values.reg.mctlwtst = get_unaligned_le32(bd->pins + 71);
0621 minfo->values.reg.memrdbk = ((bd->pins[87] << 21) & 0x1E000000) |
0622 ((bd->pins[87] << 22) & 0x00C00000) |
0623 ((bd->pins[86] << 1) & 0x000001E0) |
0624 ( bd->pins[86] & 0x0000000F);
0625 minfo->values.reg.opt = ((bd->pins[53] << 15) & 0x00400000) |
0626 ((bd->pins[53] << 22) & 0x10000000) |
0627 ((bd->pins[53] << 7) & 0x00001C00);
0628 minfo->values.reg.opt3 = get_unaligned_le32(bd->pins + 67);
0629 minfo->values.pll.system = (bd->pins[ 65] == 0xFF) ? 200000 : bd->pins[ 65] * 4000;
0630 minfo->features.pll.ref_freq = (bd->pins[ 92] & 0x01) ? 14318 : 27000;
0631 return 0;
0632 }
0633
0634 static void default_pins4(struct matrox_fb_info *minfo)
0635 {
0636
0637 minfo->limits.pixel.vcomax =
0638 minfo->limits.system.vcomax = 252000;
0639 minfo->values.reg.mctlwtst = 0x04A450A1;
0640 minfo->values.reg.memrdbk = 0x000000E7;
0641 minfo->values.reg.opt = 0x10000400;
0642 minfo->values.reg.opt3 = 0x0190A419;
0643 minfo->values.pll.system = 200000;
0644 minfo->features.pll.ref_freq = 27000;
0645 }
0646
0647 static int parse_pins5(struct matrox_fb_info *minfo,
0648 const struct matrox_bios *bd)
0649 {
0650 unsigned int mult;
0651
0652 mult = bd->pins[4]?8000:6000;
0653
0654 minfo->limits.pixel.vcomax = (bd->pins[ 38] == 0xFF) ? 600000 : bd->pins[ 38] * mult;
0655 minfo->limits.system.vcomax = (bd->pins[ 36] == 0xFF) ? minfo->limits.pixel.vcomax : bd->pins[ 36] * mult;
0656 minfo->limits.video.vcomax = (bd->pins[ 37] == 0xFF) ? minfo->limits.system.vcomax : bd->pins[ 37] * mult;
0657 minfo->limits.pixel.vcomin = (bd->pins[123] == 0xFF) ? 256000 : bd->pins[123] * mult;
0658 minfo->limits.system.vcomin = (bd->pins[121] == 0xFF) ? minfo->limits.pixel.vcomin : bd->pins[121] * mult;
0659 minfo->limits.video.vcomin = (bd->pins[122] == 0xFF) ? minfo->limits.system.vcomin : bd->pins[122] * mult;
0660 minfo->values.pll.system =
0661 minfo->values.pll.video = (bd->pins[ 92] == 0xFF) ? 284000 : bd->pins[ 92] * 4000;
0662 minfo->values.reg.opt = get_unaligned_le32(bd->pins + 48);
0663 minfo->values.reg.opt2 = get_unaligned_le32(bd->pins + 52);
0664 minfo->values.reg.opt3 = get_unaligned_le32(bd->pins + 94);
0665 minfo->values.reg.mctlwtst = get_unaligned_le32(bd->pins + 98);
0666 minfo->values.reg.memmisc = get_unaligned_le32(bd->pins + 102);
0667 minfo->values.reg.memrdbk = get_unaligned_le32(bd->pins + 106);
0668 minfo->features.pll.ref_freq = (bd->pins[110] & 0x01) ? 14318 : 27000;
0669 minfo->values.memory.ddr = (bd->pins[114] & 0x60) == 0x20;
0670 minfo->values.memory.dll = (bd->pins[115] & 0x02) != 0;
0671 minfo->values.memory.emrswen = (bd->pins[115] & 0x01) != 0;
0672 minfo->values.reg.maccess = minfo->values.memory.emrswen ? 0x00004000 : 0x00000000;
0673 if (bd->pins[115] & 4) {
0674 minfo->values.reg.mctlwtst_core = minfo->values.reg.mctlwtst;
0675 } else {
0676 static const u8 wtst_xlat[] = {
0677 0, 1, 5, 6, 7, 5, 2, 3
0678 };
0679
0680 minfo->values.reg.mctlwtst_core = (minfo->values.reg.mctlwtst & ~7) |
0681 wtst_xlat[minfo->values.reg.mctlwtst & 7];
0682 }
0683 minfo->max_pixel_clock_panellink = bd->pins[47] * 4000;
0684 return 0;
0685 }
0686
0687 static void default_pins5(struct matrox_fb_info *minfo)
0688 {
0689
0690 minfo->limits.pixel.vcomax =
0691 minfo->limits.system.vcomax =
0692 minfo->limits.video.vcomax = 600000;
0693 minfo->limits.pixel.vcomin =
0694 minfo->limits.system.vcomin =
0695 minfo->limits.video.vcomin = 256000;
0696 minfo->values.pll.system =
0697 minfo->values.pll.video = 284000;
0698 minfo->values.reg.opt = 0x404A1160;
0699 minfo->values.reg.opt2 = 0x0000AC00;
0700 minfo->values.reg.opt3 = 0x0090A409;
0701 minfo->values.reg.mctlwtst_core =
0702 minfo->values.reg.mctlwtst = 0x0C81462B;
0703 minfo->values.reg.memmisc = 0x80000004;
0704 minfo->values.reg.memrdbk = 0x01001103;
0705 minfo->features.pll.ref_freq = 27000;
0706 minfo->values.memory.ddr = 1;
0707 minfo->values.memory.dll = 1;
0708 minfo->values.memory.emrswen = 1;
0709 minfo->values.reg.maccess = 0x00004000;
0710 }
0711
0712 static int matroxfb_set_limits(struct matrox_fb_info *minfo,
0713 const struct matrox_bios *bd)
0714 {
0715 unsigned int pins_version;
0716 static const unsigned int pinslen[] = { 64, 64, 64, 128, 128 };
0717
0718 switch (minfo->chip) {
0719 case MGA_2064: default_pins1(minfo); break;
0720 case MGA_2164:
0721 case MGA_1064:
0722 case MGA_1164: default_pins2(minfo); break;
0723 case MGA_G100:
0724 case MGA_G200: default_pins3(minfo); break;
0725 case MGA_G400: default_pins4(minfo); break;
0726 case MGA_G450:
0727 case MGA_G550: default_pins5(minfo); break;
0728 }
0729 if (!bd->bios_valid) {
0730 printk(KERN_INFO "matroxfb: Your Matrox device does not have BIOS\n");
0731 return -1;
0732 }
0733 if (bd->pins_len < 64) {
0734 printk(KERN_INFO "matroxfb: BIOS on your Matrox device does not contain powerup info\n");
0735 return -1;
0736 }
0737 if (bd->pins[0] == 0x2E && bd->pins[1] == 0x41) {
0738 pins_version = bd->pins[5];
0739 if (pins_version < 2 || pins_version > 5) {
0740 printk(KERN_INFO "matroxfb: Unknown version (%u) of powerup info\n", pins_version);
0741 return -1;
0742 }
0743 } else {
0744 pins_version = 1;
0745 }
0746 if (bd->pins_len != pinslen[pins_version - 1]) {
0747 printk(KERN_INFO "matroxfb: Invalid powerup info\n");
0748 return -1;
0749 }
0750 switch (pins_version) {
0751 case 1:
0752 return parse_pins1(minfo, bd);
0753 case 2:
0754 return parse_pins2(minfo, bd);
0755 case 3:
0756 return parse_pins3(minfo, bd);
0757 case 4:
0758 return parse_pins4(minfo, bd);
0759 case 5:
0760 return parse_pins5(minfo, bd);
0761 default:
0762 printk(KERN_DEBUG "matroxfb: Powerup info version %u is not yet supported\n", pins_version);
0763 return -1;
0764 }
0765 }
0766
0767 void matroxfb_read_pins(struct matrox_fb_info *minfo)
0768 {
0769 u32 opt;
0770 u32 biosbase;
0771 u32 fbbase;
0772 struct pci_dev *pdev = minfo->pcidev;
0773
0774 memset(&minfo->bios, 0, sizeof(minfo->bios));
0775 pci_read_config_dword(pdev, PCI_OPTION_REG, &opt);
0776 pci_write_config_dword(pdev, PCI_OPTION_REG, opt | PCI_OPTION_ENABLE_ROM);
0777 pci_read_config_dword(pdev, PCI_ROM_ADDRESS, &biosbase);
0778 pci_read_config_dword(pdev, minfo->devflags.fbResource, &fbbase);
0779 pci_write_config_dword(pdev, PCI_ROM_ADDRESS, (fbbase & PCI_ROM_ADDRESS_MASK) | PCI_ROM_ADDRESS_ENABLE);
0780 parse_bios(vaddr_va(minfo->video.vbase), &minfo->bios);
0781 pci_write_config_dword(pdev, PCI_ROM_ADDRESS, biosbase);
0782 pci_write_config_dword(pdev, PCI_OPTION_REG, opt);
0783 #ifdef CONFIG_X86
0784 if (!minfo->bios.bios_valid) {
0785 unsigned char __iomem* b;
0786
0787 b = ioremap(0x000C0000, 65536);
0788 if (!b) {
0789 printk(KERN_INFO "matroxfb: Unable to map legacy BIOS\n");
0790 } else {
0791 unsigned int ven = readb(b+0x64+0) | (readb(b+0x64+1) << 8);
0792 unsigned int dev = readb(b+0x64+2) | (readb(b+0x64+3) << 8);
0793
0794 if (ven != pdev->vendor || dev != pdev->device) {
0795 printk(KERN_INFO "matroxfb: Legacy BIOS is for %04X:%04X, while this device is %04X:%04X\n",
0796 ven, dev, pdev->vendor, pdev->device);
0797 } else {
0798 parse_bios(b, &minfo->bios);
0799 }
0800 iounmap(b);
0801 }
0802 }
0803 #endif
0804 matroxfb_set_limits(minfo, &minfo->bios);
0805 printk(KERN_INFO "PInS memtype = %u\n",
0806 (minfo->values.reg.opt & 0x1C00) >> 10);
0807 }
0808
0809 EXPORT_SYMBOL(matroxfb_DAC_in);
0810 EXPORT_SYMBOL(matroxfb_DAC_out);
0811 EXPORT_SYMBOL(matroxfb_var2my);
0812 EXPORT_SYMBOL(matroxfb_PLL_calcclock);
0813 EXPORT_SYMBOL(matroxfb_vgaHWinit);
0814 EXPORT_SYMBOL(matroxfb_vgaHWrestore);
0815 EXPORT_SYMBOL(matroxfb_read_pins);
0816
0817 MODULE_AUTHOR("(c) 1999-2002 Petr Vandrovec <vandrove@vc.cvut.cz>");
0818 MODULE_DESCRIPTION("Miscellaneous support for Matrox video cards");
0819 MODULE_LICENSE("GPL");