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

📄 intelfbdrv.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		mmio_bar = 0;	}	dinfo->aperture.physical = pci_resource_start(pdev, aperture_bar);	dinfo->aperture.size     = pci_resource_len(pdev, aperture_bar);	dinfo->mmio_base_phys    = pci_resource_start(pdev, mmio_bar);	DBG_MSG("fb aperture: 0x%llx/0x%llx, MMIO region: 0x%llx/0x%llx\n",		(unsigned long long)pci_resource_start(pdev, aperture_bar),		(unsigned long long)pci_resource_len(pdev, aperture_bar),		(unsigned long long)pci_resource_start(pdev, mmio_bar),		(unsigned long long)pci_resource_len(pdev, mmio_bar));	/* Reserve the fb and MMIO regions */	if (!request_mem_region(dinfo->aperture.physical, dinfo->aperture.size,				INTELFB_MODULE_NAME)) {		ERR_MSG("Cannot reserve FB region.\n");		cleanup(dinfo);		return -ENODEV;	}	dinfo->flag |= INTELFB_FB_ACQUIRED;	if (!request_mem_region(dinfo->mmio_base_phys,				INTEL_REG_SIZE,				INTELFB_MODULE_NAME)) {		ERR_MSG("Cannot reserve MMIO region.\n");		cleanup(dinfo);		return -ENODEV;	}	dinfo->flag |= INTELFB_MMIO_ACQUIRED;	/* Get the chipset info. */	dinfo->pci_chipset = pdev->device;	if (intelfbhw_get_chipset(pdev, dinfo)) {		cleanup(dinfo);		return -ENODEV;	}	if (intelfbhw_get_memory(pdev, &aperture_size,&stolen_size)) {		cleanup(dinfo);		return -ENODEV;	}	INF_MSG("%02x:%02x.%d: %s, aperture size %dMB, "		"stolen memory %dkB\n",		pdev->bus->number, PCI_SLOT(pdev->devfn),		PCI_FUNC(pdev->devfn), dinfo->name,		BtoMB(aperture_size), BtoKB(stolen_size));	/* Set these from the options. */	dinfo->accel    = accel;	dinfo->hwcursor = hwcursor;	if (NOACCEL_CHIPSET(dinfo) && dinfo->accel == 1) {		INF_MSG("Acceleration is not supported for the %s chipset.\n",			dinfo->name);		dinfo->accel = 0;	}	/* Framebuffer parameters - Use all the stolen memory if >= vram */	if (ROUND_UP_TO_PAGE(stolen_size) >= MB(vram)) {		dinfo->fb.size = ROUND_UP_TO_PAGE(stolen_size);		dinfo->fbmem_gart = 0;	} else {		dinfo->fb.size =  MB(vram);		dinfo->fbmem_gart = 1;	}	/* Allocate space for the ring buffer and HW cursor if enabled. */	if (dinfo->accel) {		dinfo->ring.size = RINGBUFFER_SIZE;		dinfo->ring_tail_mask = dinfo->ring.size - 1;	}	if (dinfo->hwcursor)		dinfo->cursor.size = HW_CURSOR_SIZE;	/* Use agpgart to manage the GATT */	if (!(bridge = agp_backend_acquire(pdev))) {		ERR_MSG("cannot acquire agp\n");		cleanup(dinfo);		return -ENODEV;	}	/* get the current gatt info */	if (agp_copy_info(bridge, &gtt_info)) {		ERR_MSG("cannot get agp info\n");		agp_backend_release(bridge);		cleanup(dinfo);		return -ENODEV;	}	if (MB(voffset) < stolen_size)		offset = (stolen_size >> 12);	else		offset = ROUND_UP_TO_PAGE(MB(voffset))/GTT_PAGE_SIZE;	/* set the mem offsets - set them after the already used pages */	if (dinfo->accel)		dinfo->ring.offset = offset + gtt_info.current_memory;	if (dinfo->hwcursor)		dinfo->cursor.offset = offset +			+ gtt_info.current_memory + (dinfo->ring.size >> 12);	if (dinfo->fbmem_gart)		dinfo->fb.offset = offset +			+ gtt_info.current_memory + (dinfo->ring.size >> 12)			+ (dinfo->cursor.size >> 12);	/* Allocate memories (which aren't stolen) */	/* Map the fb and MMIO regions */	/* ioremap only up to the end of used aperture */	dinfo->aperture.virtual = (u8 __iomem *)ioremap_nocache		(dinfo->aperture.physical, ((offset + dinfo->fb.offset) << 12)		 + dinfo->fb.size);	if (!dinfo->aperture.virtual) {		ERR_MSG("Cannot remap FB region.\n");		cleanup(dinfo);		return -ENODEV;	}	dinfo->mmio_base =		(u8 __iomem *)ioremap_nocache(dinfo->mmio_base_phys,					      INTEL_REG_SIZE);	if (!dinfo->mmio_base) {		ERR_MSG("Cannot remap MMIO region.\n");		cleanup(dinfo);		return -ENODEV;	}	if (dinfo->accel) {		if (!(dinfo->gtt_ring_mem =		      agp_allocate_memory(bridge, dinfo->ring.size >> 12,					  AGP_NORMAL_MEMORY))) {			ERR_MSG("cannot allocate ring buffer memory\n");			agp_backend_release(bridge);			cleanup(dinfo);			return -ENOMEM;		}		if (agp_bind_memory(dinfo->gtt_ring_mem,				    dinfo->ring.offset)) {			ERR_MSG("cannot bind ring buffer memory\n");			agp_backend_release(bridge);			cleanup(dinfo);			return -EBUSY;		}		dinfo->ring.physical = dinfo->aperture.physical			+ (dinfo->ring.offset << 12);		dinfo->ring.virtual  = dinfo->aperture.virtual			+ (dinfo->ring.offset << 12);		dinfo->ring_head = 0;	}	if (dinfo->hwcursor) {		agp_memtype = dinfo->mobile ? AGP_PHYSICAL_MEMORY			: AGP_NORMAL_MEMORY;		if (!(dinfo->gtt_cursor_mem =		      agp_allocate_memory(bridge, dinfo->cursor.size >> 12,					  agp_memtype))) {			ERR_MSG("cannot allocate cursor memory\n");			agp_backend_release(bridge);			cleanup(dinfo);			return -ENOMEM;		}		if (agp_bind_memory(dinfo->gtt_cursor_mem,				    dinfo->cursor.offset)) {			ERR_MSG("cannot bind cursor memory\n");			agp_backend_release(bridge);			cleanup(dinfo);			return -EBUSY;		}		if (dinfo->mobile)			dinfo->cursor.physical				= dinfo->gtt_cursor_mem->physical;		else			dinfo->cursor.physical = dinfo->aperture.physical				+ (dinfo->cursor.offset << 12);		dinfo->cursor.virtual = dinfo->aperture.virtual			+ (dinfo->cursor.offset << 12);	}	if (dinfo->fbmem_gart) {		if (!(dinfo->gtt_fb_mem =		      agp_allocate_memory(bridge, dinfo->fb.size >> 12,					  AGP_NORMAL_MEMORY))) {			WRN_MSG("cannot allocate framebuffer memory - use "				"the stolen one\n");			dinfo->fbmem_gart = 0;		}		if (agp_bind_memory(dinfo->gtt_fb_mem,				    dinfo->fb.offset)) {			WRN_MSG("cannot bind framebuffer memory - use "				"the stolen one\n");			dinfo->fbmem_gart = 0;		}	}	/* update framebuffer memory parameters */	if (!dinfo->fbmem_gart)		dinfo->fb.offset = 0;   /* starts at offset 0 */	dinfo->fb.physical = dinfo->aperture.physical		+ (dinfo->fb.offset << 12);	dinfo->fb.virtual = dinfo->aperture.virtual + (dinfo->fb.offset << 12);	dinfo->fb_start = dinfo->fb.offset << 12;	/* release agpgart */	agp_backend_release(bridge);	if (mtrr)		set_mtrr(dinfo);	DBG_MSG("fb: 0x%x(+ 0x%x)/0x%x (0x%p)\n",		dinfo->fb.physical, dinfo->fb.offset, dinfo->fb.size,		dinfo->fb.virtual);	DBG_MSG("MMIO: 0x%x/0x%x (0x%p)\n",		dinfo->mmio_base_phys, INTEL_REG_SIZE,		dinfo->mmio_base);	DBG_MSG("ring buffer: 0x%x/0x%x (0x%p)\n",		dinfo->ring.physical, dinfo->ring.size,		dinfo->ring.virtual);	DBG_MSG("HW cursor: 0x%x/0x%x (0x%p) (offset 0x%x) (phys 0x%x)\n",		dinfo->cursor.physical, dinfo->cursor.size,		dinfo->cursor.virtual, dinfo->cursor.offset,		dinfo->cursor.physical);	DBG_MSG("options: vram = %d, accel = %d, hwcursor = %d, fixed = %d, "		"noinit = %d\n", vram, accel, hwcursor, fixed, noinit);	DBG_MSG("options: mode = \"%s\"\n", mode ? mode : "");	if (probeonly)		bailout(dinfo);	/*	 * Check if the LVDS port or any DVO ports are enabled.  If so,	 * don't allow mode switching	 */	dvo = intelfbhw_check_non_crt(dinfo);	if (dvo) {		dinfo->fixed_mode = 1;		WRN_MSG("Non-CRT device is enabled ( ");		i = 0;		while (dvo) {			if (dvo & 1) {				s = intelfbhw_dvo_to_string(1 << i);				if (s)					printk("%s ", s);			}			dvo >>= 1;			++i;		}		printk(").  Disabling mode switching.\n");	}	if (bailearly == 1)		bailout(dinfo);	if (FIXED_MODE(dinfo) &&	    screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) {		ERR_MSG("Video mode must be programmed at boot time.\n");		cleanup(dinfo);		return -ENODEV;	}	if (bailearly == 2)		bailout(dinfo);	/* Initialise dinfo and related data. */	/* If an initial mode was programmed at boot time, get its details. */	if (screen_info.orig_video_isVGA == VIDEO_TYPE_VLFB)		get_initial_mode(dinfo);	if (bailearly == 3)		bailout(dinfo);	if (FIXED_MODE(dinfo))	/* remap fb address */		update_dinfo(dinfo, &dinfo->initial_var);	if (bailearly == 4)		bailout(dinfo);	if (intelfb_set_fbinfo(dinfo)) {		cleanup(dinfo);		return -ENODEV;	}	if (bailearly == 5)		bailout(dinfo);#ifdef CONFIG_FB_INTEL_I2C	/* register I2C bus */	intelfb_create_i2c_busses(dinfo);#endif	if (bailearly == 6)		bailout(dinfo);	pci_set_drvdata(pdev, dinfo);	/* Save the initial register state. */	i = intelfbhw_read_hw_state(dinfo, &dinfo->save_state,				    bailearly > 6 ? bailearly - 6 : 0);	if (i != 0) {		DBG_MSG("intelfbhw_read_hw_state returned %d\n", i);		bailout(dinfo);	}	intelfbhw_print_hw_state(dinfo, &dinfo->save_state);	if (bailearly == 18)		bailout(dinfo);	/* Cursor initialisation */	if (dinfo->hwcursor) {		intelfbhw_cursor_init(dinfo);		intelfbhw_cursor_reset(dinfo);	}	if (bailearly == 19)		bailout(dinfo);	/* 2d acceleration init */	if (dinfo->accel)		intelfbhw_2d_start(dinfo);	if (bailearly == 20)		bailout(dinfo);	if (noregister)		bailout(dinfo);	if (register_framebuffer(dinfo->info) < 0) {		ERR_MSG("Cannot register framebuffer.\n");		cleanup(dinfo);		return -ENODEV;	}	dinfo->registered = 1;	dinfo->open = 0;	init_waitqueue_head(&dinfo->vsync.wait);	spin_lock_init(&dinfo->int_lock);	dinfo->irq_flags = 0;	dinfo->vsync.pan_display = 0;	dinfo->vsync.pan_offset = 0;	return 0;err_out_pixmap:	fb_dealloc_cmap(&info->cmap);err_out_cmap:	framebuffer_release(info);	return -ENODEV;}static void __devexitintelfb_pci_unregister(struct pci_dev *pdev){	struct intelfb_info *dinfo = pci_get_drvdata(pdev);	DBG_MSG("intelfb_pci_unregister\n");	if (!dinfo)		return;	cleanup(dinfo);	pci_set_drvdata(pdev, NULL);}/*************************************************************** *                       helper functions                      * ***************************************************************/int __inline__ intelfb_var_to_depth(const struct fb_var_screeninfo *var){	DBG_MSG("intelfb_var_to_depth: bpp: %d, green.length is %d\n",		var->bits_per_pixel, var->green.length);	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 __inline__ int var_to_refresh(const struct fb_var_screeninfo *var){	int xtot = var->xres + var->left_margin + var->right_margin +		   var->hsync_len;	int ytot = var->yres + var->upper_margin + var->lower_margin +		   var->vsync_len;	return (1000000000 / var->pixclock * 1000 + 500) / xtot / ytot;}/*************************************************************** *                Various intialisation functions              * ***************************************************************/static void __devinit get_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->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 int __devinit intelfb_init_var(struct intelfb_info *dinfo){	struct fb_var_screeninfo *var;	int msrc = 0;	DBG_MSG("intelfb_init_var\n");	var = &dinfo->info->var;	if (FIXED_MODE(dinfo)) {	        memcpy(var, &dinfo->initial_var,		       sizeof(struct fb_var_screeninfo));		msrc = 5;	} else {		const u8 *edid_s = fb_firmware_edid(&dinfo->pdev->dev);		u8 *edid_d = NULL;		if (edid_s) {			edid_d = kmemdup(edid_s, EDID_LENGTH, GFP_KERNEL);			if (edid_d) {				fb_edid_to_monspecs(edid_d,						    &dinfo->info->monspecs);				kfree(edid_d);			}		}		if (mode) {			printk("intelfb: Looking for mode in private "			       "database\n");			msrc = fb_find_mode(var, dinfo->info, mode,					    dinfo->info->monspecs.modedb,					    dinfo->info->monspecs.modedb_len,					    NULL, 0);			if (msrc && msrc > 1) {				printk("intelfb: No mode in private database, "				       "intelfb: looking for mode in global "				       "database ");				msrc = fb_find_mode(var, dinfo->info, mode,						    NULL, 0, NULL, 0);				if (msrc)					msrc |= 8;			}		}		if (!msrc)			msrc = fb_find_mode(var, dinfo->info, PREFERRED_MODE,					    NULL, 0, NULL, 0);	}	if (!msrc) {		ERR_MSG("Cannot find a suitable video mode.\n");		return 1;	}	INF_MSG("Initial video mode is %dx%d-%d@%d.\n", var->xres, var->yres,		var->bits_per_pixel, var_to_refresh(var));	DBG_MSG("Initial video mode is from %d.\n", msrc);#if ALLOCATE_FOR_PANNING	/* Allow use of half of the video ram for panning */	var->xres_virtual = var->xres;	var->yres_virtual =		dinfo->fb.size / 2 / (var->bits_per_pixel * var->xres);	if (var->yres_virtual < var->yres)		var->yres_virtual = var->yres;#else	var->yres_virtual = var->yres;#endif	if (dinfo->accel)		var->accel_flags |= FB_ACCELF_TEXT;	else		var->accel_flags &= ~FB_ACCELF_TEXT;	return 0;}static int __devinit intelfb_set_fbinfo(struct intelfb_info *dinfo){	struct fb_info *info = dinfo->info;	DBG_MSG("intelfb_set_fbinfo\n");	info->flags = FBINFO_FLAG_DEFAULT;	info->fbops = &intel_fb_ops;	info->pseudo_palette = dinfo->pseudo_palette;	info->pixmap.size = 64*1024;	info->pixmap.buf_align = 8;	info->pixmap.access_align = 32;	info->pixmap.flags = FB_PIXMAP_SYSTEM;	if (intelfb_init_var(dinfo))		return 1;

⌨️ 快捷键说明

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