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

📄 intelfbdrv.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * intelfb * * Linux framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G * integrated graphics chips. * * Copyright (C) 2002, 2003 David Dawes <dawes@tungstengraphics.com> * * 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.15 2003/02/06 17:50:08 dawes Exp $ *//* $TG$ *//* * 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) * * TODO: *  -  * * Wish List: *  - Check clock limits for 845G and 830M. *  - Test on SMP config. *  - Check if any functions/data should be __devinit, etc. *  - See if it's feasible to get/use DDC/EDID info. *  - MTRR support. *  - See if module unloading can work. *  - See if driver works built-in to 2.5.32 kernel. *  - Check acceleration problems on 830M-855GM. *  - Add gtf support so that arbitrary modes can be calculated. *  - Port driver to latest 2.5.x fbdev interface. */#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/tty.h>#include <linux/slab.h>#include <linux/delay.h>#include <linux/fb.h>#include <linux/console.h>#include <linux/selection.h>#include <linux/ioport.h>#include <linux/init.h>#include <linux/pci.h>#include <linux/vmalloc.h>#include <linux/kd.h>#include <linux/vt_kern.h>#include <linux/pagemap.h>#include <linux/version.h>#include <asm/io.h>#include <video/fbcon.h>#include <video/fbcon-cfb8.h>#include <video/fbcon-cfb16.h>#include <video/fbcon-cfb32.h>#include "intelfb.h"#include "builtinmodes.c"/* * 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 },	{ 0, }};/* Global data */static int num_registered = 0;/* Forward declarations */static int intelfb_get_fix(struct fb_fix_screeninfo *fix, int con,			   struct fb_info *info);#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)static int intelfb_get_var(struct fb_var_screeninfo *var, int con,			   struct fb_info *info);#endifstatic int intelfb_set_var(struct fb_var_screeninfo *var, int con,			   struct fb_info *info);static int intelfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,			    struct fb_info *info);static int intelfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,			    struct fb_info *info);static int intelfb_ioctl(struct inode *inode, struct file *file,			 unsigned int cmd, unsigned long arg, int con,			 struct fb_info *info);static int intelfb_switch(int con, struct fb_info *info);static int intelfb_updatevar(int con, struct fb_info *info);static int intelfb_blank(int blank, struct fb_info *info);static int intelfb_getcolreg(unsigned regno, unsigned *red, unsigned *green,			     unsigned *blue, unsigned *transp,			     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_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);static void intelfb_set_dispsw(struct intelfb_info *dinfo,			       struct display *disp);static void mode_to_var(const struct fb_videomode *mode,			struct fb_var_screeninfo *var, u32 bpp);static int intelfb_set_mode(struct intelfb_info *dinfo,			    struct fb_var_screeninfo *var,			    struct display *disp, int blank);static void intelfb_do_install_cmap(int con, struct fb_info *info);static void update_dinfo(struct intelfb_info *dinfo,			 struct fb_var_screeninfo *var, struct display *disp);static void intelfb_flashcursor(unsigned long ptr);static void fbcon_intelfb_setup(struct display *p);static void fbcon_intelfb_bmove(struct display *p, int sy, int sx, int dy,				int dx, int height, int width);static void fbcon_intelfb_clear(struct vc_data *conp, struct display *p,				int sy, int sx, int height, int width);static void fbcon_intelfb_putc(struct vc_data *conp, struct display *p,			       int c, int yy, int xx);static void fbcon_intelfb_putcs(struct vc_data *conp, struct display *p,				const unsigned short *s, int count,				int yy, int xx);static void fbcon_intelfb_revc(struct display *p, int xx, int yy);static void fbcon_intelfb_clear_margins(struct vc_data *conp,					struct display *p, int bottom_only);static void fbcon_intelfb_cursor(struct display *disp, int mode, int x, int y);/* fb ops */static struct fb_ops intel_fb_ops = {	.owner =		THIS_MODULE,#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)	.fb_get_fix =		intelfb_get_fix,	.fb_get_var =		intelfb_get_var,#else	.fb_blank =		intelfb_blank,	.fb_setcolreg =		intelfb_setcolreg,#endif	.fb_set_var =		intelfb_set_var,	.fb_get_cmap =		intelfb_get_cmap,	.fb_set_cmap =		intelfb_set_cmap,	.fb_pan_display	=	intelfbhw_pan_display,	.fb_ioctl =		intelfb_ioctl};/* PCI driver module table */static struct pci_driver intelfb_driver = {	.name =			INTELFB_MODULE_NAME,	.id_table =		intelfb_pci_table,	.probe =		intelfb_pci_register,	.remove =		__devexit_p(intelfb_pci_unregister)};/* fbcon acceleration */static struct display_switch fbcon_intelfb = {	.setup =		fbcon_intelfb_setup,	.bmove =		fbcon_intelfb_bmove,	.clear =		fbcon_intelfb_clear,	.putc =			fbcon_intelfb_putc,	.putcs =		fbcon_intelfb_putcs,	.revc =			fbcon_intelfb_revc,	.cursor =		fbcon_intelfb_cursor,	.clear_margins =	fbcon_intelfb_clear_margins,	.fontwidthmask =	FONTWIDTHRANGE(4, 16)};/* Module description/parameters */MODULE_AUTHOR("David Dawes <dawes@tungstengraphics.com>");MODULE_DESCRIPTION(	"Framebuffer driver for Intel(R) " SUPPORTED_CHIPSETS " chipsets");MODULE_LICENSE("Dual BSD/GPL");MODULE_DEVICE_TABLE(pci, intelfb_pci_table);INTELFB_INT_PARAM(accel, 1, "Enable console acceleration");INTELFB_INT_PARAM(hwcursor, 1, "Enable HW cursor");INTELFB_INT_PARAM(fixed, 0, "Disable mode switching");INTELFB_INT_PARAM(noinit, 0, "Don't initialise graphics mode when loading");INTELFB_INT_PARAM(noregister, 0, "Don't register, just probe and exit (debug)");INTELFB_INT_PARAM(probeonly, 0, "Do a minimal probe (debug)");INTELFB_INT_PARAM(idonly, 0,		  "Just identify without doing anything else (debug)");INTELFB_INT_PARAM(bailearly, 0, "Bail out early, depending on value (debug)");INTELFB_STR_PARAM(mode, NULL,		  "Initial video mode \"<xres>x<yres>[-<depth>][@<refresh>]\"");INTELFB_STR_PARAM(font, NULL, "Specify which built-in font to use");/* module load/unload entry points */int __initintelfb_init(void){	DBG_MSG("intelfb_init\n");	INF_MSG("Framebuffer driver for "		"Intel(R) " SUPPORTED_CHIPSETS " chipsets\n");	INF_MSG("Version " INTELFB_VERSION		", written by David Dawes <dawes@tungstengraphics.com>\n");	if (idonly)		return -ENODEV;	return pci_module_init(&intelfb_driver);}void __exitintelfb_exit(void){	DBG_MSG("intelfb_exit\n");	pci_unregister_driver(&intelfb_driver);}#ifndef MODULE#define OPT_EQUAL(opt, name) (!strncmp(opt, name, strlen(name)))#define OPT_INTVAL(opt, name) simple_strtoul(opt + strlen(name), 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__ intget_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;}int __initintelfb_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_bool(this_opt, "hwcursor", &hwcursor))			;		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, "font="))			font = get_opt_string(this_opt, "font=");		else if (OPT_EQUAL(this_opt, "mode="))			mode = get_opt_string(this_opt, "mode=");		else			mode = this_opt;	}	return 0;}#endif#ifdef MODULEmodule_init(intelfb_init);module_exit(intelfb_exit);#endifstatic voidcleanup(struct intelfb_info *dinfo){	DBG_MSG("cleanup\n");	if (!dinfo)		return;	if (dinfo->registered)		unregister_framebuffer(&(dinfo->info));	if (&dinfo->cursor.timer)		del_timer_sync(&dinfo->cursor.timer);#if USE_SYNC_PAGE	if (dinfo->syncpage_virt) {		struct page *pg = virt_to_page((void *)dinfo->syncpage_virt);		if (pg) {			put_page(pg);			UnlockPage(pg);			free_page(dinfo->syncpage_virt);		}	}#endif	if (dinfo->cursor_base)		iounmap((void *)dinfo->cursor_base);	if (dinfo->ring_base)		iounmap((void *)dinfo->ring_base);	if (dinfo->fb_base)		iounmap((void *)dinfo->fb_base);	if (dinfo->mmio_base)		iounmap((void *)dinfo->mmio_base);	if (dinfo->mmio_base_phys && dinfo->pdev)		release_mem_region(dinfo->mmio_base_phys,				   pci_resource_len(dinfo->pdev, 1));	if (dinfo->fb_base_phys && dinfo->pdev)		release_mem_region(dinfo->fb_base_phys,				   pci_resource_len(dinfo->pdev, 0));	kfree(dinfo);}#define bailout(dinfo) do {						\	DBG_MSG("bailout\n");						\	cleanup(dinfo);							\	INF_MSG("Not going to register framebuffer, exiting...\n");	\	return -ENODEV;							\} while (0)intintelfb_var_to_depth(const struct fb_var_screeninfo *var){#if 0	DBG_MSG("intelfb_var_to_depth: bpp: %d, green.length is %d\n",		var->bits_per_pixel, var->green.length);#endif	switch (var->bits_per_pixel) {	case 16:		return (var->green.length == 6) ? 16 : 15;	case 32:		return 24;	default:		return var->bits_per_pixel;	}}static voidget_initial_mode(struct intelfb_info *dinfo){	struct fb_var_screeninfo *var;	int xtot, ytot;	DBG_MSG("get_initial_mode\n");	dinfo->initial_vga = 1;	dinfo->initial_fb_base = screen_info.lfb_base;	dinfo->initial_video_ram = screen_info.lfb_size * KB(64);	dinfo->initial_pitch = screen_info.lfb_linelength;	var = &dinfo->initial_var;	memset(var, 0, sizeof(*var));	var->xres = screen_info.lfb_width;	var->yres = screen_info.lfb_height;	var->xres_virtual = var->xres;#if ALLOCATE_FOR_PANNING	/* Allow use of half of the video ram for panning */	var->yres_virtual =		dinfo->initial_video_ram / 2 / dinfo->initial_pitch;	if (var->yres_virtual < var->yres)		var->yres_virtual = var->yres;#else	var->yres_virtual = var->yres;#endif	var->bits_per_pixel = screen_info.lfb_depth;	switch (screen_info.lfb_depth) {	case 15:		var->bits_per_pixel = 16;		break;	case 24:		var->bits_per_pixel = 32;		break;	}	DBG_MSG("Initial info: FB is 0x%x/0x%x (%d kByte)\n",		dinfo->initial_fb_base, dinfo->initial_video_ram,		BtoKB(dinfo->initial_video_ram));	DBG_MSG("Initial info: mode is %dx%d-%d (%d)\n",		var->xres, var->yres, var->bits_per_pixel,		dinfo->initial_pitch);	/* Dummy timing values (assume 60Hz) */	var->left_margin = (var->xres / 8) & 0xf8;	var->right_margin = 32;	var->upper_margin = 16;	var->lower_margin = 4;	var->hsync_len = (var->xres / 8) & 0xf8;	var->vsync_len = 4;	xtot = var->xres + var->left_margin +		var->right_margin + var->hsync_len;	ytot = var->yres + var->upper_margin +		var->lower_margin + var->vsync_len;	var->pixclock = 10000000 / xtot * 1000 / ytot * 100 / 60;	var->height = -1;	var->width = -1;	if (var->bits_per_pixel > 8) {		var->red.offset = screen_info.red_pos;		var->red.length = screen_info.red_size;		var->green.offset = screen_info.green_pos;		var->green.length = screen_info.green_size;		var->blue.offset = screen_info.blue_pos;		var->blue.length = screen_info.blue_size;		var->transp.offset = screen_info.rsvd_pos;		var->transp.length = screen_info.rsvd_size;	} else {		var->red.length = 8;		var->green.length = 8;		var->blue.length = 8;	}}static intintelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent){	struct intelfb_info *dinfo;	int i, j, err;	const char *s;	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;	}	if (!(dinfo = kmalloc(sizeof(struct intelfb_info), GFP_KERNEL))) {		ERR_MSG("Could not allocate memory for intelfb_info.\n");		return -ENODEV;	}	memset(dinfo, 0, sizeof(*dinfo));	dinfo->pdev = pdev;

⌨️ 快捷键说明

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