/* * * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200, G400 and G450. * * (c) 1998-2001 Petr Vandrovec * * Portions Copyright (c) 2001 Matrox Graphics Inc. * * Version: 1.62 2001/11/29 * * See matroxfb_base.c for contributors. * */ /* make checkconfig does not walk through include tree :-( */ #include #include "matroxfb_DAC1064.h" #include "matroxfb_misc.h" #include "matroxfb_accel.h" #include "g450_pll.h" #include #ifdef NEED_DAC1064 #define outDAC1064 matroxfb_DAC_out #define inDAC1064 matroxfb_DAC_in #define DAC1064_OPT_SCLK_PCI 0x00 #define DAC1064_OPT_SCLK_PLL 0x01 #define DAC1064_OPT_SCLK_EXT 0x02 #define DAC1064_OPT_SCLK_MASK 0x03 #define DAC1064_OPT_GDIV1 0x04 /* maybe it is GDIV2 on G100 ?! */ #define DAC1064_OPT_GDIV3 0x00 #define DAC1064_OPT_MDIV1 0x08 #define DAC1064_OPT_MDIV2 0x00 #define DAC1064_OPT_RESERVED 0x10 static void matroxfb_DAC1064_flashcursor(unsigned long ptr) { unsigned long flags; #define minfo ((struct matrox_fb_info*)ptr) matroxfb_DAC_lock_irqsave(flags); outDAC1064(PMINFO M1064_XCURCTRL, inDAC1064(PMINFO M1064_XCURCTRL) ^ M1064_XCURCTRL_DIS ^ M1064_XCURCTRL_XGA); ACCESS_FBINFO(cursor.timer.expires) = jiffies + HZ/2; add_timer(&ACCESS_FBINFO(cursor.timer)); matroxfb_DAC_unlock_irqrestore(flags); #undef minfo } static void matroxfb_DAC1064_createcursor(WPMINFO struct display* p) { vaddr_t cursorbase; u_int32_t xline; unsigned int i; unsigned int h, to; CRITFLAGS if (ACCESS_FBINFO(currcon_display) != p) return; matroxfb_createcursorshape(PMINFO p, p->var.vmode); xline = (~0) << (32 - ACCESS_FBINFO(cursor.w)); cursorbase = ACCESS_FBINFO(video.vbase); h = ACCESS_FBINFO(features.DAC1064.cursorimage); CRITBEGIN #ifdef __BIG_ENDIAN WaitTillIdle(); mga_outl(M_OPMODE, M_OPMODE_32BPP); #endif to = ACCESS_FBINFO(cursor.u); for (i = 0; i < to; i++) { mga_writel(cursorbase, h, 0); mga_writel(cursorbase, h+4, 0); mga_writel(cursorbase, h+8, ~0); mga_writel(cursorbase, h+12, ~0); h += 16; } to = ACCESS_FBINFO(cursor.d); for (; i < to; i++) { mga_writel(cursorbase, h, 0); mga_writel(cursorbase, h+4, xline); mga_writel(cursorbase, h+8, ~0); mga_writel(cursorbase, h+12, ~0); h += 16; } for (; i < 64; i++) { mga_writel(cursorbase, h, 0); mga_writel(cursorbase, h+4, 0); mga_writel(cursorbase, h+8, ~0); mga_writel(cursorbase, h+12, ~0); h += 16; } #ifdef __BIG_ENDIAN mga_outl(M_OPMODE, ACCESS_FBINFO(accel.m_opmode)); #endif CRITEND } static void matroxfb_DAC1064_cursor(struct display* p, int mode, int x, int y) { unsigned long flags; MINFO_FROM_DISP(p); if (ACCESS_FBINFO(currcon_display) != p) return; if (mode == CM_ERASE) { if (ACCESS_FBINFO(cursor.state) != CM_ERASE) { del_timer_sync(&ACCESS_FBINFO(cursor.timer)); matroxfb_DAC_lock_irqsave(flags); ACCESS_FBINFO(cursor.state) = CM_ERASE; outDAC1064(PMINFO M1064_XCURCTRL, M1064_XCURCTRL_DIS); matroxfb_DAC_unlock_irqrestore(flags); } return; } if ((p->conp->vc_cursor_type & CUR_HWMASK) != ACCESS_FBINFO(cursor.type)) matroxfb_DAC1064_createcursor(PMINFO p); x *= fontwidth(p); y *= fontheight(p); y -= p->var.yoffset; if (p->var.vmode & FB_VMODE_DOUBLE) y *= 2; del_timer_sync(&ACCESS_FBINFO(cursor.timer)); matroxfb_DAC_lock_irqsave(flags); if ((x != ACCESS_FBINFO(cursor.x)) || (y != ACCESS_FBINFO(cursor.y)) || ACCESS_FBINFO(cursor.redraw)) { ACCESS_FBINFO(cursor.redraw) = 0; ACCESS_FBINFO(cursor.x) = x; ACCESS_FBINFO(cursor.y) = y; x += 64; y += 64; outDAC1064(PMINFO M1064_XCURCTRL, M1064_XCURCTRL_DIS); mga_outb(M_RAMDAC_BASE+M1064_CURPOSXL, x); mga_outb(M_RAMDAC_BASE+M1064_CURPOSXH, x >> 8); mga_outb(M_RAMDAC_BASE+M1064_CURPOSYL, y); mga_outb(M_RAMDAC_BASE+M1064_CURPOSYH, y >> 8); } ACCESS_FBINFO(cursor.state) = CM_DRAW; if (ACCESS_FBINFO(devflags.blink)) mod_timer(&ACCESS_FBINFO(cursor.timer), jiffies + HZ/2); outDAC1064(PMINFO M1064_XCURCTRL, M1064_XCURCTRL_XGA); matroxfb_DAC_unlock_irqrestore(flags); } static int matroxfb_DAC1064_setfont(struct display* p, int width, int height) { if (p && p->conp) matroxfb_DAC1064_createcursor(PMXINFO(p) p); return 0; } static int DAC1064_selhwcursor(WPMINFO struct display* p) { ACCESS_FBINFO(dispsw.cursor) = matroxfb_DAC1064_cursor; ACCESS_FBINFO(dispsw.set_font) = matroxfb_DAC1064_setfont; return 0; } static void DAC1064_calcclock(CPMINFO unsigned int freq, unsigned int fmax, unsigned int* in, unsigned int* feed, unsigned int* post) { unsigned int fvco; unsigned int p; DBG("DAC1064_calcclock") fvco = PLL_calcclock(PMINFO freq, fmax, in, feed, &p); if (ACCESS_FBINFO(devflags.g450dac)) { if (fvco <= 300000) /* 276-324 */ ; else if (fvco <= 400000) /* 378-438 */ p |= 0x08; else if (fvco <= 550000) /* 540-567 */ p |= 0x10; else if (fvco <= 690000) /* 675-695 */ p |= 0x18; else if (fvco <= 800000) /* 776-803 */ p |= 0x20; else if (fvco <= 891000) /* 891-891 */ p |= 0x28; else if (fvco <= 940000) /* 931-945 */ p |= 0x30; else /* <959 */ p |= 0x38; } else { p = (1 << p) - 1; if (fvco <= 100000) ; else if (fvco <= 140000) p |= 0x08; else if (fvco <= 180000) p |= 0x10; else p |= 0x18; } *post = p; } /* they must be in POS order */ static const unsigned char MGA1064_DAC_regs[] = { M1064_XCURADDL, M1064_XCURADDH, M1064_XCURCTRL, M1064_XCURCOL0RED, M1064_XCURCOL0GREEN, M1064_XCURCOL0BLUE, M1064_XCURCOL1RED, M1064_XCURCOL1GREEN, M1064_XCURCOL1BLUE, M1064_XCURCOL2RED, M1064_XCURCOL2GREEN, M1064_XCURCOL2BLUE, DAC1064_XVREFCTRL, M1064_XMULCTRL, M1064_XPIXCLKCTRL, M1064_XGENCTRL, M1064_XMISCCTRL, M1064_XGENIOCTRL, M1064_XGENIODATA, M1064_XZOOMCTRL, M1064_XSENSETEST, M1064_XCRCBITSEL, M1064_XCOLKEYMASKL, M1064_XCOLKEYMASKH, M1064_XCOLKEYL, M1064_XCOLKEYH }; static const unsigned char MGA1064_DAC[] = { 0x00, 0x00, M1064_XCURCTRL_DIS, 0x00, 0x00, 0x00, /* black */ 0xFF, 0xFF, 0xFF, /* white */ 0xFF, 0x00, 0x00, /* red */ 0x00, 0, M1064_XPIXCLKCTRL_PLL_UP | M1064_XPIXCLKCTRL_EN | M1064_XPIXCLKCTRL_SRC_PLL, M1064_XGENCTRL_VS_0 | M1064_XGENCTRL_ALPHA_DIS | M1064_XGENCTRL_BLACK_0IRE | M1064_XGENCTRL_NO_SYNC_ON_GREEN, M1064_XMISCCTRL_DAC_8BIT, 0x00, 0x00, M1064_XZOOMCTRL_1, M1064_XSENSETEST_BCOMP | M1064_XSENSETEST_GCOMP | M1064_XSENSETEST_RCOMP | M1064_XSENSETEST_PDOWN, 0x00, 0x00, 0x00, 0xFF, 0xFF}; static void DAC1064_setpclk(WPMINFO unsigned long fout) { unsigned int m, n, p; DBG("DAC1064_setpclk") DAC1064_calcclock(PMINFO fout, ACCESS_FBINFO(max_pixel_clock), &m, &n, &p); ACCESS_FBINFO(hw).DACclk[0] = m; ACCESS_FBINFO(hw).DACclk[1] = n; ACCESS_FBINFO(hw).DACclk[2] = p; } static void DAC1064_setmclk(WPMINFO int oscinfo, unsigned long fmem) { u_int32_t mx; struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); DBG("DAC1064_setmclk") if (ACCESS_FBINFO(devflags.noinit)) { /* read MCLK and give up... */ hw->DACclk[3] = inDAC1064(PMINFO DAC1064_XSYSPLLM); hw->DACclk[4] = inDAC1064(PMINFO DAC1064_XSYSPLLN); hw->DACclk[5] = inDAC1064(PMINFO DAC1064_XSYSPLLP); return; } mx = hw->MXoptionReg | 0x00000004; pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, mx); mx &= ~0x000000BB; if (oscinfo & DAC1064_OPT_GDIV1) mx |= 0x00000008; if (oscinfo & DAC1064_OPT_MDIV1) mx |= 0x00000010; if (oscinfo & DAC1064_OPT_RESERVED) mx |= 0x00000080; if ((oscinfo & DAC1064_OPT_SCLK_MASK) == DAC1064_OPT_SCLK_PLL) { /* select PCI clock until we have setup oscilator... */ int clk; unsigned int m, n, p; /* powerup system PLL, select PCI clock */ mx |= 0x00000020; pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, mx); mx &= ~0x00000004; pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, mx); /* !!! you must not access device if MCLK is not running !!! Doing so cause immediate PCI lockup :-( Maybe they should generate ABORT or I/O (parity...) error and Linux should recover from this... (kill driver/process). But world is not perfect... */ /* (bit 2 of PCI_OPTION_REG must be 0... and bits 0,1 must not select PLL... because of PLL can be stopped at this time) */ DAC1064_calcclock(PMINFO fmem, ACCESS_FBINFO(max_pixel_clock), &m, &n, &p); outDAC1064(PMINFO DAC1064_XSYSPLLM, hw->DACclk[3] = m); outDAC1064(PMINFO DAC1064_XSYSPLLN, hw->DACclk[4] = n); outDAC1064(PMINFO DAC1064_XSYSPLLP, hw->DACclk[5] = p); for (clk = 65536; clk; --clk) { if (inDAC1064(PMINFO DAC1064_XSYSPLLSTAT) & 0x40) break; } if (!clk) printk(KERN_ERR "matroxfb: aiee, SYSPLL not locked\n"); /* select PLL */ mx |= 0x00000005; } else { /* select specified system clock source */ mx |= oscinfo & DAC1064_OPT_SCLK_MASK; } pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, mx); mx &= ~0x00000004; pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, mx); hw->MXoptionReg = mx; } void DAC1064_global_init(WPMINFO2) { struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); hw->DACreg[POS1064_XMISCCTRL] &= M1064_XMISCCTRL_DAC_WIDTHMASK; hw->DACreg[POS1064_XMISCCTRL] |= M1064_XMISCCTRL_LUT_EN; hw->DACreg[POS1064_XPIXCLKCTRL] = M1064_XPIXCLKCTRL_PLL_UP | M1064_XPIXCLKCTRL_EN | M1064_XPIXCLKCTRL_SRC_PLL; hw->DACreg[POS1064_XOUTPUTCONN] = 0x01; /* output #1 enabled */ if (ACCESS_FBINFO(output.ph) & MATROXFB_OUTPUT_CONN_SECONDARY) { if (ACCESS_FBINFO(devflags.g450dac)) { hw->DACreg[POS1064_XPIXCLKCTRL] = M1064_XPIXCLKCTRL_PLL_UP | M1064_XPIXCLKCTRL_EN | M1064_XPIXCLKCTRL_SRC_PLL2; hw->DACreg[POS1064_XOUTPUTCONN] = 0x05; /* output #1 enabled; CRTC1 connected to output #2 */ } else { hw->DACreg[POS1064_XPIXCLKCTRL] = M1064_XPIXCLKCTRL_PLL_UP | M1064_XPIXCLKCTRL_EN | M1064_XPIXCLKCTRL_SRC_EXT; hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_MAFC | G400_XMISCCTRL_VDO_MAFC12; } } else if (ACCESS_FBINFO(output.sh) & MATROXFB_OUTPUT_CONN_SECONDARY) { hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_MAFC | G400_XMISCCTRL_VDO_C2_MAFC12; hw->DACreg[POS1064_XOUTPUTCONN] = 0x09; /* output #1 enabled; CRTC2 connected to output #2 */ } else if (ACCESS_FBINFO(output.ph) & MATROXFB_OUTPUT_CONN_DFP) hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_PANELLINK | G400_XMISCCTRL_VDO_MAFC12; else hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_DIS; if ((ACCESS_FBINFO(output.ph) | ACCESS_FBINFO(output.sh)) & MATROXFB_OUTPUT_CONN_PRIMARY) hw->DACreg[POS1064_XMISCCTRL] |= M1064_XMISCCTRL_DAC_EN; } void DAC1064_global_restore(WPMINFO2) { struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); outDAC1064(PMINFO M1064_XPIXCLKCTRL, hw->DACreg[POS1064_XPIXCLKCTRL]); outDAC1064(PMINFO M1064_XMISCCTRL, hw->DACreg[POS1064_XMISCCTRL]); if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG400) { outDAC1064(PMINFO 0x20, 0x04); outDAC1064(PMINFO 0x1F, ACCESS_FBINFO(devflags.dfp_type)); if (ACCESS_FBINFO(devflags.g450dac)) { outDAC1064(PMINFO M1064_XSYNCCTRL, 0xCC); /* only matrox know... */ outDAC1064(PMINFO M1064_XPWRCTRL, 0x1F); /* powerup everything */ outDAC1064(PMINFO M1064_XOUTPUTCONN, hw->DACreg[POS1064_XOUTPUTCONN]); } } } static int DAC1064_init_1(WPMINFO struct my_timming* m, struct display *p) { struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); DBG("DAC1064_init_1") memcpy(hw->DACreg, MGA1064_DAC, sizeof(MGA1064_DAC_regs)); if (p->type == FB_TYPE_TEXT) { hw->DACreg[POS1064_XMISCCTRL] = M1064_XMISCCTRL_DAC_6BIT; hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_8BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED; } else { switch (p->var.bits_per_pixel) { /* case 4: not supported by MGA1064 DAC */ case 8: hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_8BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED; break; case 16: if (p->var.green.length == 5) hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_15BPP_1BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED; else hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_16BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED; break; case 24: hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_24BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED; break; case 32: hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_32BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED; break; default: return 1; /* unsupported depth */ } } DAC1064_global_init(PMINFO2); hw->DACreg[POS1064_XVREFCTRL] = ACCESS_FBINFO(features.DAC1064.xvrefctrl); hw->DACreg[POS1064_XGENCTRL] &= ~M1064_XGENCTRL_SYNC_ON_GREEN_MASK; hw->DACreg[POS1064_XGENCTRL] |= (m->sync & FB_SYNC_ON_GREEN)?M1064_XGENCTRL_SYNC_ON_GREEN:M1064_XGENCTRL_NO_SYNC_ON_GREEN; hw->DACreg[POS1064_XCURADDL] = ACCESS_FBINFO(features.DAC1064.cursorimage) >> 10; hw->DACreg[POS1064_XCURADDH] = ACCESS_FBINFO(features.DAC1064.cursorimage) >> 18; return 0; } static int DAC1064_init_2(WPMINFO struct my_timming* m, struct display* p) { struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); DBG("DAC1064_init_2") if (p->var.bits_per_pixel > 16) { /* 256 entries */ int i; for (i = 0; i < 256; i++) { hw->DACpal[i * 3 + 0] = i; hw->DACpal[i * 3 + 1] = i; hw->DACpal[i * 3 + 2] = i; } } else if (p->var.bits_per_pixel > 8) { if (p->var.green.length == 5) { /* 0..31, 128..159 */ int i; for (i = 0; i < 32; i++) { /* with p15 == 0 */ hw->DACpal[i * 3 + 0] = i << 3; hw->DACpal[i * 3 + 1] = i << 3; hw->DACpal[i * 3 + 2] = i << 3; /* with p15 == 1 */ hw->DACpal[(i + 128) * 3 + 0] = i << 3; hw->DACpal[(i + 128) * 3 + 1] = i << 3; hw->DACpal[(i + 128) * 3 + 2] = i << 3; } } else { int i; for (i = 0; i < 64; i++) { /* 0..63 */ hw->DACpal[i * 3 + 0] = i << 3; hw->DACpal[i * 3 + 1] = i << 2; hw->DACpal[i * 3 + 2] = i << 3; } } } else { memset(hw->DACpal, 0, 768); } return 0; } static void DAC1064_restore_1(WPMINFO2) { struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); CRITFLAGS DBG("DAC1064_restore_1") CRITBEGIN if ((inDAC1064(PMINFO DAC1064_XSYSPLLM) != hw->DACclk[3]) || (inDAC1064(PMINFO DAC1064_XSYSPLLN) != hw->DACclk[4]) || (inDAC1064(PMINFO DAC1064_XSYSPLLP) != hw->DACclk[5])) { outDAC1064(PMINFO DAC1064_XSYSPLLM, hw->DACclk[3]); outDAC1064(PMINFO DAC1064_XSYSPLLN, hw->DACclk[4]); outDAC1064(PMINFO DAC1064_XSYSPLLP, hw->DACclk[5]); } { unsigned int i; for (i = 0; i < sizeof(MGA1064_DAC_regs); i++) { if ((i != POS1064_XPIXCLKCTRL) && (i != POS1064_XMISCCTRL)) outDAC1064(PMINFO MGA1064_DAC_regs[i], hw->DACreg[i]); } } DAC1064_global_restore(PMINFO2); CRITEND }; static void DAC1064_restore_2(WPMINFO struct display* p) { #ifdef DEBUG unsigned int i; #endif DBG("DAC1064_restore_2") matrox_init_putc(PMINFO p, matroxfb_DAC1064_createcursor); #ifdef DEBUG dprintk(KERN_DEBUG "DAC1064regs "); for (i = 0; i < sizeof(MGA1064_DAC_regs); i++) { dprintk("R%02X=%02X ", MGA1064_DAC_regs[i], ACCESS_FBINFO(hw).DACreg[i]); if ((i & 0x7) == 0x7) dprintk("\n" KERN_DEBUG "continuing... "); } dprintk("\n" KERN_DEBUG "DAC1064clk "); for (i = 0; i < 6; i++) dprintk("C%02X=%02X ", i, ACCESS_FBINFO(hw).DACclk[i]); dprintk("\n"); #endif } static int m1064_compute(void* outdev, struct my_timming* m) { #define minfo ((struct matrox_fb_info*)outdev) #ifdef CONFIG_FB_MATROX_G450 if (ACCESS_FBINFO(devflags.g450dac)) { matroxfb_g450_setclk(PMINFO m->pixclock, M_PIXEL_PLL_C); } else #endif { int i; int tmout; CRITFLAGS DAC1064_setpclk(PMINFO m->pixclock); CRITBEGIN for (i = 0; i < 3; i++) outDAC1064(PMINFO M1064_XPIXPLLCM + i, ACCESS_FBINFO(hw).DACclk[i]); for (tmout = 500000; tmout; tmout--) { if (inDAC1064(PMINFO M1064_XPIXPLLSTAT) & 0x40) break; udelay(10); }; CRITEND if (!tmout) printk(KERN_ERR "matroxfb: Pixel PLL not locked after 5 secs\n"); } #undef minfo return 0; } static int m1064_program(void* outdev) { /* nothing, hardware is set in m1064_compute */ return 0; } static int m1064_start(void* outdev) { /* nothing */ return 0; } static void m1064_incuse(void* outdev) { /* nothing yet; MODULE_INC_USE in future... */ } static void m1064_decuse(void* outdev) { /* nothing yet; MODULE_DEC_USE in future... */ } static int m1064_setmode(void* outdev, u_int32_t mode) { if (mode != MATROXFB_OUTPUT_MODE_MONITOR) return -EINVAL; return 0; } static struct matrox_altout m1064 = { m1064_compute, m1064_program, m1064_start, m1064_incuse, m1064_decuse, m1064_setmode }; #endif /* NEED_DAC1064 */ #ifdef CONFIG_FB_MATROX_MYSTIQUE static int MGA1064_init(WPMINFO struct my_timming* m, struct display* p) { struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); DBG("MGA1064_init") if (DAC1064_init_1(PMINFO m, p)) return 1; if (matroxfb_vgaHWinit(PMINFO m, p)) return 1; hw->MiscOutReg = 0xCB; if (m->sync & FB_SYNC_HOR_HIGH_ACT) hw->MiscOutReg &= ~0x40; if (m->sync & FB_SYNC_VERT_HIGH_ACT) hw->MiscOutReg &= ~0x80; if (m->sync & FB_SYNC_COMP_HIGH_ACT) /* should be only FB_SYNC_COMP */ hw->CRTCEXT[3] |= 0x40; if (DAC1064_init_2(PMINFO m, p)) return 1; return 0; } #endif #ifdef CONFIG_FB_MATROX_G100 static int MGAG100_init(WPMINFO struct my_timming* m, struct display* p) { struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); DBG("MGAG100_init") if (DAC1064_init_1(PMINFO m, p)) return 1; hw->MXoptionReg &= ~0x2000; if (matroxfb_vgaHWinit(PMINFO m, p)) return 1; hw->MiscOutReg = 0xEF; if (m->sync & FB_SYNC_HOR_HIGH_ACT) hw->MiscOutReg &= ~0x40; if (m->sync & FB_SYNC_VERT_HIGH_ACT) hw->MiscOutReg &= ~0x80; if (m->sync & FB_SYNC_COMP_HIGH_ACT) /* should be only FB_SYNC_COMP */ hw->CRTCEXT[3] |= 0x40; if (DAC1064_init_2(PMINFO m, p)) return 1; return 0; } #endif /* G100 */ #ifdef CONFIG_FB_MATROX_MYSTIQUE static void MGA1064_ramdac_init(WPMINFO2) { DBG("MGA1064_ramdac_init"); /* ACCESS_FBINFO(features.DAC1064.vco_freq_min) = 120000; */ ACCESS_FBINFO(features.pll.vco_freq_min) = 62000; ACCESS_FBINFO(features.pll.ref_freq) = 14318; ACCESS_FBINFO(features.pll.feed_div_min) = 100; ACCESS_FBINFO(features.pll.feed_div_max) = 127; ACCESS_FBINFO(features.pll.in_div_min) = 1; ACCESS_FBINFO(features.pll.in_div_max) = 31; ACCESS_FBINFO(features.pll.post_shift_max) = 3; ACCESS_FBINFO(features.DAC1064.xvrefctrl) = DAC1064_XVREFCTRL_EXTERNAL; /* maybe cmdline MCLK= ?, doc says gclk=44MHz, mclk=66MHz... it was 55/83 with old values */ DAC1064_setmclk(PMINFO DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV3 | DAC1064_OPT_SCLK_PLL, 133333); } #endif #ifdef CONFIG_FB_MATROX_G100 /* BIOS environ */ static int x7AF4 = 0x10; /* flags, maybe 0x10 = SDRAM, 0x00 = SGRAM??? */ /* G100 wants 0x10, G200 SGRAM does not care... */ #if 0 static int def50 = 0; /* reg50, & 0x0F, & 0x3000 (only 0x0000, 0x1000, 0x2000 (0x3000 disallowed and treated as 0) */ #endif static void MGAG100_progPixClock(CPMINFO int flags, int m, int n, int p) { int reg; int selClk; int clk; DBG("MGAG100_progPixClock") outDAC1064(PMINFO M1064_XPIXCLKCTRL, inDAC1064(PMINFO M1064_XPIXCLKCTRL) | M1064_XPIXCLKCTRL_DIS | M1064_XPIXCLKCTRL_PLL_UP); switch (flags & 3) { case 0: reg = M1064_XPIXPLLAM; break; case 1: reg = M1064_XPIXPLLBM; break; default: reg = M1064_XPIXPLLCM; break; } outDAC1064(PMINFO reg++, m); outDAC1064(PMINFO reg++, n); outDAC1064(PMINFO reg, p); selClk = mga_inb(M_MISC_REG_READ) & ~0xC; /* there should be flags & 0x03 & case 0/1/else */ /* and we should first select source and after that we should wait for PLL */ /* and we are waiting for PLL with oscilator disabled... Is it right? */ switch (flags & 0x03) { case 0x00: break; case 0x01: selClk |= 4; break; default: selClk |= 0x0C; break; } mga_outb(M_MISC_REG, selClk); for (clk = 500000; clk; clk--) { if (inDAC1064(PMINFO M1064_XPIXPLLSTAT) & 0x40) break; udelay(10); }; if (!clk) printk(KERN_ERR "matroxfb: Pixel PLL%c not locked after usual time\n", (reg-M1064_XPIXPLLAM-2)/4 + 'A'); selClk = inDAC1064(PMINFO M1064_XPIXCLKCTRL) & ~M1064_XPIXCLKCTRL_SRC_MASK; switch (flags & 0x0C) { case 0x00: selClk |= M1064_XPIXCLKCTRL_SRC_PCI; break; case 0x04: selClk |= M1064_XPIXCLKCTRL_SRC_PLL; break; default: selClk |= M1064_XPIXCLKCTRL_SRC_EXT; break; } outDAC1064(PMINFO M1064_XPIXCLKCTRL, selClk); outDAC1064(PMINFO M1064_XPIXCLKCTRL, inDAC1064(PMINFO M1064_XPIXCLKCTRL) & ~M1064_XPIXCLKCTRL_DIS); } static void MGAG100_setPixClock(CPMINFO int flags, int freq) { unsigned int m, n, p; DBG("MGAG100_setPixClock") DAC1064_calcclock(PMINFO freq, ACCESS_FBINFO(max_pixel_clock), &m, &n, &p); MGAG100_progPixClock(PMINFO flags, m, n, p); } #endif #ifdef CONFIG_FB_MATROX_MYSTIQUE static int MGA1064_preinit(WPMINFO2) { static const int vxres_mystique[] = { 512, 640, 768, 800, 832, 960, 1024, 1152, 1280, 1600, 1664, 1920, 2048, 0}; struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); DBG("MGA1064_preinit") /* ACCESS_FBINFO(capable.cfb4) = 0; ... preinitialized by 0 */ ACCESS_FBINFO(capable.text) = 1; ACCESS_FBINFO(capable.vxres) = vxres_mystique; ACCESS_FBINFO(features.accel.has_cacheflush) = 1; ACCESS_FBINFO(cursor.timer.function) = matroxfb_DAC1064_flashcursor; ACCESS_FBINFO(primout) = &m1064; if (ACCESS_FBINFO(devflags.noinit)) return 0; /* do not modify settings */ hw->MXoptionReg &= 0xC0000100; hw->MXoptionReg |= 0x00094E20; if (ACCESS_FBINFO(devflags.novga)) hw->MXoptionReg &= ~0x00000100; if (ACCESS_FBINFO(devflags.nobios)) hw->MXoptionReg &= ~0x40000000; if (ACCESS_FBINFO(devflags.nopciretry)) hw->MXoptionReg |= 0x20000000; pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg); mga_setr(M_SEQ_INDEX, 0x01, 0x20); mga_outl(M_CTLWTST, 0x00000000); udelay(200); mga_outl(M_MACCESS, 0x00008000); udelay(100); mga_outl(M_MACCESS, 0x0000C000); return 0; } static void MGA1064_reset(WPMINFO2) { DBG("MGA1064_reset"); ACCESS_FBINFO(features.DAC1064.cursorimage) = ACCESS_FBINFO(video.len_usable) - 1024; if (ACCESS_FBINFO(devflags.hwcursor)) ACCESS_FBINFO(video.len_usable) -= 1024; matroxfb_fastfont_init(MINFO); MGA1064_ramdac_init(PMINFO2); } #endif #ifdef CONFIG_FB_MATROX_G100 static void g450_mclk_init(WPMINFO2) { /* switch all clocks to PCI source */ pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg | 4); pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION3_REG, ACCESS_FBINFO(values).reg.opt3 & ~0x00300C03); pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg); if (((ACCESS_FBINFO(values).reg.opt3 & 0x000003) == 0x000003) || ((ACCESS_FBINFO(values).reg.opt3 & 0x000C00) == 0x000C00) || ((ACCESS_FBINFO(values).reg.opt3 & 0x300000) == 0x300000)) { matroxfb_g450_setclk(PMINFO ACCESS_FBINFO(values.pll.video), M_VIDEO_PLL); } else { /* slow down video clocks... */ matroxfb_g450_setclk(PMINFO 0, M_VIDEO_PLL); } matroxfb_g450_setclk(PMINFO ACCESS_FBINFO(values.pll.system), M_SYSTEM_PLL); /* switch clocks to their real PLL source(s) */ pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg | 4); pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION3_REG, ACCESS_FBINFO(values).reg.opt3); pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg); } static void g450_memory_init(WPMINFO2) { /* disable memory refresh */ ACCESS_FBINFO(hw).MXoptionReg &= ~0x001F8000; pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg); /* set memory interface parameters */ ACCESS_FBINFO(hw).MXoptionReg &= ~0x00207E00; ACCESS_FBINFO(hw).MXoptionReg |= 0x00207E00 & ACCESS_FBINFO(values).reg.opt; pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg); pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, ACCESS_FBINFO(values).reg.opt2); mga_outl(M_CTLWTST, ACCESS_FBINFO(values).reg.mctlwtst); /* first set up memory interface with disabled memory interface clocks */ pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_MEMMISC_REG, ACCESS_FBINFO(values).reg.memmisc & ~0x80000000U); mga_outl(M_MEMRDBK, ACCESS_FBINFO(values).reg.memrdbk); mga_outl(M_MACCESS, ACCESS_FBINFO(values).reg.maccess); /* start memory clocks */ pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_MEMMISC_REG, ACCESS_FBINFO(values).reg.memmisc | 0x80000000U); udelay(200); if (ACCESS_FBINFO(values).memory.ddr && (!ACCESS_FBINFO(values).memory.emrswen || !ACCESS_FBINFO(values).memory.dll)) { mga_outl(M_MEMRDBK, ACCESS_FBINFO(values).reg.memrdbk & ~0x1000); } mga_outl(M_MACCESS, ACCESS_FBINFO(values).reg.maccess | 0x8000); udelay(200); ACCESS_FBINFO(hw).MXoptionReg |= 0x001F8000 & ACCESS_FBINFO(values).reg.opt; pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg); /* value is written to memory chips only if old != new */ mga_outl(M_PLNWT, 0); mga_outl(M_PLNWT, ~0); if (ACCESS_FBINFO(values).reg.mctlwtst != ACCESS_FBINFO(values).reg.mctlwtst_core) { mga_outl(M_CTLWTST, ACCESS_FBINFO(values).reg.mctlwtst_core); } } static void g450_preinit(WPMINFO2) { u_int32_t c2ctl; u_int8_t curctl; u_int8_t c1ctl; /* ACCESS_FBINFO(hw).MXoptionReg = minfo->values.reg.opt; */ ACCESS_FBINFO(hw).MXoptionReg &= 0xC0000100; ACCESS_FBINFO(hw).MXoptionReg |= 0x00000020; if (ACCESS_FBINFO(devflags.novga)) ACCESS_FBINFO(hw).MXoptionReg &= ~0x00000100; if (ACCESS_FBINFO(devflags.nobios)) ACCESS_FBINFO(hw).MXoptionReg &= ~0x40000000; if (ACCESS_FBINFO(devflags.nopciretry)) ACCESS_FBINFO(hw).MXoptionReg |= 0x20000000; ACCESS_FBINFO(hw).MXoptionReg |= ACCESS_FBINFO(values).reg.opt & 0x03400040; pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg); /* Init system clocks */ /* stop crtc2 */ c2ctl = mga_inl(M_C2CTL); mga_outl(M_C2CTL, c2ctl & ~1); /* stop cursor */ curctl = inDAC1064(PMINFO M1064_XCURCTRL); outDAC1064(PMINFO M1064_XCURCTRL, 0); /* stop crtc1 */ c1ctl = mga_readr(M_SEQ_INDEX, 1); mga_setr(M_SEQ_INDEX, 1, c1ctl | 0x20); g450_mclk_init(PMINFO2); g450_memory_init(PMINFO2); /* set legacy VGA clock sources for DOSEmu or VMware... */ matroxfb_g450_setclk(PMINFO 25175, M_PIXEL_PLL_A); matroxfb_g450_setclk(PMINFO 28322, M_PIXEL_PLL_B); /* restore crtc1 */ mga_setr(M_SEQ_INDEX, 1, c1ctl); /* restore cursor */ outDAC1064(PMINFO M1064_XCURCTRL, curctl); /* restore crtc2 */ mga_outl(M_C2CTL, c2ctl); return; } static int MGAG100_preinit(WPMINFO2) { static const int vxres_g100[] = { 512, 640, 768, 800, 832, 960, 1024, 1152, 1280, 1600, 1664, 1920, 2048, 0}; struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); u_int32_t reg50; #if 0 u_int32_t q; #endif DBG("MGAG100_preinit") /* there are some instabilities if in_div > 19 && vco < 61000 */ if (ACCESS_FBINFO(devflags.g450dac)) { ACCESS_FBINFO(features.pll.vco_freq_min) = 130000; /* my sample: >118 */ } else { ACCESS_FBINFO(features.pll.vco_freq_min) = 62000; } if (!ACCESS_FBINFO(features.pll.ref_freq)) { ACCESS_FBINFO(features.pll.ref_freq) = 27000; } ACCESS_FBINFO(features.pll.feed_div_min) = 7; ACCESS_FBINFO(features.pll.feed_div_max) = 127; ACCESS_FBINFO(features.pll.in_div_min) = 1; ACCESS_FBINFO(features.pll.in_div_max) = 31; ACCESS_FBINFO(features.pll.post_shift_max) = 3; ACCESS_FBINFO(features.DAC1064.xvrefctrl) = DAC1064_XVREFCTRL_G100_DEFAULT; /* ACCESS_FBINFO(capable.cfb4) = 0; ... preinitialized by 0 */ ACCESS_FBINFO(capable.text) = 1; ACCESS_FBINFO(capable.vxres) = vxres_g100; ACCESS_FBINFO(features.accel.has_cacheflush) = 1; ACCESS_FBINFO(cursor.timer.function) = matroxfb_DAC1064_flashcursor; ACCESS_FBINFO(capable.plnwt) = ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG100 ? ACCESS_FBINFO(devflags.sgram) : 1; ACCESS_FBINFO(primout) = &m1064; if (ACCESS_FBINFO(devflags.g450dac)) { /* we must do this always, BIOS does not do it for us and accelerator dies without it */ mga_outl(0x1C0C, 0); } if (ACCESS_FBINFO(devflags.noinit)) return 0; if (ACCESS_FBINFO(devflags.g450dac)) { g450_preinit(PMINFO2); return 0; } hw->MXoptionReg &= 0xC0000100; hw->MXoptionReg |= 0x00000020; if (ACCESS_FBINFO(devflags.novga)) hw->MXoptionReg &= ~0x00000100; if (ACCESS_FBINFO(devflags.nobios)) hw->MXoptionReg &= ~0x40000000; if (ACCESS_FBINFO(devflags.nopciretry)) hw->MXoptionReg |= 0x20000000; pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg); DAC1064_setmclk(PMINFO DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV3 | DAC1064_OPT_SCLK_PCI, 133333); if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG100) { pci_read_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, ®50); reg50 &= ~0x3000; pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, reg50); hw->MXoptionReg |= 0x1080; pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg); mga_outl(M_CTLWTST, 0x00000300); /* mga_outl(M_CTLWTST, 0x03258A31); */ udelay(100); mga_outb(0x1C05, 0x00); mga_outb(0x1C05, 0x80); udelay(100); mga_outb(0x1C05, 0x40); mga_outb(0x1C05, 0xC0); udelay(100); reg50 &= ~0xFF; reg50 |= 0x07; pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, reg50); /* it should help with G100 */ mga_outb(M_GRAPHICS_INDEX, 6); mga_outb(M_GRAPHICS_DATA, (mga_inb(M_GRAPHICS_DATA) & 3) | 4); mga_setr(M_EXTVGA_INDEX, 0x03, 0x81); mga_setr(M_EXTVGA_INDEX, 0x04, 0x00); mga_writeb(ACCESS_FBINFO(video.vbase), 0x0000, 0xAA); mga_writeb(ACCESS_FBINFO(video.vbase), 0x0800, 0x55); mga_writeb(ACCESS_FBINFO(video.vbase), 0x4000, 0x55); #if 0 if (mga_readb(ACCESS_FBINFO(video.vbase), 0x0000) != 0xAA) { hw->MXoptionReg &= ~0x1000; } #endif hw->MXoptionReg |= 0x00078020; } else if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG200) { pci_read_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, ®50); reg50 &= ~0x3000; pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, reg50); if (ACCESS_FBINFO(devflags.memtype) == -1) hw->MXoptionReg |= ACCESS_FBINFO(values).reg.opt & 0x1C00; else hw->MXoptionReg |= (ACCESS_FBINFO(devflags.memtype) & 7) << 10; if (ACCESS_FBINFO(devflags.sgram)) hw->MXoptionReg |= 0x4000; mga_outl(M_CTLWTST, ACCESS_FBINFO(values).reg.mctlwtst); mga_outl(M_MEMRDBK, ACCESS_FBINFO(values).reg.memrdbk); udelay(200); mga_outl(M_MACCESS, 0x00000000); mga_outl(M_MACCESS, 0x00008000); udelay(100); mga_outw(M_MEMRDBK, ACCESS_FBINFO(values).reg.memrdbk); hw->MXoptionReg |= 0x00078020; } else { pci_read_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, ®50); reg50 &= ~0x00000100; reg50 |= 0x00000000; pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, reg50); if (ACCESS_FBINFO(devflags.memtype) == -1) ACCESS_FBINFO(devflags.memtype) = 0; hw->MXoptionReg |= (ACCESS_FBINFO(devflags.memtype) & 7) << 10; if (ACCESS_FBINFO(devflags.sgram)) hw->MXoptionReg |= 0x4000; mga_outl(M_CTLWTST, 0x042450A1); mga_outl(M_MEMRDBK, 0x00000108); udelay(200); mga_outl(M_MACCESS, 0x00000000); mga_outl(M_MACCESS, 0x00008000); udelay(100); mga_outl(M_MEMRDBK, 0x00000108); hw->MXoptionReg |= 0x00040020; } pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg); return 0; } static void MGAG100_reset(WPMINFO2) { u_int8_t b; struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); DBG("MGAG100_reset") ACCESS_FBINFO(features.DAC1064.cursorimage) = ACCESS_FBINFO(video.len_usable) - 1024; if (ACCESS_FBINFO(devflags.hwcursor)) ACCESS_FBINFO(video.len_usable) -= 1024; matroxfb_fastfont_init(MINFO); { #ifdef G100_BROKEN_IBM_82351 u_int32_t d; find 1014/22 (IBM/82351); /* if found and bridging Matrox, do some strange stuff */ pci_read_config_byte(ibm, PCI_SECONDARY_BUS, &b); if (b == ACCESS_FBINFO(pcidev)->bus->number) { pci_write_config_byte(ibm, PCI_COMMAND+1, 0); /* disable back-to-back & SERR */ pci_write_config_byte(ibm, 0x41, 0xF4); /* ??? */ pci_write_config_byte(ibm, PCI_IO_BASE, 0xF0); /* ??? */ pci_write_config_byte(ibm, PCI_IO_LIMIT, 0x00); /* ??? */ } #endif if (!ACCESS_FBINFO(devflags.noinit)) { if (x7AF4 & 8) { hw->MXoptionReg |= 0x40; /* FIXME... */ pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg); } mga_setr(M_EXTVGA_INDEX, 0x06, 0x50); } } if (ACCESS_FBINFO(devflags.g450dac)) { /* either leave MCLK as is... or they were set in preinit */ hw->DACclk[3] = inDAC1064(PMINFO DAC1064_XSYSPLLM); hw->DACclk[4] = inDAC1064(PMINFO DAC1064_XSYSPLLN); hw->DACclk[5] = inDAC1064(PMINFO DAC1064_XSYSPLLP); } else { DAC1064_setmclk(PMINFO DAC1064_OPT_RESERVED | DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV1 | DAC1064_OPT_SCLK_PLL, 133333); } if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG400) { if (ACCESS_FBINFO(devflags.dfp_type) == -1) { ACCESS_FBINFO(devflags.dfp_type) = inDAC1064(PMINFO 0x1F); } } if (ACCESS_FBINFO(devflags.noinit)) return; if (ACCESS_FBINFO(devflags.g450dac)) { } else { MGAG100_setPixClock(PMINFO 4, 25175); MGAG100_setPixClock(PMINFO 5, 28322); if (x7AF4 & 0x10) { b = inDAC1064(PMINFO M1064_XGENIODATA) & ~1; outDAC1064(PMINFO M1064_XGENIODATA, b); b = inDAC1064(PMINFO M1064_XGENIOCTRL) | 1; outDAC1064(PMINFO M1064_XGENIOCTRL, b); } } } #endif #ifdef CONFIG_FB_MATROX_MYSTIQUE static void MGA1064_restore(WPMINFO struct display* p) { int i; struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); CRITFLAGS DBG("MGA1064_restore") CRITBEGIN pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg); mga_outb(M_IEN, 0x00); mga_outb(M_CACHEFLUSH, 0x00); CRITEND DAC1064_restore_1(PMINFO2); matroxfb_vgaHWrestore(PMINFO2); for (i = 0; i < 6; i++) mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]); DAC1064_restore_2(PMINFO p); } #endif #ifdef CONFIG_FB_MATROX_G100 static void MGAG100_restore(WPMINFO struct display* p) { int i; struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); CRITFLAGS DBG("MGAG100_restore") CRITBEGIN pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg); CRITEND DAC1064_restore_1(PMINFO2); matroxfb_vgaHWrestore(PMINFO2); #ifdef CONFIG_FB_MATROX_32MB if (ACCESS_FBINFO(devflags.support32MB)) mga_setr(M_EXTVGA_INDEX, 8, hw->CRTCEXT[8]); #endif for (i = 0; i < 6; i++) mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]); DAC1064_restore_2(PMINFO p); } #endif #ifdef CONFIG_FB_MATROX_MYSTIQUE struct matrox_switch matrox_mystique = { MGA1064_preinit, MGA1064_reset, MGA1064_init, MGA1064_restore, DAC1064_selhwcursor }; EXPORT_SYMBOL(matrox_mystique); #endif #ifdef CONFIG_FB_MATROX_G100 struct matrox_switch matrox_G100 = { MGAG100_preinit, MGAG100_reset, MGAG100_init, MGAG100_restore, DAC1064_selhwcursor }; EXPORT_SYMBOL(matrox_G100); #endif #ifdef NEED_DAC1064 EXPORT_SYMBOL(DAC1064_global_init); EXPORT_SYMBOL(DAC1064_global_restore); #endif MODULE_LICENSE("GPL");