📄 matroxfb_base.c
字号:
/* * * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200 and G400 * * (c) 1998-2001 Petr Vandrovec <vandrove@vc.cvut.cz> * * Version: 1.54 2001/09/09 * * 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 * * (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 "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 <linux/matroxfb.h>#include <asm/uaccess.h>#ifdef CONFIG_PPCunsigned 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);int matroxfb_switch(int con, struct fb_info *info);/* --------------------------------------------------------------------- *//* * 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 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 struct display *disp; CRITFLAGS DBG("matrox_pan_var") if (ACCESS_FBINFO(dead)) return; disp = ACCESS_FBINFO(currcon_display); if (disp->type == FB_TYPE_TEXT) { pos = var->yoffset / fontheight(disp) * disp->next_line / ACCESS_FBINFO(devflags.textstep) + var->xoffset / (fontwidth(disp)?fontwidth(disp):8); } else { pos = (var->yoffset * var->xres_virtual + var->xoffset) * ACCESS_FBINFO(curr.final_bppShift) / 32; pos += ACCESS_FBINFO(curr.ydstorg.chunks); } p0 = ACCESS_FBINFO(currenthw)->CRTC[0x0D] = pos & 0xFF; p1 = ACCESS_FBINFO(currenthw)->CRTC[0x0C] = (pos & 0xFF00) >> 8; p2 = ACCESS_FBINFO(currenthw)->CRTCEXT[0] = (ACCESS_FBINFO(currenthw)->CRTCEXT[0] & 0xB0) | ((pos >> 16) & 0x0F) | ((pos >> 14) & 0x40);#ifdef CONFIG_FB_MATROX_32MB p3 = ACCESS_FBINFO(currenthw)->CRTCEXT[8] = pos >> 21;#endif CRITBEGIN 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 mga_setr(M_EXTVGA_INDEX, 0x00, p2); 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)); del_timer_sync(&ACCESS_FBINFO(cursor.timer));#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(ACCESS_FBINFO(fbcon.disp)); kfree(minfo);#endif} /* * Open/Release the frame buffer device */static int matroxfb_open(struct fb_info *info, int user){#define minfo ((struct matrox_fb_info*)info) DBG_LOOP("matroxfb_open") if (ACCESS_FBINFO(dead)) { return -ENXIO; } ACCESS_FBINFO(usecount)++;#undef minfo return(0);}static int matroxfb_release(struct fb_info *info, int user){#define minfo ((struct matrox_fb_info*)info) DBG_LOOP("matroxfb_release") if (!(--ACCESS_FBINFO(usecount)) && ACCESS_FBINFO(dead)) { matroxfb_remove(PMINFO 0); }#undef minfo return(0);}static int matroxfb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info* info) {#define minfo ((struct matrox_fb_info*)info) DBG("matroxfb_pan_display") if (var->vmode & FB_VMODE_YWRAP) { if (var->yoffset < 0 || var->yoffset >= fb_display[con].var.yres_virtual || var->xoffset) return -EINVAL; } else { if (var->xoffset+fb_display[con].var.xres > fb_display[con].var.xres_virtual || var->yoffset+fb_display[con].var.yres > fb_display[con].var.yres_virtual) return -EINVAL; } if (con == ACCESS_FBINFO(currcon)) matrox_pan_var(PMINFO var); fb_display[con].var.xoffset = var->xoffset; fb_display[con].var.yoffset = var->yoffset; if (var->vmode & FB_VMODE_YWRAP) fb_display[con].var.vmode |= FB_VMODE_YWRAP; else fb_display[con].var.vmode &= ~FB_VMODE_YWRAP; return 0;#undef minfo}static int matroxfb_updatevar(int con, struct fb_info *info){#define minfo ((struct matrox_fb_info*)info) DBG("matroxfb_updatevar"); matrox_pan_var(PMINFO &fb_display[con].var); return 0;#undef minfo}static int matroxfb_get_final_bppShift(CPMINFO int bpp) { int bppshft2; DBG("matroxfb_get_final_bppShift") bppshft2 = bpp; if (!bppshft2) { return 8; } if (isInterleave(MINFO)) bppshft2 >>= 1; if (ACCESS_FBINFO(devflags.video64bits)) bppshft2 >>= 1; return bppshft2;}static int matroxfb_test_and_set_rounding(CPMINFO int xres, int bpp) { int over; int rounding; DBG("matroxfb_test_and_set_rounding") switch (bpp) { case 0: return xres; case 4: rounding = 128; break; case 8: rounding = 64; /* doc says 64; 32 is OK for G400 */ break; case 16: rounding = 32; break; case 24: rounding = 64; /* doc says 64; 32 is OK for G400 */ break; default: rounding = 16; /* on G400, 16 really does not work */ if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG400) rounding = 32; break; } if (isInterleave(MINFO)) { rounding *= 2; } over = xres % rounding; if (over) xres += rounding-over; return xres;}static int matroxfb_pitch_adjust(CPMINFO int xres, int bpp) { const int* width; int xres_new; DBG("matroxfb_pitch_adjust") if (!bpp) return xres; width = ACCESS_FBINFO(capable.vxres); if (ACCESS_FBINFO(devflags.precise_width)) { while (*width) { if ((*width >= xres) && (matroxfb_test_and_set_rounding(PMINFO *width, bpp) == *width)) { break; } width++; } xres_new = *width; } else { xres_new = matroxfb_test_and_set_rounding(PMINFO xres, bpp); } if (!xres_new) return 0; if (xres != xres_new) { printk(KERN_INFO "matroxfb: cannot set xres to %d, rounded up to %d\n", xres, xres_new); } return xres_new;}static int matroxfb_get_cmap_len(struct fb_var_screeninfo *var) { DBG("matroxfb_get_cmap_len") switch (var->bits_per_pixel) {#ifdef FBCON_HAS_VGATEXT case 0: return 16; /* pseudocolor... 16 entries HW palette */#endif#ifdef FBCON_HAS_CFB4 case 4: return 16; /* pseudocolor... 16 entries HW palette */#endif#ifdef FBCON_HAS_CFB8 case 8: return 256; /* pseudocolor... 256 entries HW palette */#endif#ifdef FBCON_HAS_CFB16 case 16: return 16; /* directcolor... 16 entries SW palette */ /* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */#endif#ifdef FBCON_HAS_CFB24 case 24: return 16; /* directcolor... 16 entries SW palette */ /* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */#endif#ifdef FBCON_HAS_CFB32 case 32: return 16; /* directcolor... 16 entries SW palette */ /* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */#endif } return 16; /* return something reasonable... or panic()? */}static int matroxfb_decode_var(CPMINFO struct display* p, struct fb_var_screeninfo *var, int *visual, int *video_cmap_len, unsigned int* ydstorg) { unsigned int vramlen; unsigned int memlen; DBG("matroxfb_decode_var") switch (var->bits_per_pixel) {#ifdef FBCON_HAS_VGATEXT case 0: if (!ACCESS_FBINFO(capable.text)) return -EINVAL; break;#endif#ifdef FBCON_HAS_CFB4 case 4: if (!ACCESS_FBINFO(capable.cfb4)) return -EINVAL; break;#endif#ifdef FBCON_HAS_CFB8 case 8: break;#endif#ifdef FBCON_HAS_CFB16 case 16: break;#endif#ifdef FBCON_HAS_CFB24 case 24: break;#endif#ifdef FBCON_HAS_CFB32 case 32: break;#endif default: return -EINVAL; } *ydstorg = 0; vramlen = ACCESS_FBINFO(video.len_usable); if (var->yres_virtual < var->yres) var->yres_virtual = var->yres; if (var->xres_virtual < var->xres)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -