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

📄 fbdev.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * 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 * * 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. *//* version number of this driver */#define RIVAFB_VERSION "0.7.3"#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/errno.h>#include <linux/string.h>#include <linux/mm.h>#include <linux/selection.h>#include <linux/tty.h>#include <linux/malloc.h>#include <linux/delay.h>#include <linux/fb.h>#include <linux/init.h>#include <linux/pci.h>#include <video/fbcon.h>#include "riva_hw.h"#include "nv4ref.h"#include "nvreg.h"#include "../vga.h"#include <video/fbcon-cfb4.h>#include <video/fbcon-cfb8.h>#include <video/fbcon-cfb16.h>#include <video/fbcon-cfb32.h>#ifndef CONFIG_PCI		/* sanity check */#error This driver requires PCI support.#endif/***************************************************************** * * various helpful macros and constants * *//* #define RIVAFBDEBUG */#ifdef RIVAFBDEBUG#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)#else#define DPRINTK(fmt, args...)#endif#ifndef RIVA_NDEBUG#define assert(expr) \	if(!(expr)) { \        printk( "Assertion failed! %s,%s,%s,line=%d\n",\        #expr,__FILE__,__FUNCTION__,__LINE__); \	BUG(); \        }#else#define assert(expr)#endif/* GGI compatibility macros */#define io_out8			outb#define io_in8			inb#define NUM_SEQ_REGS		0x05#define NUM_CRT_REGS		0x41#define NUM_GRC_REGS		0x09#define NUM_ATC_REGS		0x15#define PFX "rivafb: "#define CNVT_TOHW(val,width)	((((val)<<(width))+0x7FFF-(val))>>16)/* 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)enum riva_chips {	CH_RIVA_128 = 0,	CH_RIVA_TNT,	CH_RIVA_TNT2,	CH_RIVA_UTNT2,	/* UTNT2 */	CH_RIVA_VTNT2,	/* VTNT2 */	CH_RIVA_UVTNT2,	/* VTNT2 */	CH_RIVA_ITNT2,	/* ITNT2 */};/* directly indexed by riva_chips enum, above */static struct riva_chip_info {	const char *name;	unsigned arch_rev;} riva_chip_info[] __devinitdata = {	{ "RIVA-128", 3 },	{ "RIVA-TNT", 4 },	{ "RIVA-TNT2", 5 },	{ "RIVA-UTNT2", 5 },	{ "RIVA-VTNT2", 5 },	{ "RIVA-UVTNT2", 5 },	{ "RIVA-ITNT2", 5 },};static struct pci_device_id rivafb_pci_tbl[] __devinitdata = {	{ PCI_VENDOR_ID_NVIDIA_SGS, PCI_DEVICE_ID_NVIDIA_SGS_RIVA128, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_128 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_TNT, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_TNT },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_TNT2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_TNT2 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_UTNT2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_UTNT2 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_VTNT2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_VTNT2 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_UVTNT2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_VTNT2 },	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_ITNT2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_ITNT2 },	{ 0, } /* terminate list */};MODULE_DEVICE_TABLE(pci, rivafb_pci_tbl);/* holds the state of the VGA core and extended Riva hw state from riva_hw.c. * From KGI originally. */struct riva_regs {	u8 attr[NUM_ATC_REGS];	u8 crtc[NUM_CRT_REGS];	u8 gra[NUM_GRC_REGS];	u8 seq[NUM_SEQ_REGS];	u8 misc_output;	RIVA_HW_STATE ext;};/* * describes the state of a Riva board */struct rivafb_par {	struct riva_regs state;	/* state of hw board */	__u32 visual;		/* FB_VISUAL_xxx */	unsigned depth;		/* bpp of current mode */};typedef struct {	unsigned char red, green, blue, transp;} riva_cfb8_cmap_t;struct rivafb_info;struct rivafb_info {	struct fb_info info;	/* kernel framebuffer info */	RIVA_HW_INST riva;	/* interface to riva_hw.c */	const char *drvr_name;	/* Riva hardware board type */	unsigned long ctrl_base_phys;	/* physical control register base addr */	unsigned long fb_base_phys;	/* physical framebuffer base addr */	caddr_t ctrl_base;	/* virtual control register base addr */	caddr_t fb_base;	/* virtual framebuffer base addr */	unsigned ram_amount;	/* amount of RAM on card, in bytes */	unsigned dclk_max;	/* max DCLK */	struct riva_regs initial_state;	/* initial startup video mode */	struct display disp;	int currcon;	struct display *currcon_display;	struct rivafb_info *next;	struct pci_dev *pd;	/* pointer to board's pci info */	unsigned base0_region_size;	/* size of control register region */	unsigned base1_region_size;	/* size of framebuffer region */	riva_cfb8_cmap_t palette[256];	/* VGA DAC palette cache */#if defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB32)	union {#ifdef FBCON_HAS_CFB16		u_int16_t cfb16[16];#endif#ifdef FBCON_HAS_CFB32		u_int32_t cfb32[16];#endif	} con_cmap;#endif				/* FBCON_HAS_CFB16 | FBCON_HAS_CFB32 */};/* ------------------- global variables ------------------------ */static struct rivafb_info *riva_boards = NULL;/* command line data, set in rivafb_setup() */static char fontname[40] __initdata = { 0 };#ifndef MODULEstatic char noaccel __initdata = 0;	/* unused */static const char *mode_option __initdata = NULL;#endifstatic struct fb_var_screeninfo rivafb_default_var = {	/* 640x480-8@60, yres_virtual=2400 (fits for all Riva cards */	640, 480, 640, 2400, 0, 0, 8, 0,	{0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},	0, 0, -1, -1, 0, 39721, 40, 24, 32, 11, 96, 2,	0, FB_VMODE_NONINTERLACED};/* ------------------- prototypes ------------------------------ */static int rivafb_get_fix (struct fb_fix_screeninfo *fix, int con,		    struct fb_info *info);static int rivafb_get_var (struct fb_var_screeninfo *var, int con,		    struct fb_info *info);static int rivafb_set_var (struct fb_var_screeninfo *var, int con,		    struct fb_info *info);static int rivafb_get_cmap (struct fb_cmap *cmap, int kspc, int con,		     struct fb_info *info);static int rivafb_set_cmap (struct fb_cmap *cmap, int kspc, int con,		     struct fb_info *info);static int rivafb_pan_display (struct fb_var_screeninfo *var, int con,			struct fb_info *info);static int rivafb_ioctl (struct inode *inode, struct file *file, unsigned int cmd,		  unsigned long arg, int con, struct fb_info *info);static int rivafb_switch (int con, struct fb_info *info);static int rivafb_updatevar (int con, struct fb_info *info);static void rivafb_blank (int blank, struct fb_info *info);static void riva_load_video_mode (struct rivafb_info *rivainfo,				  struct fb_var_screeninfo *video_mode);static int riva_getcolreg (unsigned regno, unsigned *red, unsigned *green,			   unsigned *blue, unsigned *transp,			   struct fb_info *info);static int riva_setcolreg (unsigned regno, unsigned red, unsigned green,			   unsigned blue, unsigned transp,			   struct fb_info *info);static int riva_get_cmap_len (const struct fb_var_screeninfo *var);static int riva_set_fbinfo (struct rivafb_info *rinfo);static void riva_save_state (struct rivafb_info *rinfo, struct riva_regs *regs);static void riva_load_state (struct rivafb_info *rinfo, struct riva_regs *regs);static struct rivafb_info *riva_board_list_add (struct rivafb_info *board_list,					 struct rivafb_info *new_node);static struct rivafb_info *riva_board_list_del (struct rivafb_info *board_list,					 struct rivafb_info *del_node);static void riva_wclut (unsigned char regnum, unsigned char red,			unsigned char green, unsigned char blue);/* kernel interface */static struct fb_ops riva_fb_ops = {	owner:		THIS_MODULE,	fb_get_fix:	rivafb_get_fix,	fb_get_var:	rivafb_get_var,	fb_set_var:	rivafb_set_var,	fb_get_cmap:	rivafb_get_cmap,	fb_set_cmap:	rivafb_set_cmap,	fb_pan_display:	rivafb_pan_display,	fb_ioctl:	rivafb_ioctl,};/* 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 */};/* ------------------- general utility functions -------------------------- *//** * riva_set_dispsw * @rinfo: pointer to internal driver struct for a given Riva card * * DESCRIPTION: * Sets up console Low level operations depending on the current? color depth * of the display */static void riva_set_dispsw (struct rivafb_info *rinfo){	struct display *disp = &rinfo->disp;	DPRINTK ("ENTER\n");	assert (rinfo != NULL);	disp->dispsw_data = NULL;	switch (disp->var.bits_per_pixel) {#ifdef FBCON_HAS_MFB	case 1:		disp->dispsw = &fbcon_mfb;		break;#endif#ifdef FBCON_HAS_CFB4	case 4:		disp->dispsw = &fbcon_cfb4;		break;#endif#ifdef FBCON_HAS_CFB8	case 8:		disp->dispsw = &fbcon_cfb8;		break;#endif#ifdef FBCON_HAS_CFB16	case 15:	case 16:		disp->dispsw = &fbcon_cfb16;		disp->dispsw_data = &rinfo->con_cmap.cfb16;		break;#endif#ifdef FBCON_HAS_CFB24	case 24:		disp->dispsw = &fbcon_cfb24;		disp->dispsw_data = rinfo->con_cmap.cfb24;		break;#endif#ifdef FBCON_HAS_CFB32	case 32:		disp->dispsw = &fbcon_cfb32;		disp->dispsw_data = rinfo->con_cmap.cfb32;		break;#endif	default:		DPRINTK ("Setting fbcon_dummy renderer\n");		disp->dispsw = &fbcon_dummy;	}	DPRINTK ("EXIT\n");}static int riva_init_disp_var (struct rivafb_info *rinfo){#ifndef MODULE	if (mode_option)		fb_find_mode (&rinfo->disp.var, &rinfo->info, mode_option,			      NULL, 0, NULL, 8);#endif				/* !MODULE */	return 0;}static int __devinit riva_init_disp (struct rivafb_info *rinfo){	struct fb_info *info;	struct display *disp;	DPRINTK ("ENTER\n");	assert (rinfo != NULL);	info = &rinfo->info;	disp = &rinfo->disp;	disp->var = rivafb_default_var;	info->disp = disp;	/* FIXME: assure that disp->cmap is completely filled out */	disp->screen_base = rinfo->fb_base;	disp->visual = FB_VISUAL_PSEUDOCOLOR;	disp->type = FB_TYPE_PACKED_PIXELS;	disp->type_aux = 0;	disp->ypanstep = 1;	disp->ywrapstep = 0;	disp->next_line = disp->line_length =	    (disp->var.xres_virtual * disp->var.bits_per_pixel) >> 3;	disp->can_soft_blank = 1;	disp->inverse = 0;	riva_set_dispsw (rinfo);	disp->scrollmode = 0;	rinfo->currcon_display = disp;	if ((riva_init_disp_var (rinfo)) < 0) {	/* must be done last */		DPRINTK ("EXIT, returning -1\n");		return -1;	}	DPRINTK ("EXIT, returning 0\n");	return 0;}static int __devinit riva_set_fbinfo (struct rivafb_info *rinfo){	struct fb_info *info;	assert (rinfo != NULL);	info = &rinfo->info;	strcpy (info->modename, rinfo->drvr_name);	info->node = -1;	info->flags = FBINFO_FLAG_DEFAULT;	info->fbops = &riva_fb_ops;	/* FIXME: set monspecs to what??? */	info->display_fg = NULL;	strncpy (info->fontname, fontname, sizeof (info->fontname));	info->fontname[sizeof (info->fontname) - 1] = 0;	info->changevar = NULL;	info->switch_con = rivafb_switch;	info->updatevar = rivafb_updatevar;	info->blank = rivafb_blank;	if (riva_init_disp (rinfo) < 0)	/* must be done last */		return -1;	return 0;}/* ----------------------------- PCI bus ----------------------------- */static int __devinit rivafb_init_one (struct pci_dev *pd,				      const struct pci_device_id *ent){	struct rivafb_info *rinfo;	struct riva_chip_info *rci = &riva_chip_info[ent->driver_data];	assert (pd != NULL);	assert (rci != NULL);	rinfo = kmalloc (sizeof (struct rivafb_info), GFP_KERNEL);	if (!rinfo)		goto err_out;	memset (rinfo, 0, sizeof (struct rivafb_info));	rinfo->drvr_name = rci->name;	rinfo->riva.Architecture = rci->arch_rev;	rinfo->pd = pd;	rinfo->base0_region_size = pci_resource_len (pd, 0);	rinfo->base1_region_size = pci_resource_len (pd, 1);	assert (rinfo->base0_region_size >= 0x00800000);	/* from GGI */	assert (rinfo->base1_region_size >= 0x01000000);	/* from GGI */	rinfo->ctrl_base_phys = pci_resource_start (rinfo->pd, 0);	rinfo->fb_base_phys = pci_resource_start (rinfo->pd, 1);	if (!request_mem_region (rinfo->ctrl_base_phys,				 rinfo->base0_region_size, "rivafb")) {		printk (KERN_ERR PFX "cannot reserve MMIO region\n");		goto err_out_kfree;	}	if (!request_mem_region (rinfo->fb_base_phys,				 rinfo->base1_region_size, "rivafb")) {		printk (KERN_ERR PFX "cannot reserve FB region\n");		goto err_out_free_base0;	}	rinfo->ctrl_base = ioremap (rinfo->ctrl_base_phys,				    rinfo->base0_region_size);	if (!rinfo->ctrl_base) {		printk (KERN_ERR PFX "cannot ioremap MMIO base\n");		goto err_out_free_base1;	}		rinfo->fb_base = ioremap (rinfo->fb_base_phys,				  rinfo->base1_region_size);	if (!rinfo->fb_base) {		printk (KERN_ERR PFX "cannot ioremap FB base\n");		goto err_out_iounmap_ctrl;	}		rinfo->riva.EnableIRQ = 0;	rinfo->riva.IO = (inb (0x3CC) & 0x01) ? 0x3D0 : 0x3B0;	rinfo->riva.PRAMDAC = (unsigned *) (rinfo->ctrl_base + 0x00680000);	rinfo->riva.PFB = (unsigned *) (rinfo->ctrl_base + 0x00100000);	rinfo->riva.PFIFO = (unsigned *) (rinfo->ctrl_base + 0x00002000);	rinfo->riva.PGRAPH = (unsigned *) (rinfo->ctrl_base + 0x00400000);	rinfo->riva.PEXTDEV = (unsigned *) (rinfo->ctrl_base + 0x00101000);	rinfo->riva.PTIMER = (unsigned *) (rinfo->ctrl_base + 0x00009000);	rinfo->riva.PMC = (unsigned *) (rinfo->ctrl_base + 0x00000000);	rinfo->riva.FIFO = (unsigned *) (rinfo->ctrl_base + 0x00800000);	switch (rinfo->riva.Architecture) {	case 3:		rinfo->riva.PRAMIN =		    (unsigned *) (rinfo->fb_base + 0x00C00000);		break;	case 4:	case 5:		rinfo->riva.PCRTC =		    (unsigned *) (rinfo->ctrl_base + 0x00600000);		rinfo->riva.PRAMIN =		    (unsigned *) (rinfo->ctrl_base + 0x00710000);		break;	}	RivaGetConfig (&rinfo->riva);	/* back to normal */	assert (rinfo->pd != NULL);	/* unlock io */	vga_io_wcrt (0x11, 0xFF);	/* vgaHWunlock() + riva unlock (0x7F) */	outb (rinfo->riva.LockUnlockIndex, rinfo->riva.LockUnlockIO);	outb (0x57, rinfo->riva.LockUnlockIO + 1);	memcpy (&rinfo->initial_state, &reg_template,		sizeof (reg_template));	riva_save_state (rinfo, &rinfo->initial_state);	rinfo->ram_amount = rinfo->riva.RamAmountKBytes * 1024;	rinfo->dclk_max = rinfo->riva.MaxVClockFreqKHz * 1000;

⌨️ 快捷键说明

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