📄 matroxfb_base.c
字号:
/* * * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200 and G400 * * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz> * * Portions Copyright (c) 2001 Matrox Graphics Inc. * * Version: 1.65 2002/08/14 * * MTRR stuff: 1998 Tom Rini <trini@kernel.crashing.org> * * Contributors: "menion?" <menion@mindless.com> * Betatesting, fixes, ideas * * "Kurt Garloff" <garloff@suse.de> * Betatesting, fixes, ideas, videomodes, videomodes timmings * * "Tom Rini" <trini@kernel.crashing.org> * MTRR stuff, PPC cleanups, betatesting, fixes, ideas * * "Bibek Sahu" <scorpio@dodds.net> * Access device through readb|w|l and write b|w|l * Extensive debugging stuff * * "Daniel Haun" <haund@usa.net> * Testing, hardware cursor fixes * * "Scott Wood" <sawst46+@pitt.edu> * Fixes * * "Gerd Knorr" <kraxel@goldbach.isdn.cs.tu-berlin.de> * Betatesting * * "Kelly French" <targon@hazmat.com> * "Fernando Herrera" <fherrera@eurielec.etsit.upm.es> * Betatesting, bug reporting * * "Pablo Bianucci" <pbian@pccp.com.ar> * Fixes, ideas, betatesting * * "Inaky Perez Gonzalez" <inaky@peloncho.fis.ucm.es> * Fixes, enhandcements, ideas, betatesting * * "Ryuichi Oikawa" <roikawa@rr.iiij4u.or.jp> * PPC betatesting, PPC support, backward compatibility * * "Paul Womar" <Paul@pwomar.demon.co.uk> * "Owen Waller" <O.Waller@ee.qub.ac.uk> * PPC betatesting * * "Thomas Pornin" <pornin@bolet.ens.fr> * Alpha betatesting * * "Pieter van Leuven" <pvl@iae.nl> * "Ulf Jaenicke-Roessler" <ujr@physik.phy.tu-dresden.de> * G100 testing * * "H. Peter Arvin" <hpa@transmeta.com> * Ideas * * "Cort Dougan" <cort@cs.nmt.edu> * CHRP fixes and PReP cleanup * * "Mark Vojkovich" <mvojkovi@ucsd.edu> * G400 support * * "Samuel Hocevar" <sam@via.ecp.fr> * Fixes * * "Anton Altaparmakov" <AntonA@bigfoot.com> * G400 MAX/non-MAX distinction * * "Ken Aaker" <kdaaker@rchland.vnet.ibm.com> * memtype extension (needed for GXT130P RS/6000 adapter) * * "Uns Lider" <unslider@miranda.org> * G100 PLNWT fixes * * "Denis Zaitsev" <zzz@cd-club.ru> * Fixes * * "Mike Pieper" <mike@pieper-family.de> * TVOut enhandcements, V4L2 control interface. * * "Diego Biurrun" <diego@biurrun.de> * DFP testing * * (following author is not in any relation with this code, but his code * is included in this driver) * * Based on framebuffer driver for VBE 2.0 compliant graphic boards * (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de> * * (following author is not in any relation with this code, but his ideas * were used when writting this driver) * * FreeVBE/AF (Matrox), "Shawn Hargreaves" <shawn@talula.demon.co.uk> * *//* make checkconfig does not check included files... */#include <linux/config.h>#include <linux/version.h>#include "matroxfb_base.h"#include "matroxfb_misc.h"#include "matroxfb_accel.h"#include "matroxfb_DAC1064.h"#include "matroxfb_Ti3026.h"#include "matroxfb_maven.h"#include "matroxfb_crtc2.h"#include "matroxfb_g450.h"#include <linux/matroxfb.h>#include <linux/interrupt.h>#include <asm/uaccess.h>#ifdef CONFIG_PPC_PMACunsigned char nvram_read_byte(int);static int default_vmode = VMODE_NVRAM;static int default_cmode = CMODE_NVRAM;#endifstatic void matroxfb_unregister_device(struct matrox_fb_info* minfo);/* --------------------------------------------------------------------- *//* * card parameters *//* --------------------------------------------------------------------- */static struct fb_var_screeninfo vesafb_defined = { 640,480,640,480,/* W,H, W, H (virtual) load xres,xres_virtual*/ 0,0, /* virtual -> visible no offset */ 8, /* depth -> load bits_per_pixel */ 0, /* greyscale ? */ {0,0,0}, /* R */ {0,0,0}, /* G */ {0,0,0}, /* B */ {0,0,0}, /* transparency */ 0, /* standard pixel format */ FB_ACTIVATE_NOW, -1,-1, FB_ACCELF_TEXT, /* accel flags */ 39721L,48L,16L,33L,10L, 96L,2L,~0, /* No sync info */ FB_VMODE_NONINTERLACED, 0, {0,0,0,0,0}};/* --------------------------------------------------------------------- */static void update_crtc2(WPMINFO unsigned int pos) { struct matroxfb_dh_fb_info* info = ACCESS_FBINFO(crtc2.info); /* Make sure that displays are compatible */ if (info && (info->fbcon.var.bits_per_pixel == ACCESS_FBINFO(fbcon).var.bits_per_pixel) && (info->fbcon.var.xres_virtual == ACCESS_FBINFO(fbcon).var.xres_virtual) && (info->fbcon.var.green.length == ACCESS_FBINFO(fbcon).var.green.length) ) { switch (ACCESS_FBINFO(fbcon).var.bits_per_pixel) { case 16: case 32: pos = pos * 8; if (info->interlaced) { mga_outl(0x3C2C, pos); mga_outl(0x3C28, pos + ACCESS_FBINFO(fbcon).var.xres_virtual * ACCESS_FBINFO(fbcon).var.bits_per_pixel / 8); } else { mga_outl(0x3C28, pos); } break; } }}static void matroxfb_crtc1_panpos(WPMINFO2) { if (ACCESS_FBINFO(crtc1.panpos) >= 0) { unsigned long flags; int panpos; matroxfb_DAC_lock_irqsave(flags); panpos = ACCESS_FBINFO(crtc1.panpos); if (panpos >= 0) { unsigned int extvga_reg; ACCESS_FBINFO(crtc1.panpos) = -1; /* No update pending anymore */ extvga_reg = mga_inb(M_EXTVGA_INDEX); mga_setr(M_EXTVGA_INDEX, 0x00, panpos); if (extvga_reg != 0x00) { mga_outb(M_EXTVGA_INDEX, extvga_reg); } } matroxfb_DAC_unlock_irqrestore(flags); }}static irqreturn_t matrox_irq(int irq, void *dev_id, struct pt_regs *fp){ u_int32_t status; int handled = 0; MINFO_FROM(dev_id); status = mga_inl(M_STATUS); if (status & 0x20) { mga_outl(M_ICLEAR, 0x20); ACCESS_FBINFO(crtc1.vsync.cnt)++; matroxfb_crtc1_panpos(PMINFO2); wake_up_interruptible(&ACCESS_FBINFO(crtc1.vsync.wait)); handled = 1; } if (status & 0x200) { mga_outl(M_ICLEAR, 0x200); ACCESS_FBINFO(crtc2.vsync.cnt)++; wake_up_interruptible(&ACCESS_FBINFO(crtc2.vsync.wait)); handled = 1; } return IRQ_RETVAL(handled);}int matroxfb_enable_irq(WPMINFO int reenable) { u_int32_t bm; if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG400) bm = 0x220; else bm = 0x020; if (!test_and_set_bit(0, &ACCESS_FBINFO(irq_flags))) { if (request_irq(ACCESS_FBINFO(pcidev)->irq, matrox_irq, SA_SHIRQ, "matroxfb", MINFO)) { clear_bit(0, &ACCESS_FBINFO(irq_flags)); return -EINVAL; } /* Clear any pending field interrupts */ mga_outl(M_ICLEAR, bm); mga_outl(M_IEN, mga_inl(M_IEN) | bm); } else if (reenable) { u_int32_t ien; ien = mga_inl(M_IEN); if ((ien & bm) != bm) { printk(KERN_DEBUG "matroxfb: someone disabled IRQ [%08X]\n", ien); mga_outl(M_IEN, ien | bm); } } return 0;}static void matroxfb_disable_irq(WPMINFO2) { if (test_and_clear_bit(0, &ACCESS_FBINFO(irq_flags))) { /* Flush pending pan-at-vbl request... */ matroxfb_crtc1_panpos(PMINFO2); if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG400) mga_outl(M_IEN, mga_inl(M_IEN) & ~0x220); else mga_outl(M_IEN, mga_inl(M_IEN) & ~0x20); free_irq(ACCESS_FBINFO(pcidev)->irq, MINFO); }}int matroxfb_wait_for_sync(WPMINFO u_int32_t crtc) { struct matrox_vsync *vs; unsigned int cnt; int ret; switch (crtc) { case 0: vs = &ACCESS_FBINFO(crtc1.vsync); break; case 1: if (ACCESS_FBINFO(devflags.accelerator) != FB_ACCEL_MATROX_MGAG400) { return -ENODEV; } vs = &ACCESS_FBINFO(crtc2.vsync); break; default: return -ENODEV; } ret = matroxfb_enable_irq(PMINFO 0); if (ret) { return ret; } cnt = vs->cnt; ret = wait_event_interruptible_timeout(vs->wait, cnt != vs->cnt, HZ/10); if (ret < 0) { return ret; } if (ret == 0) { matroxfb_enable_irq(PMINFO 1); return -ETIMEDOUT; } return 0;}/* --------------------------------------------------------------------- */static void matrox_pan_var(WPMINFO struct fb_var_screeninfo *var) { unsigned int pos; unsigned short p0, p1, p2;#ifdef CONFIG_FB_MATROX_32MB unsigned int p3;#endif int vbl; unsigned long flags; CRITFLAGS DBG(__FUNCTION__) if (ACCESS_FBINFO(dead)) return; ACCESS_FBINFO(fbcon).var.xoffset = var->xoffset; ACCESS_FBINFO(fbcon).var.yoffset = var->yoffset; pos = (ACCESS_FBINFO(fbcon).var.yoffset * ACCESS_FBINFO(fbcon).var.xres_virtual + ACCESS_FBINFO(fbcon).var.xoffset) * ACCESS_FBINFO(curr.final_bppShift) / 32; pos += ACCESS_FBINFO(curr.ydstorg.chunks); p0 = ACCESS_FBINFO(hw).CRTC[0x0D] = pos & 0xFF; p1 = ACCESS_FBINFO(hw).CRTC[0x0C] = (pos & 0xFF00) >> 8; p2 = ACCESS_FBINFO(hw).CRTCEXT[0] = (ACCESS_FBINFO(hw).CRTCEXT[0] & 0xB0) | ((pos >> 16) & 0x0F) | ((pos >> 14) & 0x40);#ifdef CONFIG_FB_MATROX_32MB p3 = ACCESS_FBINFO(hw).CRTCEXT[8] = pos >> 21;#endif /* FB_ACTIVATE_VBL and we can acquire interrupts? Honor FB_ACTIVATE_VBL then... */ vbl = (var->activate & FB_ACTIVATE_VBL) && (matroxfb_enable_irq(PMINFO 0) == 0); CRITBEGIN matroxfb_DAC_lock_irqsave(flags); mga_setr(M_CRTC_INDEX, 0x0D, p0); mga_setr(M_CRTC_INDEX, 0x0C, p1);#ifdef CONFIG_FB_MATROX_32MB if (ACCESS_FBINFO(devflags.support32MB)) mga_setr(M_EXTVGA_INDEX, 0x08, p3);#endif if (vbl) { ACCESS_FBINFO(crtc1.panpos) = p2; } else { /* Abort any pending change */ ACCESS_FBINFO(crtc1.panpos) = -1; mga_setr(M_EXTVGA_INDEX, 0x00, p2); } matroxfb_DAC_unlock_irqrestore(flags); update_crtc2(PMINFO pos); CRITEND}static void matroxfb_remove(WPMINFO int dummy) { /* Currently we are holding big kernel lock on all dead & usecount updates. * Destroy everything after all users release it. Especially do not unregister * framebuffer and iounmap memory, neither fbmem nor fbcon-cfb* does not check * for device unplugged when in use. * In future we should point mmio.vbase & video.vbase somewhere where we can * write data without causing too much damage... */ ACCESS_FBINFO(dead) = 1; if (ACCESS_FBINFO(usecount)) { /* destroy it later */ return; } matroxfb_unregister_device(MINFO); unregister_framebuffer(&ACCESS_FBINFO(fbcon)); matroxfb_g450_shutdown(PMINFO2);#ifdef CONFIG_MTRR if (ACCESS_FBINFO(mtrr.vram_valid)) mtrr_del(ACCESS_FBINFO(mtrr.vram), ACCESS_FBINFO(video.base), ACCESS_FBINFO(video.len));#endif mga_iounmap(ACCESS_FBINFO(mmio.vbase)); mga_iounmap(ACCESS_FBINFO(video.vbase)); release_mem_region(ACCESS_FBINFO(video.base), ACCESS_FBINFO(video.len_maximum)); release_mem_region(ACCESS_FBINFO(mmio.base), 16384);#ifdef CONFIG_FB_MATROX_MULTIHEAD kfree(minfo);#endif} /* * Open/Release the frame buffer device */static int matroxfb_open(struct fb_info *info, int user){ MINFO_FROM_INFO(info); DBG_LOOP(__FUNCTION__) if (ACCESS_FBINFO(dead)) { return -ENXIO; } ACCESS_FBINFO(usecount)++; if (user) { ACCESS_FBINFO(userusecount)++; } return(0);}static int matroxfb_release(struct fb_info *info, int user){ MINFO_FROM_INFO(info); DBG_LOOP(__FUNCTION__) if (user) { if (0 == --ACCESS_FBINFO(userusecount)) { matroxfb_disable_irq(PMINFO2); } } if (!(--ACCESS_FBINFO(usecount)) && ACCESS_FBINFO(dead)) { matroxfb_remove(PMINFO 0); } return(0);}static int matroxfb_pan_display(struct fb_var_screeninfo *var, struct fb_info* info) { MINFO_FROM_INFO(info); DBG(__FUNCTION__) matrox_pan_var(PMINFO var); return 0;}static int matroxfb_get_final_bppShift(CPMINFO int bpp) { int bppshft2; DBG(__FUNCTION__) bppshft2 = bpp;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -