⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fbdev.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * linux/drivers/video/riva/fbdev.c - nVidia RIVA 128/TNT/TNT2 fb driver * * Maintained by Ani Joshi <ajoshi@shell.unixbox.com> * * Copyright 1999-2000 Jeff Garzik * * Contributors: * *	Ani Joshi:  Lots of debugging and cleanup work, really helped *	get the driver going * *	Ferenc Bakonyi:  Bug fixes, cleanup, modularization * *	Jindrich Makovicka:  Accel code help, hw cursor, mtrr * *	Paul Richards:  Bug fixes, updates * * Initial template from skeletonfb.c, created 28 Dec 1997 by Geert Uytterhoeven * Includes riva_hw.c from nVidia, see copyright below. * KGI code provided the basis for state storage, init, and mode switching. * * This file is subject to the terms and conditions of the GNU General Public * License.  See the file COPYING in the main directory of this archive * for more details. * * Known bugs and issues: *	restoring text mode fails *	doublescan modes are broken */#include <linux/module.h>#include <linux/kernel.h>#include <linux/errno.h>#include <linux/string.h>#include <linux/mm.h>#include <linux/slab.h>#include <linux/delay.h>#include <linux/fb.h>#include <linux/init.h>#include <linux/pci.h>#include <linux/backlight.h>#include <linux/bitrev.h>#ifdef CONFIG_MTRR#include <asm/mtrr.h>#endif#ifdef CONFIG_PPC_OF#include <asm/prom.h>#include <asm/pci-bridge.h>#endif#ifdef CONFIG_PMAC_BACKLIGHT#include <asm/machdep.h>#include <asm/backlight.h>#endif#include "rivafb.h"#include "nvreg.h"/* version number of this driver */#define RIVAFB_VERSION "0.9.5b"/* ------------------------------------------------------------------------- * * * various helpful macros and constants * * ------------------------------------------------------------------------- */#ifdef CONFIG_FB_RIVA_DEBUG#define NVTRACE          printk#else#define NVTRACE          if(0) printk#endif#define NVTRACE_ENTER(...)  NVTRACE("%s START\n", __func__)#define NVTRACE_LEAVE(...)  NVTRACE("%s END\n", __func__)#ifdef CONFIG_FB_RIVA_DEBUG#define assert(expr) \	if(!(expr)) { \	printk( "Assertion failed! %s,%s,%s,line=%d\n",\	#expr,__FILE__,__func__,__LINE__); \	BUG(); \	}#else#define assert(expr)#endif#define PFX "rivafb: "/* macro that allows you to set overflow bits */#define SetBitField(value,from,to) SetBF(to,GetBF(value,from))#define SetBit(n)		(1<<(n))#define Set8Bits(value)		((value)&0xff)/* HW cursor parameters */#define MAX_CURS		32/* ------------------------------------------------------------------------- * * * prototypes * * ------------------------------------------------------------------------- */static int rivafb_blank(int blank, struct fb_info *info);/* ------------------------------------------------------------------------- * * * card identification * * ------------------------------------------------------------------------- */static struct pci_device_id rivafb_pci_tbl[] = {	{ PCI_VENDOR_ID_NVIDIA_SGS, PCI_DEVICE_ID_NVIDIA_SGS_RIVA128,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_TNT,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_TNT2,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_UTNT2,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_VTNT2,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_UVTNT2,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_ITNT2,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_SDR,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_DDR,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX2,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GO,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO2_MXR,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS2,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_ULTRA,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO2_PRO,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_460,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	// NF2/IGP version, GeForce 4 MX, NV18	{ PCI_VENDOR_ID_NVIDIA, 0x01f0,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO_M32,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_500XGL,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO_M64,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_200,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_550XGL,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_500_GOGL,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_IGEFORCE2,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3_1,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3_2,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_DDC,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4600,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4400,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4200,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_900XGL,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_750XGL,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_700XGL,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO_5200,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ 0, } /* terminate list */};MODULE_DEVICE_TABLE(pci, rivafb_pci_tbl);/* ------------------------------------------------------------------------- * * * global variables * * ------------------------------------------------------------------------- *//* command line data, set in rivafb_setup() */static int flatpanel __devinitdata = -1; /* Autodetect later */static int forceCRTC __devinitdata = -1;static int noaccel   __devinitdata = 0;#ifdef CONFIG_MTRRstatic int nomtrr __devinitdata = 0;#endif#ifdef CONFIG_PMAC_BACKLIGHTstatic int backlight __devinitdata = 1;#elsestatic int backlight __devinitdata = 0;#endifstatic char *mode_option __devinitdata = NULL;static int  strictmode       = 0;static struct fb_fix_screeninfo __devinitdata rivafb_fix = {	.type		= FB_TYPE_PACKED_PIXELS,	.xpanstep	= 1,	.ypanstep	= 1,};static struct fb_var_screeninfo __devinitdata rivafb_default_var = {	.xres		= 640,	.yres		= 480,	.xres_virtual	= 640,	.yres_virtual	= 480,	.bits_per_pixel	= 8,	.red		= {0, 8, 0},	.green		= {0, 8, 0},	.blue		= {0, 8, 0},	.transp		= {0, 0, 0},	.activate	= FB_ACTIVATE_NOW,	.height		= -1,	.width		= -1,	.pixclock	= 39721,	.left_margin	= 40,	.right_margin	= 24,	.upper_margin	= 32,	.lower_margin	= 11,	.hsync_len	= 96,	.vsync_len	= 2,	.vmode		= FB_VMODE_NONINTERLACED};/* from GGI */static const struct riva_regs reg_template = {	{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,	/* ATTR */	 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,	 0x41, 0x01, 0x0F, 0x00, 0x00},	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	/* CRT  */	 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE3,	/* 0x10 */	 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	/* 0x20 */	 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	/* 0x30 */	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	 0x00,							/* 0x40 */	 },	{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,	/* GRA  */	 0xFF},	{0x03, 0x01, 0x0F, 0x00, 0x0E},				/* SEQ  */	0xEB							/* MISC */};/* * Backlight control */#ifdef CONFIG_FB_RIVA_BACKLIGHT/* We do not have any information about which values are allowed, thus * we used safe values. */#define MIN_LEVEL 0x158#define MAX_LEVEL 0x534#define LEVEL_STEP ((MAX_LEVEL - MIN_LEVEL) / FB_BACKLIGHT_MAX)static int riva_bl_get_level_brightness(struct riva_par *par,		int level){	struct fb_info *info = pci_get_drvdata(par->pdev);	int nlevel;	/* Get and convert the value */	/* No locking on bl_curve since accessing a single value */	nlevel = MIN_LEVEL + info->bl_curve[level] * LEVEL_STEP;	if (nlevel < 0)		nlevel = 0;	else if (nlevel < MIN_LEVEL)		nlevel = MIN_LEVEL;	else if (nlevel > MAX_LEVEL)		nlevel = MAX_LEVEL;	return nlevel;}static int riva_bl_update_status(struct backlight_device *bd){	struct riva_par *par = bl_get_data(bd);	U032 tmp_pcrt, tmp_pmc;	int level;	if (bd->props.power != FB_BLANK_UNBLANK ||	    bd->props.fb_blank != FB_BLANK_UNBLANK)		level = 0;	else		level = bd->props.brightness;	tmp_pmc = NV_RD32(par->riva.PMC, 0x10F0) & 0x0000FFFF;	tmp_pcrt = NV_RD32(par->riva.PCRTC0, 0x081C) & 0xFFFFFFFC;	if(level > 0) {		tmp_pcrt |= 0x1;		tmp_pmc |= (1 << 31); /* backlight bit */		tmp_pmc |= riva_bl_get_level_brightness(par, level) << 16; /* level */	}	NV_WR32(par->riva.PCRTC0, 0x081C, tmp_pcrt);	NV_WR32(par->riva.PMC, 0x10F0, tmp_pmc);	return 0;}static int riva_bl_get_brightness(struct backlight_device *bd){	return bd->props.brightness;}static struct backlight_ops riva_bl_ops = {	.get_brightness = riva_bl_get_brightness,	.update_status	= riva_bl_update_status,};static void riva_bl_init(struct riva_par *par){	struct fb_info *info = pci_get_drvdata(par->pdev);	struct backlight_device *bd;	char name[12];	if (!par->FlatPanel)		return;#ifdef CONFIG_PMAC_BACKLIGHT	if (!machine_is(powermac) ||	    !pmac_has_backlight_type("mnca"))		return;#endif	snprintf(name, sizeof(name), "rivabl%d", info->node);	bd = backlight_device_register(name, info->dev, par, &riva_bl_ops);	if (IS_ERR(bd)) {		info->bl_dev = NULL;		printk(KERN_WARNING "riva: Backlight registration failed\n");		goto error;	}	info->bl_dev = bd;	fb_bl_default_curve(info, 0,		MIN_LEVEL * FB_BACKLIGHT_MAX / MAX_LEVEL,		FB_BACKLIGHT_MAX);	bd->props.max_brightness = FB_BACKLIGHT_LEVELS - 1;	bd->props.brightness = bd->props.max_brightness;	bd->props.power = FB_BLANK_UNBLANK;	backlight_update_status(bd);	printk("riva: Backlight initialized (%s)\n", name);	return;error:	return;}static void riva_bl_exit(struct fb_info *info){	struct backlight_device *bd = info->bl_dev;	backlight_device_unregister(bd);	printk("riva: Backlight unloaded\n");}#elsestatic inline void riva_bl_init(struct riva_par *par) {}static inline void riva_bl_exit(struct fb_info *info) {}#endif /* CONFIG_FB_RIVA_BACKLIGHT *//* ------------------------------------------------------------------------- * * * MMIO access macros * * ------------------------------------------------------------------------- */static inline void CRTCout(struct riva_par *par, unsigned char index,			   unsigned char val){	VGA_WR08(par->riva.PCIO, 0x3d4, index);	VGA_WR08(par->riva.PCIO, 0x3d5, val);}static inline unsigned char CRTCin(struct riva_par *par,				   unsigned char index){	VGA_WR08(par->riva.PCIO, 0x3d4, index);	return (VGA_RD08(par->riva.PCIO, 0x3d5));}static inline void GRAout(struct riva_par *par, unsigned char index,			  unsigned char val){	VGA_WR08(par->riva.PVIO, 0x3ce, index);	VGA_WR08(par->riva.PVIO, 0x3cf, val);}static inline unsigned char GRAin(struct riva_par *par,				  unsigned char index){	VGA_WR08(par->riva.PVIO, 0x3ce, index);	return (VGA_RD08(par->riva.PVIO, 0x3cf));}static inline void SEQout(struct riva_par *par, unsigned char index,			  unsigned char val){	VGA_WR08(par->riva.PVIO, 0x3c4, index);	VGA_WR08(par->riva.PVIO, 0x3c5, val);}static inline unsigned char SEQin(struct riva_par *par,				  unsigned char index){	VGA_WR08(par->riva.PVIO, 0x3c4, index);	return (VGA_RD08(par->riva.PVIO, 0x3c5));}static inline void ATTRout(struct riva_par *par, unsigned char index,			   unsigned char val){	VGA_WR08(par->riva.PCIO, 0x3c0, index);	VGA_WR08(par->riva.PCIO, 0x3c0, val);}static inline unsigned char ATTRin(struct riva_par *par,				   unsigned char index){	VGA_WR08(par->riva.PCIO, 0x3c0, index);	return (VGA_RD08(par->riva.PCIO, 0x3c1));}static inline void MISCout(struct riva_par *par, unsigned char val){	VGA_WR08(par->riva.PVIO, 0x3c2, val);}static inline unsigned char MISCin(struct riva_par *par){	return (VGA_RD08(par->riva.PVIO, 0x3cc));}static inline void reverse_order(u32 *l){	u8 *a = (u8 *)l;	a[0] = bitrev8(a[0]);	a[1] = bitrev8(a[1]);	a[2] = bitrev8(a[2]);	a[3] = bitrev8(a[3]);}/* ------------------------------------------------------------------------- * * * cursor stuff * * ------------------------------------------------------------------------- *//** * rivafb_load_cursor_image - load cursor image to hardware * @data: address to monochrome bitmap (1 = foreground color, 0 = background) * @par:  pointer to private data * @w:    width of cursor image in pixels * @h:    height of cursor image in scanlines * @bg:   background color (ARGB1555) - alpha bit determines opacity * @fg:   foreground color (ARGB1555) * * DESCRIPTiON: * Loads cursor image based on a monochrome source and mask bitmap.  The * image bits determines the color of the pixel, 0 for background, 1 for * foreground.  Only the affected region (as determined by @w and @h  * parameters) will be updated. * * CALLED FROM: * rivafb_cursor() */static void rivafb_load_cursor_image(struct riva_par *par, u8 *data8,				     u16 bg, u16 fg, u32 w, u32 h){	int i, j, k = 0;	u32 b, tmp;	u32 *data = (u32 *)data8;	bg = le16_to_cpu(bg);	fg = le16_to_cpu(fg);	w = (w + 1) & ~1;	for (i = 0; i < h; i++) {		b = *data++;		reverse_order(&b);				for (j = 0; j < w/2; j++) {			tmp = 0;#if defined (__BIG_ENDIAN)			tmp = (b & (1 << 31)) ? fg << 16 : bg << 16;			b <<= 1;			tmp |= (b & (1 << 31)) ? fg : bg;			b <<= 1;#else			tmp = (b & 1) ? fg : bg;			b >>= 1;			tmp |= (b & 1) ? fg << 16 : bg << 16;			b >>= 1;#endif			writel(tmp, &par->riva.CURSOR[k++]);		}		k += (MAX_CURS - w)/2;	}}/* ------------------------------------------------------------------------- * * * general utility functions * * ------------------------------------------------------------------------- *//** * riva_wclut - set CLUT entry * @chip: pointer to RIVA_HW_INST object * @regnum: register number * @red: red component * @green: green component * @blue: blue component * * DESCRIPTION: * Sets color register @regnum. * * CALLED FROM: * rivafb_setcolreg() */static void riva_wclut(RIVA_HW_INST *chip,		       unsigned char regnum, unsigned char red,		       unsigned char green, unsigned char blue){	VGA_WR08(chip->PDIO, 0x3c8, regnum);	VGA_WR08(chip->PDIO, 0x3c9, red);	VGA_WR08(chip->PDIO, 0x3c9, green);	VGA_WR08(chip->PDIO, 0x3c9, blue);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -