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

📄 intelfbhw.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * intelfb * * Linux framebuffer driver for Intel(R) 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/intelfbhw.c,v 1.7 2003/02/06 00:53:11 dawes Exp $ *//* $TG$ */#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 "intelfbhw.h"intintelfbhw_get_chipset(struct pci_dev *pdev, const char **name, int *chipset,		      int *mobile){	u32 tmp;	if (!pdev || !name || !chipset || !mobile)		return 1;	switch (pdev->device) {	case PCI_DEVICE_ID_INTEL_830M:		*name = "Intel(R) 830M";		*chipset = INTEL_830M;		*mobile = 1;		return 0;	case PCI_DEVICE_ID_INTEL_845G:		*name = "Intel(R) 845G";		*chipset = INTEL_845G;		*mobile = 0;		return 0;	case PCI_DEVICE_ID_INTEL_85XGM:		tmp = 0;		*mobile = 1;		pci_read_config_dword(pdev, INTEL_85X_CAPID, &tmp);		switch ((tmp >> INTEL_85X_VARIANT_SHIFT) &			INTEL_85X_VARIANT_MASK) {		case INTEL_VAR_855GME:			*name = "Intel(R) 855GME";			*chipset = INTEL_855GME;			return 0;		case INTEL_VAR_855GM:			*name = "Intel(R) 855GM";			*chipset = INTEL_855GM;			return 0;		case INTEL_VAR_852GME:			*name = "Intel(R) 852GME";			*chipset = INTEL_852GME;			return 0;		case INTEL_VAR_852GM:			*name = "Intel(R) 852GM";			*chipset = INTEL_852GM;			return 0;		default:			*name = "Intel(R) 852GM/855GM";			*chipset = INTEL_85XGM;			return 0;		}		break;	case PCI_DEVICE_ID_INTEL_865G:		*name = "Intel(R) 865G";		*chipset = INTEL_865G;		*mobile = 0;		return 0;	default:		return 1;	}}intintelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size,		     int *stolen_size){	struct pci_dev *bridge_dev;	u16 tmp;	if (!pdev || !aperture_size || !stolen_size)		return 1;	/* Find the bridge device.  It is always 0:0.0 */	if (!(bridge_dev = pci_find_slot(0, PCI_DEVFN(0, 0)))) {		ERR_MSG("cannot find bridge device\n");		return 1;	}	/* Get the fb aperture size and "stolen" memory amount. */	tmp = 0;	pci_read_config_word(bridge_dev, INTEL_GMCH_CTRL, &tmp);	switch (pdev->device) {	case PCI_DEVICE_ID_INTEL_830M:	case PCI_DEVICE_ID_INTEL_845G:		if ((tmp & INTEL_GMCH_MEM_MASK) == INTEL_GMCH_MEM_64M)			*aperture_size = MB(64);		else			*aperture_size = MB(128);		switch (tmp & INTEL_830_GMCH_GMS_MASK) {		case INTEL_830_GMCH_GMS_STOLEN_512:			*stolen_size = KB(512) - KB(132);			return 0;		case INTEL_830_GMCH_GMS_STOLEN_1024:			*stolen_size = MB(1) - KB(132);			return 0;		case INTEL_830_GMCH_GMS_STOLEN_8192:			*stolen_size = MB(8) - KB(132);			return 0;		case INTEL_830_GMCH_GMS_LOCAL:			ERR_MSG("only local memory found\n");			return 1;		case INTEL_830_GMCH_GMS_DISABLED:			ERR_MSG("video memory is disabled\n");			return 1;		default:			ERR_MSG("unexpected GMCH_GMS value: 0x%02x\n",				tmp & INTEL_830_GMCH_GMS_MASK);			return 1;		}		break;	default:		*aperture_size = MB(128);		switch (tmp & INTEL_855_GMCH_GMS_MASK) {		case INTEL_855_GMCH_GMS_STOLEN_1M:			*stolen_size = MB(1) - KB(132);			return 0;		case INTEL_855_GMCH_GMS_STOLEN_4M:			*stolen_size = MB(4) - KB(132);			return 0;		case INTEL_855_GMCH_GMS_STOLEN_8M:			*stolen_size = MB(8) - KB(132);			return 0;		case INTEL_855_GMCH_GMS_STOLEN_16M:			*stolen_size = MB(16) - KB(132);			return 0;		case INTEL_855_GMCH_GMS_STOLEN_32M:			*stolen_size = MB(32) - KB(132);			return 0;		case INTEL_855_GMCH_GMS_DISABLED:			ERR_MSG("video memory is disabled\n");			return 0;		default:			ERR_MSG("unexpected GMCH_GMS value: 0x%02x\n",				tmp & INTEL_855_GMCH_GMS_MASK);			return 1;		}	}}const char *intelfbhw_check_non_crt(struct intelfb_info *dinfo){	if (INREG(LVDS) & PORT_ENABLE)		return "LVDS port";	else if (INREG(DVOA) & PORT_ENABLE)		return "DVO port A";	else if (INREG(DVOB) & PORT_ENABLE)		return "DVO port B";	else if (INREG(DVOC) & PORT_ENABLE)		return "DVO port C";	else		return NULL;}intintelfbhw_validate_mode(struct intelfb_info *dinfo, int con,			struct fb_var_screeninfo *var){	int bytes_per_pixel;	int tmp;	DBG_MSG("intelfbhw_validate_mode\n");	bytes_per_pixel = var->bits_per_pixel / 8;	if (bytes_per_pixel == 3)		bytes_per_pixel = 4;	/* Check if enough video memory. */	tmp = var->yres_virtual * var->xres_virtual * bytes_per_pixel;	if (tmp > dinfo->video_ram) {		if (con >= 0)			WRN_MSG("Not enough video ram for mode "				"(%d KByte vs %d KByte).\n",				BtoKB(tmp), BtoKB(dinfo->video_ram));		return 1;	}	/* Check if x/y limits are OK. */	if (var->xres - 1 > HACTIVE_MASK) {		if (con >= 0)			WRN_MSG("X resolution too large (%d vs %d).\n",				var->xres, HACTIVE_MASK + 1);		return 1;	}	if (var->yres - 1 > VACTIVE_MASK) {		if (con >= 0)			WRN_MSG("Y resolution too large (%d vs %d).\n",				var->yres, VACTIVE_MASK + 1);		return 1;	}	/* Check for interlaced/doublescan modes. */	if (var->vmode & FB_VMODE_INTERLACED) {		if (con >= 0)			WRN_MSG("Mode is interlaced.\n");		return 1;	}	if (var->vmode & FB_VMODE_DOUBLE) {		if (con >= 0)			WRN_MSG("Mode is double-scan.\n");		return 1;	}	/* Check if clock is OK. */	tmp = 1000000000 / var->pixclock;	if (tmp < MIN_CLOCK) {		if (con >= 0)			WRN_MSG("Pixel clock is too low (%d MHz vs %d MHz).\n",				(tmp + 500) / 1000, MIN_CLOCK / 1000);		return 1;	}	if (tmp > MAX_CLOCK) {		if (con >= 0)			WRN_MSG("Pixel clock is too high (%d MHz vs %d MHz).\n",				(tmp + 500) / 1000, MAX_CLOCK / 1000);		return 1;	}	return 0;}intintelfbhw_pan_display(struct fb_var_screeninfo *var, int con,		      struct fb_info *info){	struct intelfb_info *dinfo = GET_DINFO(info);	u32 offset, xoffset, yoffset;	DBG_MSG("intelfbhw_pan_display\n");	if (con != dinfo->currcon)		return 0;	xoffset = ROUND_DOWN_TO(var->xoffset, 8);	yoffset = var->yoffset;	if ((xoffset + var->xres > var->xres_virtual) ||	    (yoffset + var->yres > var->yres_virtual))		return EINVAL;	offset = (yoffset * dinfo->pitch) +		 (xoffset * var->bits_per_pixel) / 8;	OUTREG(DSPABASE, offset);	return 0;}/* Blank the screen. */voidintelfbhw_do_blank(int blank, struct fb_info *info){	struct intelfb_info *dinfo = GET_DINFO(info);	u32 tmp;	DBG_MSG("intelfbhw_do_blank: blank is %d\n", blank);	/* Turn plane A on or off */	tmp = INREG(DSPACNTR);	if (blank)		tmp &= ~DISPPLANE_PLANE_ENABLE;	else		tmp |= DISPPLANE_PLANE_ENABLE;	OUTREG(DSPACNTR, tmp);	/* Flush */	tmp = INREG(DSPABASE);	OUTREG(DSPABASE, tmp);	/* Turn off/on the HW cursor */#if VERBOSE > 0	DBG_MSG("cursor.enabled is %d\n", dinfo->cursor.enabled);#endif	if (dinfo->cursor.enabled) {		if (blank) {			intelfbhw_cursor_hide(dinfo);		} else {			intelfbhw_cursor_show(dinfo);		}		dinfo->cursor.enabled = 1;	}	dinfo->cursor.blanked = blank;	/* Set DPMS level */	tmp = INREG(ADPA) & ~ADPA_DPMS_CONTROL_MASK;	switch (blank) {	case 0:	case 1:		tmp |= ADPA_DPMS_D0;		break;	case 2:		tmp |= ADPA_DPMS_D1;		break;	case 3:		tmp |= ADPA_DPMS_D2;		break;	case 4:		tmp |= ADPA_DPMS_D3;		break;	}	OUTREG(ADPA, tmp);		return;}voidintelfbhw_setcolreg(struct intelfb_info *dinfo, unsigned regno,		    unsigned red, unsigned green, unsigned blue,		    unsigned transp){#if VERBOSE > 1	DBG_MSG("intelfbhw_setcolreg: %d: (%d, %d, %d)\n",		regno, red, green, blue);#endif	u32 palette_reg = (dinfo->pipe == PIPE_A) ?			  PALETTE_A : PALETTE_B;	OUTREG(palette_reg + (regno << 2), 	       (red << PALETTE_8_RED_SHIFT) |	       (green << PALETTE_8_GREEN_SHIFT) |	       (blue << PALETTE_8_BLUE_SHIFT));}intintelfbhw_read_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw,			int flag){	int i;	DBG_MSG("intelfbhw_read_hw_state\n");	if (!hw || !dinfo)		return -1;	/* Read in as much of the HW state as possible. */	hw->vga0_divisor = INREG(VGA0_DIVISOR);	hw->vga1_divisor = INREG(VGA1_DIVISOR);	hw->vga_pd = INREG(VGAPD);	hw->dpll_a = INREG(DPLL_A);	hw->dpll_b = INREG(DPLL_B);	hw->fpa0 = INREG(FPA0);	hw->fpa1 = INREG(FPA1);	hw->fpb0 = INREG(FPB0);	hw->fpb1 = INREG(FPB1);	if (flag == 1)		return flag;#if 0	/* This seems to be a problem with the 852GM/855GM */	for (i = 0; i < PALETTE_8_ENTRIES; i++) {		hw->palette_a[i] = INREG(PALETTE_A + (i << 2));		hw->palette_b[i] = INREG(PALETTE_B + (i << 2));	}#endif	if (flag == 2)		return flag;	hw->htotal_a = INREG(HTOTAL_A);	hw->hblank_a = INREG(HBLANK_A);	hw->hsync_a = INREG(HSYNC_A);	hw->vtotal_a = INREG(VTOTAL_A);	hw->vblank_a = INREG(VBLANK_A);	hw->vsync_a = INREG(VSYNC_A);	hw->src_size_a = INREG(SRC_SIZE_A);	hw->bclrpat_a = INREG(BCLRPAT_A);	hw->htotal_b = INREG(HTOTAL_B);	hw->hblank_b = INREG(HBLANK_B);	hw->hsync_b = INREG(HSYNC_B);	hw->vtotal_b = INREG(VTOTAL_B);	hw->vblank_b = INREG(VBLANK_B);	hw->vsync_b = INREG(VSYNC_B);	hw->src_size_b = INREG(SRC_SIZE_B);	hw->bclrpat_b = INREG(BCLRPAT_B);	if (flag == 3)		return flag;	hw->adpa = INREG(ADPA);	hw->dvoa = INREG(DVOA);	hw->dvob = INREG(DVOB);	hw->dvoc = INREG(DVOC);	hw->dvoa_srcdim = INREG(DVOA_SRCDIM);	hw->dvob_srcdim = INREG(DVOB_SRCDIM);	hw->dvoc_srcdim = INREG(DVOC_SRCDIM);	hw->lvds = INREG(LVDS);	if (flag == 4)		return flag;	hw->pipe_a_conf = INREG(PIPEACONF);	hw->pipe_b_conf = INREG(PIPEBCONF);	hw->disp_arb = INREG(DISPARB);	if (flag == 5)		return flag;	hw->cursor_a_control = INREG(CURSOR_A_CONTROL);	hw->cursor_b_control = INREG(CURSOR_B_CONTROL);	hw->cursor_a_base = INREG(CURSOR_A_BASEADDR);	hw->cursor_b_base = INREG(CURSOR_B_BASEADDR);	if (flag == 6)		return flag;	for (i = 0; i < 4; i++) {		hw->cursor_a_palette[i] = INREG(CURSOR_A_PALETTE0 + (i << 2));		hw->cursor_b_palette[i] = INREG(CURSOR_B_PALETTE0 + (i << 2));	}	if (flag == 7)		return flag;	hw->cursor_size = INREG(CURSOR_SIZE);	if (flag == 8)		return flag;	hw->disp_a_ctrl = INREG(DSPACNTR);	hw->disp_b_ctrl = INREG(DSPBCNTR);	hw->disp_a_base = INREG(DSPABASE);	hw->disp_b_base = INREG(DSPBBASE);	hw->disp_a_stride = INREG(DSPASTRIDE);	hw->disp_b_stride = INREG(DSPBSTRIDE);	if (flag == 9)		return flag;	hw->vgacntrl = INREG(VGACNTRL);	if (flag == 10)		return flag;	hw->add_id = INREG(ADD_ID);	if (flag == 11)		return flag;	for (i = 0; i < 7; i++) {		hw->swf0x[i] = INREG(SWF00 + (i << 2));		hw->swf1x[i] = INREG(SWF10 + (i << 2));		if (i < 3)			hw->swf3x[i] = INREG(SWF30 + (i << 2));	}	for (i = 0; i < 8; i++)		hw->fence[i] = INREG(FENCE + (i << 2));	hw->instpm = INREG(INSTPM);	hw->mem_mode = INREG(MEM_MODE);	hw->fw_blc_0 = INREG(FW_BLC_0);	hw->fw_blc_1 = INREG(FW_BLC_1);	return 0;}voidintelfbhw_print_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw){#if REGDUMP	int i, m1, m2, n, p1, p2;	DBG_MSG("intelfbhw_print_hw_state\n");	if (!hw || !dinfo)		return;	/* Read in as much of the HW state as possible. */	printk("hw state dump start\n");	printk("	VGA0_DIVISOR:		0x%08x\n", hw->vga0_divisor);	printk("	VGA1_DIVISOR:		0x%08x\n", hw->vga1_divisor);	printk("	VGAPD: 			0x%08x\n", hw->vga_pd);	n = (hw->vga0_divisor >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;	m1 = (hw->vga0_divisor >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;	m2 = (hw->vga0_divisor >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;	if (hw->vga_pd & VGAPD_0_P1_FORCE_DIV2)		p1 = 0;	else		p1 = (hw->vga_pd >> VGAPD_0_P1_SHIFT) & DPLL_P1_MASK;	p2 = (hw->vga_pd >> VGAPD_0_P2_SHIFT) & DPLL_P2_MASK;	printk("	VGA0: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",		m1, m2, n, p1, p2);	printk("	VGA0: clock is %d\n", CALC_VCLOCK(m1, m2, n, p1, p2));		n = (hw->vga1_divisor >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;	m1 = (hw->vga1_divisor >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;	m2 = (hw->vga1_divisor >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;	if (hw->vga_pd & VGAPD_1_P1_FORCE_DIV2)		p1 = 0;	else		p1 = (hw->vga_pd >> VGAPD_1_P1_SHIFT) & DPLL_P1_MASK;	p2 = (hw->vga_pd >> VGAPD_1_P2_SHIFT) & DPLL_P2_MASK;	printk("	VGA1: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",		m1, m2, n, p1, p2);	printk("	VGA1: clock is %d\n", CALC_VCLOCK(m1, m2, n, p1, p2));		printk("	DPLL_A:			0x%08x\n", hw->dpll_a);	printk("	DPLL_B:			0x%08x\n", hw->dpll_b);	printk("	FPA0:			0x%08x\n", hw->fpa0);	printk("	FPA1:			0x%08x\n", hw->fpa1);	printk("	FPB0:			0x%08x\n", hw->fpb0);	printk("	FPB1:			0x%08x\n", hw->fpb1);	n = (hw->fpa0 >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;	m1 = (hw->fpa0 >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;	m2 = (hw->fpa0 >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;	if (hw->dpll_a & DPLL_P1_FORCE_DIV2)		p1 = 0;	else		p1 = (hw->dpll_a >> DPLL_P1_SHIFT) & DPLL_P1_MASK;	p2 = (hw->dpll_a >> DPLL_P2_SHIFT) & DPLL_P2_MASK;	printk("	PLLA0: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",		m1, m2, n, p1, p2);	printk("	PLLA0: clock is %d\n", CALC_VCLOCK(m1, m2, n, p1, p2));	n = (hw->fpa1 >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;	m1 = (hw->fpa1 >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;	m2 = (hw->fpa1 >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;	if (hw->dpll_a & DPLL_P1_FORCE_DIV2)		p1 = 0;	else		p1 = (hw->dpll_a >> DPLL_P1_SHIFT) & DPLL_P1_MASK;	p2 = (hw->dpll_a >> DPLL_P2_SHIFT) & DPLL_P2_MASK;	printk("	PLLA1: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",		m1, m2, n, p1, p2);	printk("	PLLA1: clock is %d\n", CALC_VCLOCK(m1, m2, n, p1, p2));	#if 0	printk("	PALETTE_A:\n");	for (i = 0; i < PALETTE_8_ENTRIES)		printk("	%3d:	0x%08x\n", i, hw->palette_a[i];	printk("	PALETTE_B:\n");	for (i = 0; i < PALETTE_8_ENTRIES)		printk("	%3d:	0x%08x\n", i, hw->palette_b[i];#endif	printk("	HTOTAL_A:		0x%08x\n", hw->htotal_a);	printk("	HBLANK_A:		0x%08x\n", hw->hblank_a);	printk("	HSYNC_A:		0x%08x\n", hw->hsync_a);	printk("	VTOTAL_A:		0x%08x\n", hw->vtotal_a);	printk("	VBLANK_A:		0x%08x\n", hw->vblank_a);	printk("	VSYNC_A:		0x%08x\n", hw->vsync_a);

⌨️ 快捷键说明

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