📄 matroxfb_dac1064.c
字号:
break; case MATROXFB_SRC_NONE:#if 0 /* HELP! If we boot without DFP connected to DVI, we can poweroff TMDS. But if we boot with DFP connected, TMDS generated clocks are used instead of ALL pixclocks available... If someone knows which register handles it, please reveal this secret to me... */ hw->DACreg[POS1064_XPWRCTRL] &= ~0x04; /* Poweroff TMDS */#endif break; } /* Now set timming related variables... */ g450_set_plls(PMINFO2); } else#endif { if (ACCESS_FBINFO(outputs[1]).src == MATROXFB_SRC_CRTC1) { 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(outputs[1]).src == MATROXFB_SRC_CRTC2) { hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_MAFC | G400_XMISCCTRL_VDO_C2_MAFC12; } else if (ACCESS_FBINFO(outputs[2]).src == MATROXFB_SRC_CRTC1) hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_PANELLINK | G400_XMISCCTRL_VDO_MAFC12; else hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_DIS; if (ACCESS_FBINFO(outputs[0]).src != MATROXFB_SRC_NONE) 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); outDAC1064(PMINFO M1064_XPWRCTRL, hw->DACreg[POS1064_XPWRCTRL]); outDAC1064(PMINFO M1064_XPANMODE, hw->DACreg[POS1064_XPANMODE]); 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 */ } } 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; DAC1064_global_init(PMINFO2); 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* out, struct my_timming* m) {#define minfo ((struct matrox_fb_info*)out) { 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 struct matrox_altout m1064 = { .owner = THIS_MODULE, .name = "Primary output", .compute = m1064_compute,};#ifdef CONFIG_FB_MATROX_G450static int g450_compute(void* out, struct my_timming* m) {#define minfo ((struct matrox_fb_info*)out) if (m->mnp < 0) { m->mnp = matroxfb_g450_setclk(PMINFO m->pixclock, (m->crtc == MATROXFB_SRC_CRTC1) ? M_PIXEL_PLL_C : M_VIDEO_PLL); if (m->mnp >= 0) { m->pixclock = g450_mnp2f(PMINFO m->mnp); } }#undef minfo return 0;}static struct matrox_altout g450out = { .owner = THIS_MODULE, .name = "Primary output", .compute = g450_compute,};#endif#endif /* NEED_DAC1064 */#ifdef CONFIG_FB_MATROX_MYSTIQUEstatic 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_G100static 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_MYSTIQUEstatic 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 0static int def50 = 0; /* reg50, & 0x0F, & 0x3000 (only 0x0000, 0x1000, 0x2000 (0x3000 disallowed and treated as 0) */#endifstatic 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_MYSTIQUEstatic 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(outputs[0]).output = &m1064; ACCESS_FBINFO(outputs[0]).src = MATROXFB_SRC_CRTC1; ACCESS_FBINFO(outputs[0]).data = MINFO; ACCESS_FBINFO(outputs[0]).mode = MATROXFB_OUTPUT_MODE_MONITOR; 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -