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

📄 intelfbdrv.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * intelfb * * Linux framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G/915G/915GM/ * 945G/945GM/945GME/965G/965GM integrated graphics chips. * * Copyright © 2002, 2003 David Dawes <dawes@xfree86.org> *                   2004 Sylvain Meyer *                   2006 David Airlie * * This driver consists of two parts.  The first part (intelfbdrv.c) provides * the basic fbdev interfaces, is derived in part from the radeonfb and * vesafb drivers, and is covered by the GPL.  The second part (intelfbhw.c) * provides the code to program the hardware.  Most of it is derived from * the i810/i830 XFree86 driver.  The HW-specific code is covered here * under a dual license (GPL and MIT/XFree86 license). * * Author: David Dawes * *//* $DHD: intelfb/intelfbdrv.c,v 1.20 2003/06/27 15:17:40 dawes Exp $ *//* * Changes: *    01/2003 - Initial driver (0.1.0), no mode switching, no acceleration. *		This initial version is a basic core that works a lot like *		the vesafb driver.  It must be built-in to the kernel, *		and the initial video mode must be set with vga=XXX at *		boot time.  (David Dawes) * *    01/2003 - Version 0.2.0: Mode switching added, colormap support *		implemented, Y panning, and soft screen blanking implemented. *		No acceleration yet.  (David Dawes) * *    01/2003 - Version 0.3.0: fbcon acceleration support added.  Module *		option handling added.  (David Dawes) * *    01/2003 - Version 0.4.0: fbcon HW cursor support added.  (David Dawes) * *    01/2003 - Version 0.4.1: Add auto-generation of built-in modes. *		(David Dawes) * *    02/2003 - Version 0.4.2: Add check for active non-CRT devices, and *		mode validation checks.  (David Dawes) * *    02/2003 - Version 0.4.3: Check when the VC is in graphics mode so that *		acceleration is disabled while an XFree86 server is running. *		(David Dawes) * *    02/2003 - Version 0.4.4: Monitor DPMS support.  (David Dawes) * *    02/2003 - Version 0.4.5: Basic XFree86 + fbdev working.  (David Dawes) * *    02/2003 - Version 0.5.0: Modify to work with the 2.5.32 kernel as well *		as 2.4.x kernels.  (David Dawes) * *    02/2003 - Version 0.6.0: Split out HW-specifics into a separate file. *		(David Dawes) * *    02/2003 - Version 0.7.0: Test on 852GM/855GM.  Acceleration and HW *		cursor are disabled on this platform.  (David Dawes) * *    02/2003 - Version 0.7.1: Test on 845G.  Acceleration is disabled *		on this platform.  (David Dawes) * *    02/2003 - Version 0.7.2: Test on 830M.  Acceleration and HW *		cursor are disabled on this platform.  (David Dawes) * *    02/2003 - Version 0.7.3: Fix 8-bit modes for mobile platforms *		(David Dawes) * *    02/2003 - Version 0.7.4: Add checks for FB and FBCON_HAS_CFB* configured *		in the kernel, and add mode bpp verification and default *		bpp selection based on which FBCON_HAS_CFB* are configured. *		(David Dawes) * *    02/2003 - Version 0.7.5: Add basic package/install scripts based on the *		DRI packaging scripts.  (David Dawes) * *    04/2003 - Version 0.7.6: Fix typo that affects builds with SMP-enabled *		kernels.  (David Dawes, reported by Anupam). * *    06/2003 - Version 0.7.7: *              Fix Makefile.kernel build problem (Tsutomu Yasuda). *		Fix mis-placed #endif (2.4.21 kernel). * *    09/2004 - Version 0.9.0 - by Sylvain Meyer *              Port to linux 2.6 kernel fbdev *              Fix HW accel and HW cursor on i845G *              Use of agpgart for fb memory reservation *              Add mtrr support * *    10/2004 - Version 0.9.1 *              Use module_param instead of old MODULE_PARM *              Some cleanup * *    11/2004 - Version 0.9.2 *              Add vram option to reserve more memory than stolen by BIOS *              Fix intelfbhw_pan_display typo *              Add __initdata annotations * *    04/2008 - Version 0.9.5 *              Add support for 965G/965GM. (Maik Broemme <mbroemme@plusserver.de>) * *    08/2008 - Version 0.9.6 *              Add support for 945GME. (Phil Endecott <spam_from_intelfb@chezphil.org>) */#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/ioport.h>#include <linux/init.h>#include <linux/pci.h>#include <linux/vmalloc.h>#include <linux/pagemap.h>#include <linux/screen_info.h>#include <asm/io.h>#ifdef CONFIG_MTRR#include <asm/mtrr.h>#endif#include "intelfb.h"#include "intelfbhw.h"#include "../edid.h"static void __devinit get_initial_mode(struct intelfb_info *dinfo);static void update_dinfo(struct intelfb_info *dinfo,			 struct fb_var_screeninfo *var);static int intelfb_open(struct fb_info *info, int user);static int intelfb_release(struct fb_info *info, int user);static int intelfb_check_var(struct fb_var_screeninfo *var,			     struct fb_info *info);static int intelfb_set_par(struct fb_info *info);static int intelfb_setcolreg(unsigned regno, unsigned red, unsigned green,			     unsigned blue, unsigned transp,			     struct fb_info *info);static int intelfb_blank(int blank, struct fb_info *info);static int intelfb_pan_display(struct fb_var_screeninfo *var,			       struct fb_info *info);static void intelfb_fillrect(struct fb_info *info,			     const struct fb_fillrect *rect);static void intelfb_copyarea(struct fb_info *info,			     const struct fb_copyarea *region);static void intelfb_imageblit(struct fb_info *info,			      const struct fb_image *image);static int intelfb_cursor(struct fb_info *info,			   struct fb_cursor *cursor);static int intelfb_sync(struct fb_info *info);static int intelfb_ioctl(struct fb_info *info,			 unsigned int cmd, unsigned long arg);static int __devinit intelfb_pci_register(struct pci_dev *pdev,					  const struct pci_device_id *ent);static void __devexit intelfb_pci_unregister(struct pci_dev *pdev);static int __devinit intelfb_set_fbinfo(struct intelfb_info *dinfo);/* * Limiting the class to PCI_CLASS_DISPLAY_VGA prevents function 1 of the * mobile chipsets from being registered. */#if DETECT_VGA_CLASS_ONLY#define INTELFB_CLASS_MASK ~0 << 8#else#define INTELFB_CLASS_MASK 0#endifstatic struct pci_device_id intelfb_pci_table[] __devinitdata = {	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_830M, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_830M },	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_845G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_845G },	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_85XGM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_85XGM },	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_865G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_865G },	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_915G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_915G },	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_915GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_915GM },	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945G },	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945GM },	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945GME, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945GME },	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_965G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_965G },	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_965GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_965GM },	{ 0, }};/* Global data */static int num_registered = 0;/* fb ops */static struct fb_ops intel_fb_ops = {	.owner =		THIS_MODULE,	.fb_open =              intelfb_open,	.fb_release =           intelfb_release,	.fb_check_var =         intelfb_check_var,	.fb_set_par =           intelfb_set_par,	.fb_setcolreg =		intelfb_setcolreg,	.fb_blank =		intelfb_blank,	.fb_pan_display =       intelfb_pan_display,	.fb_fillrect  =         intelfb_fillrect,	.fb_copyarea  =         intelfb_copyarea,	.fb_imageblit =         intelfb_imageblit,	.fb_cursor =            intelfb_cursor,	.fb_sync =              intelfb_sync,	.fb_ioctl =		intelfb_ioctl};/* PCI driver module table */static struct pci_driver intelfb_driver = {	.name =		"intelfb",	.id_table =	intelfb_pci_table,	.probe =	intelfb_pci_register,	.remove =	__devexit_p(intelfb_pci_unregister)};/* Module description/parameters */MODULE_AUTHOR("David Dawes <dawes@tungstengraphics.com>, "	      "Sylvain Meyer <sylvain.meyer@worldonline.fr>");MODULE_DESCRIPTION("Framebuffer driver for Intel(R) " SUPPORTED_CHIPSETS		   " chipsets");MODULE_LICENSE("Dual BSD/GPL");MODULE_DEVICE_TABLE(pci, intelfb_pci_table);static int accel        = 1;static int vram         = 4;static int hwcursor     = 0;static int mtrr         = 1;static int fixed        = 0;static int noinit       = 0;static int noregister   = 0;static int probeonly    = 0;static int idonly       = 0;static int bailearly    = 0;static int voffset	= 48;static char *mode       = NULL;module_param(accel, bool, S_IRUGO);MODULE_PARM_DESC(accel, "Enable hardware acceleration");module_param(vram, int, S_IRUGO);MODULE_PARM_DESC(vram, "System RAM to allocate to framebuffer in MiB");module_param(voffset, int, S_IRUGO);MODULE_PARM_DESC(voffset, "Offset of framebuffer in MiB");module_param(hwcursor, bool, S_IRUGO);MODULE_PARM_DESC(hwcursor, "Enable HW cursor");module_param(mtrr, bool, S_IRUGO);MODULE_PARM_DESC(mtrr, "Enable MTRR support");module_param(fixed, bool, S_IRUGO);MODULE_PARM_DESC(fixed, "Disable mode switching");module_param(noinit, bool, 0);MODULE_PARM_DESC(noinit, "Don't initialise graphics mode when loading");module_param(noregister, bool, 0);MODULE_PARM_DESC(noregister, "Don't register, just probe and exit (debug)");module_param(probeonly, bool, 0);MODULE_PARM_DESC(probeonly, "Do a minimal probe (debug)");module_param(idonly, bool, 0);MODULE_PARM_DESC(idonly, "Just identify without doing anything else (debug)");module_param(bailearly, bool, 0);MODULE_PARM_DESC(bailearly, "Bail out early, depending on value (debug)");module_param(mode, charp, S_IRUGO);MODULE_PARM_DESC(mode,		 "Initial video mode \"<xres>x<yres>[-<depth>][@<refresh>]\"");#ifndef MODULE#define OPT_EQUAL(opt, name) (!strncmp(opt, name, strlen(name)))#define OPT_INTVAL(opt, name) simple_strtoul(opt + strlen(name) + 1, NULL, 0)#define OPT_STRVAL(opt, name) (opt + strlen(name))static __inline__ char * get_opt_string(const char *this_opt, const char *name){	const char *p;	int i;	char *ret;	p = OPT_STRVAL(this_opt, name);	i = 0;	while (p[i] && p[i] != ' ' && p[i] != ',')		i++;	ret = kmalloc(i + 1, GFP_KERNEL);	if (ret) {		strncpy(ret, p, i);		ret[i] = '\0';	}	return ret;}static __inline__ int get_opt_int(const char *this_opt, const char *name,				  int *ret){	if (!ret)		return 0;	if (!OPT_EQUAL(this_opt, name))		return 0;	*ret = OPT_INTVAL(this_opt, name);	return 1;}static __inline__ int get_opt_bool(const char *this_opt, const char *name,				   int *ret){	if (!ret)		return 0;	if (OPT_EQUAL(this_opt, name)) {		if (this_opt[strlen(name)] == '=')			*ret = simple_strtoul(this_opt + strlen(name) + 1,					      NULL, 0);		else			*ret = 1;	} else {		if (OPT_EQUAL(this_opt, "no") && OPT_EQUAL(this_opt + 2, name))			*ret = 0;		else			return 0;	}	return 1;}static int __init intelfb_setup(char *options){	char *this_opt;	DBG_MSG("intelfb_setup\n");	if (!options || !*options) {		DBG_MSG("no options\n");		return 0;	} else		DBG_MSG("options: %s\n", options);	/*	 * These are the built-in options analogous to the module parameters	 * defined above.	 *	 * The syntax is:	 *	 *    video=intelfb:[mode][,<param>=<val>] ...	 *	 * e.g.,	 *	 *    video=intelfb:1024x768-16@75,accel=0	 */	while ((this_opt = strsep(&options, ","))) {		if (!*this_opt)			continue;		if (get_opt_bool(this_opt, "accel", &accel))			;		else if (get_opt_int(this_opt, "vram", &vram))			;		else if (get_opt_bool(this_opt, "hwcursor", &hwcursor))			;		else if (get_opt_bool(this_opt, "mtrr", &mtrr))			;		else if (get_opt_bool(this_opt, "fixed", &fixed))			;		else if (get_opt_bool(this_opt, "init", &noinit))			noinit = !noinit;		else if (OPT_EQUAL(this_opt, "mode="))			mode = get_opt_string(this_opt, "mode=");		else			mode = this_opt;	}	return 0;}#endifstatic int __init intelfb_init(void){#ifndef MODULE	char *option = NULL;#endif	DBG_MSG("intelfb_init\n");	INF_MSG("Framebuffer driver for "		"Intel(R) " SUPPORTED_CHIPSETS " chipsets\n");	INF_MSG("Version " INTELFB_VERSION "\n");	if (idonly)		return -ENODEV;#ifndef MODULE	if (fb_get_options("intelfb", &option))		return -ENODEV;	intelfb_setup(option);#endif	return pci_register_driver(&intelfb_driver);}static void __exit intelfb_exit(void){	DBG_MSG("intelfb_exit\n");	pci_unregister_driver(&intelfb_driver);}module_init(intelfb_init);module_exit(intelfb_exit);/*************************************************************** *                     mtrr support functions                  * ***************************************************************/#ifdef CONFIG_MTRRstatic inline void __devinit set_mtrr(struct intelfb_info *dinfo){	dinfo->mtrr_reg = mtrr_add(dinfo->aperture.physical,				   dinfo->aperture.size, MTRR_TYPE_WRCOMB, 1);	if (dinfo->mtrr_reg < 0) {		ERR_MSG("unable to set MTRR\n");		return;	}	dinfo->has_mtrr = 1;}static inline void unset_mtrr(struct intelfb_info *dinfo){	if (dinfo->has_mtrr)		mtrr_del(dinfo->mtrr_reg, dinfo->aperture.physical,			 dinfo->aperture.size);}#else#define set_mtrr(x) WRN_MSG("MTRR is disabled in the kernel\n")#define unset_mtrr(x) do { } while (0)#endif /* CONFIG_MTRR *//*************************************************************** *                        driver init / cleanup                * ***************************************************************/static void cleanup(struct intelfb_info *dinfo){	DBG_MSG("cleanup\n");	if (!dinfo)		return;	intelfbhw_disable_irq(dinfo);	fb_dealloc_cmap(&dinfo->info->cmap);	kfree(dinfo->info->pixmap.addr);	if (dinfo->registered)		unregister_framebuffer(dinfo->info);	unset_mtrr(dinfo);	if (dinfo->fbmem_gart && dinfo->gtt_fb_mem) {		agp_unbind_memory(dinfo->gtt_fb_mem);		agp_free_memory(dinfo->gtt_fb_mem);	}	if (dinfo->gtt_cursor_mem) {		agp_unbind_memory(dinfo->gtt_cursor_mem);		agp_free_memory(dinfo->gtt_cursor_mem);	}	if (dinfo->gtt_ring_mem) {		agp_unbind_memory(dinfo->gtt_ring_mem);		agp_free_memory(dinfo->gtt_ring_mem);	}#ifdef CONFIG_FB_INTEL_I2C	/* un-register I2C bus */	intelfb_delete_i2c_busses(dinfo);#endif	if (dinfo->mmio_base)		iounmap((void __iomem *)dinfo->mmio_base);	if (dinfo->aperture.virtual)		iounmap((void __iomem *)dinfo->aperture.virtual);	if (dinfo->flag & INTELFB_MMIO_ACQUIRED)		release_mem_region(dinfo->mmio_base_phys, INTEL_REG_SIZE);	if (dinfo->flag & INTELFB_FB_ACQUIRED)		release_mem_region(dinfo->aperture.physical,				   dinfo->aperture.size);	framebuffer_release(dinfo->info);}#define bailout(dinfo) do {						\	DBG_MSG("bailout\n");						\	cleanup(dinfo);							\	INF_MSG("Not going to register framebuffer, exiting...\n");	\	return -ENODEV;							\} while (0)static int __devinit intelfb_pci_register(struct pci_dev *pdev,					  const struct pci_device_id *ent){	struct fb_info *info;	struct intelfb_info *dinfo;	int i, err, dvo;	int aperture_size, stolen_size;	struct agp_kern_info gtt_info;	int agp_memtype;	const char *s;	struct agp_bridge_data *bridge;	int aperture_bar = 0;	int mmio_bar = 1;	int offset;	DBG_MSG("intelfb_pci_register\n");	num_registered++;	if (num_registered != 1) {		ERR_MSG("Attempted to register %d devices "			"(should be only 1).\n", num_registered);		return -ENODEV;	}	info = framebuffer_alloc(sizeof(struct intelfb_info), &pdev->dev);	if (!info) {		ERR_MSG("Could not allocate memory for intelfb_info.\n");		return -ENODEV;	}	if (fb_alloc_cmap(&info->cmap, 256, 1) < 0) {		ERR_MSG("Could not allocate cmap for intelfb_info.\n");		goto err_out_cmap;		return -ENODEV;	}	dinfo = info->par;	dinfo->info  = info;	dinfo->fbops = &intel_fb_ops;	dinfo->pdev  = pdev;	/* Reserve pixmap space. */	info->pixmap.addr = kzalloc(64 * 1024, GFP_KERNEL);	if (info->pixmap.addr == NULL) {		ERR_MSG("Cannot reserve pixmap memory.\n");		goto err_out_pixmap;	}	/* set early this option because it could be changed by tv encoder	   driver */	dinfo->fixed_mode = fixed;	/* Enable device. */	if ((err = pci_enable_device(pdev))) {		ERR_MSG("Cannot enable device.\n");		cleanup(dinfo);		return -ENODEV;	}	/* Set base addresses. */	if ((ent->device == PCI_DEVICE_ID_INTEL_915G) ||	    (ent->device == PCI_DEVICE_ID_INTEL_915GM) ||	    (ent->device == PCI_DEVICE_ID_INTEL_945G)  ||	    (ent->device == PCI_DEVICE_ID_INTEL_945GM) ||	    (ent->device == PCI_DEVICE_ID_INTEL_945GME) ||	    (ent->device == PCI_DEVICE_ID_INTEL_965G) ||	    (ent->device == PCI_DEVICE_ID_INTEL_965GM)) {		aperture_bar = 2;

⌨️ 快捷键说明

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