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

📄 savagefb_driver.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	/* We need to set CR67 whether or not we use the BIOS. */	dclk = timings.Clock;	reg->CR67 = 0x00;	switch(var->bits_per_pixel) {	case 8:		if ((par->chip == S3_SAVAGE2000) && (dclk >= 230000))			reg->CR67 = 0x10;	/* 8bpp, 2 pixels/clock */		else			reg->CR67 = 0x00;	/* 8bpp, 1 pixel/clock */		break;	case 15:		if (S3_SAVAGE_MOBILE_SERIES(par->chip) ||		    ((par->chip == S3_SAVAGE2000) && (dclk >= 230000)))			reg->CR67 = 0x30;	/* 15bpp, 2 pixel/clock */		else			reg->CR67 = 0x20;	/* 15bpp, 1 pixels/clock */		break;	case 16:		if (S3_SAVAGE_MOBILE_SERIES(par->chip) ||		   ((par->chip == S3_SAVAGE2000) && (dclk >= 230000)))			reg->CR67 = 0x50;	/* 16bpp, 2 pixel/clock */		else			reg->CR67 = 0x40;	/* 16bpp, 1 pixels/clock */		break;	case 24:		reg->CR67 = 0x70;		break;	case 32:		reg->CR67 = 0xd0;		break;	}	/*	 * Either BIOS use is disabled, or we failed to find a suitable	 * match.  Fall back to traditional register-crunching.	 */	vga_out8(0x3d4, 0x3a, par);	tmp = vga_in8(0x3d5, par);	if (1 /*FIXME:psav->pci_burst*/)		reg->CR3A = (tmp & 0x7f) | 0x15;	else		reg->CR3A = tmp | 0x95;	reg->CR53 = 0x00;	reg->CR31 = 0x8c;	reg->CR66 = 0x89;	vga_out8(0x3d4, 0x58, par);	reg->CR58 = vga_in8(0x3d5, par) & 0x80;	reg->CR58 |= 0x13;	reg->SR15 = 0x03 | 0x80;	reg->SR18 = 0x00;	reg->CR43 = reg->CR45 = reg->CR65 = 0x00;	vga_out8(0x3d4, 0x40, par);	reg->CR40 = vga_in8(0x3d5, par) & ~0x01;	reg->MMPR0 = 0x010400;	reg->MMPR1 = 0x00;	reg->MMPR2 = 0x0808;	reg->MMPR3 = 0x08080810;	SavageCalcClock(dclk, 1, 1, 127, 0, 4, 180000, 360000, &m, &n, &r);	/* m = 107; n = 4; r = 2; */	if (par->MCLK <= 0) {		reg->SR10 = 255;		reg->SR11 = 255;	} else {		common_calc_clock(par->MCLK, 1, 1, 31, 0, 3, 135000, 270000,				   &reg->SR11, &reg->SR10);		/*      reg->SR10 = 80; // MCLK == 286000 */		/*      reg->SR11 = 125; */	}	reg->SR12 = (r << 6) | (n & 0x3f);	reg->SR13 = m & 0xff;	reg->SR29 = (r & 4) | (m & 0x100) >> 5 | (n & 0x40) >> 2;	if (var->bits_per_pixel < 24)		reg->MMPR0 -= 0x8000;	else		reg->MMPR0 -= 0x4000;	if (timings.interlaced)		reg->CR42 = 0x20;	else		reg->CR42 = 0x00;	reg->CR34 = 0x10; /* display fifo */	i = ((((timings.HTotal >> 3) - 5) & 0x100) >> 8) |		((((timings.HDisplay >> 3) - 1) & 0x100) >> 7) |		((((timings.HSyncStart >> 3) - 1) & 0x100) >> 6) |		((timings.HSyncStart & 0x800) >> 7);	if ((timings.HSyncEnd >> 3) - (timings.HSyncStart >> 3) > 64)		i |= 0x08;	if ((timings.HSyncEnd >> 3) - (timings.HSyncStart >> 3) > 32)		i |= 0x20;	j = (reg->CRTC[0] + ((i & 0x01) << 8) +	     reg->CRTC[4] + ((i & 0x10) << 4) + 1) / 2;	if (j - (reg->CRTC[4] + ((i & 0x10) << 4)) < 4) {		if (reg->CRTC[4] + ((i & 0x10) << 4) + 4 <=		    reg->CRTC[0] + ((i & 0x01) << 8))			j = reg->CRTC[4] + ((i & 0x10) << 4) + 4;		else			j = reg->CRTC[0] + ((i & 0x01) << 8) + 1;	}	reg->CR3B = j & 0xff;	i |= (j & 0x100) >> 2;	reg->CR3C = (reg->CRTC[0] + ((i & 0x01) << 8)) / 2;	reg->CR5D = i;	reg->CR5E = (((timings.VTotal - 2) & 0x400) >> 10) |		(((timings.VDisplay - 1) & 0x400) >> 9) |		(((timings.VSyncStart) & 0x400) >> 8) |		(((timings.VSyncStart) & 0x400) >> 6) | 0x40;	width = (var->xres_virtual * ((var->bits_per_pixel+7) / 8)) >> 3;	reg->CR91 = reg->CRTC[19] = 0xff & width;	reg->CR51 = (0x300 & width) >> 4;	reg->CR90 = 0x80 | (width >> 8);	reg->MiscOutReg |= 0x0c;	/* Set frame buffer description. */	if (var->bits_per_pixel <= 8)		reg->CR50 = 0;	else if (var->bits_per_pixel <= 16)		reg->CR50 = 0x10;	else		reg->CR50 = 0x30;	if (var->xres_virtual <= 640)		reg->CR50 |= 0x40;	else if (var->xres_virtual == 800)		reg->CR50 |= 0x80;	else if (var->xres_virtual == 1024)		reg->CR50 |= 0x00;	else if (var->xres_virtual == 1152)		reg->CR50 |= 0x01;	else if (var->xres_virtual == 1280)		reg->CR50 |= 0xc0;	else if (var->xres_virtual == 1600)		reg->CR50 |= 0x81;	else		reg->CR50 |= 0xc1;	/* Use GBD */	if (par->chip == S3_SAVAGE2000)		reg->CR33 = 0x08;	else		reg->CR33 = 0x20;	reg->CRTC[0x17] = 0xeb;	reg->CR67 |= 1;	vga_out8(0x3d4, 0x36, par);	reg->CR36 = vga_in8(0x3d5, par);	vga_out8(0x3d4, 0x68, par);	reg->CR68 = vga_in8(0x3d5, par);	reg->CR69 = 0;	vga_out8(0x3d4, 0x6f, par);	reg->CR6F = vga_in8(0x3d5, par);	vga_out8(0x3d4, 0x86, par);	reg->CR86 = vga_in8(0x3d5, par);	vga_out8(0x3d4, 0x88, par);	reg->CR88 = vga_in8(0x3d5, par) | 0x08;	vga_out8(0x3d4, 0xb0, par);	reg->CRB0 = vga_in8(0x3d5, par) | 0x80;	return 0;}/* --------------------------------------------------------------------- *//* *    Set a single color register. Return != 0 for invalid regno. */static int savagefb_setcolreg(unsigned        regno,			      unsigned        red,			      unsigned        green,			      unsigned        blue,			      unsigned        transp,			      struct fb_info *info){	struct savagefb_par *par = info->par;	if (regno >= NR_PALETTE)		return -EINVAL;	par->palette[regno].red    = red;	par->palette[regno].green  = green;	par->palette[regno].blue   = blue;	par->palette[regno].transp = transp;	switch (info->var.bits_per_pixel) {	case 8:		vga_out8(0x3c8, regno, par);		vga_out8(0x3c9, red   >> 10, par);		vga_out8(0x3c9, green >> 10, par);		vga_out8(0x3c9, blue  >> 10, par);		break;	case 16:		if (regno < 16)			((u32 *)info->pseudo_palette)[regno] =				((red   & 0xf800)      ) |				((green & 0xfc00) >>  5) |				((blue  & 0xf800) >> 11);		break;	case 24:		if (regno < 16)			((u32 *)info->pseudo_palette)[regno] =				((red    & 0xff00) <<  8) |				((green  & 0xff00)      ) |				((blue   & 0xff00) >>  8);		break;	case 32:		if (regno < 16)			((u32 *)info->pseudo_palette)[regno] =				((transp & 0xff00) << 16) |				((red    & 0xff00) <<  8) |				((green  & 0xff00)      ) |				((blue   & 0xff00) >>  8);		break;	default:		return 1;	}	return 0;}static void savagefb_set_par_int(struct savagefb_par  *par, struct savage_reg *reg){	unsigned char tmp, cr3a, cr66, cr67;	DBG("savagefb_set_par_int");	par->SavageWaitIdle(par);	vga_out8(0x3c2, 0x23, par);	vga_out16(0x3d4, 0x4838, par);	vga_out16(0x3d4, 0xa539, par);	vga_out16(0x3c4, 0x0608, par);	vgaHWProtect(par, 1);	/*	 * Some Savage/MX and /IX systems go nuts when trying to exit the	 * server after WindowMaker has displayed a gradient background.  I	 * haven't been able to find what causes it, but a non-destructive	 * switch to mode 3 here seems to eliminate the issue.	 */	VerticalRetraceWait(par);	vga_out8(0x3d4, 0x67, par);	cr67 = vga_in8(0x3d5, par);	vga_out8(0x3d5, cr67/*par->CR67*/ & ~0x0c, par); /* no STREAMS yet */	vga_out8(0x3d4, 0x23, par);	vga_out8(0x3d5, 0x00, par);	vga_out8(0x3d4, 0x26, par);	vga_out8(0x3d5, 0x00, par);	/* restore extended regs */	vga_out8(0x3d4, 0x66, par);	vga_out8(0x3d5, reg->CR66, par);	vga_out8(0x3d4, 0x3a, par);	vga_out8(0x3d5, reg->CR3A, par);	vga_out8(0x3d4, 0x31, par);	vga_out8(0x3d5, reg->CR31, par);	vga_out8(0x3d4, 0x32, par);	vga_out8(0x3d5, reg->CR32, par);	vga_out8(0x3d4, 0x58, par);	vga_out8(0x3d5, reg->CR58, par);	vga_out8(0x3d4, 0x53, par);	vga_out8(0x3d5, reg->CR53 & 0x7f, par);	vga_out16(0x3c4, 0x0608, par);	/* Restore DCLK registers. */	vga_out8(0x3c4, 0x0e, par);	vga_out8(0x3c5, reg->SR0E, par);	vga_out8(0x3c4, 0x0f, par);	vga_out8(0x3c5, reg->SR0F, par);	vga_out8(0x3c4, 0x29, par);	vga_out8(0x3c5, reg->SR29, par);	vga_out8(0x3c4, 0x15, par);	vga_out8(0x3c5, reg->SR15, par);	/* Restore flat panel expansion regsters. */	if (par->chip == S3_SAVAGE_MX) {		int i;		for (i = 0; i < 8; i++) {			vga_out8(0x3c4, 0x54+i, par);			vga_out8(0x3c5, reg->SR54[i], par);		}	}	vgaHWRestore (par, reg);	/* extended mode timing registers */	vga_out8(0x3d4, 0x53, par);	vga_out8(0x3d5, reg->CR53, par);	vga_out8(0x3d4, 0x5d, par);	vga_out8(0x3d5, reg->CR5D, par);	vga_out8(0x3d4, 0x5e, par);	vga_out8(0x3d5, reg->CR5E, par);	vga_out8(0x3d4, 0x3b, par);	vga_out8(0x3d5, reg->CR3B, par);	vga_out8(0x3d4, 0x3c, par);	vga_out8(0x3d5, reg->CR3C, par);	vga_out8(0x3d4, 0x43, par);	vga_out8(0x3d5, reg->CR43, par);	vga_out8(0x3d4, 0x65, par);	vga_out8(0x3d5, reg->CR65, par);	/* restore the desired video mode with cr67 */	vga_out8(0x3d4, 0x67, par);	/* following part not present in X11 driver */	cr67 = vga_in8(0x3d5, par) & 0xf;	vga_out8(0x3d5, 0x50 | cr67, par);	udelay(10000);	vga_out8(0x3d4, 0x67, par);	/* end of part */	vga_out8(0x3d5, reg->CR67 & ~0x0c, par);	/* other mode timing and extended regs */	vga_out8(0x3d4, 0x34, par);	vga_out8(0x3d5, reg->CR34, par);	vga_out8(0x3d4, 0x40, par);	vga_out8(0x3d5, reg->CR40, par);	vga_out8(0x3d4, 0x42, par);	vga_out8(0x3d5, reg->CR42, par);	vga_out8(0x3d4, 0x45, par);	vga_out8(0x3d5, reg->CR45, par);	vga_out8(0x3d4, 0x50, par);	vga_out8(0x3d5, reg->CR50, par);	vga_out8(0x3d4, 0x51, par);	vga_out8(0x3d5, reg->CR51, par);	/* memory timings */	vga_out8(0x3d4, 0x36, par);	vga_out8(0x3d5, reg->CR36, par);	vga_out8(0x3d4, 0x60, par);	vga_out8(0x3d5, reg->CR60, par);	vga_out8(0x3d4, 0x68, par);	vga_out8(0x3d5, reg->CR68, par);	vga_out8(0x3d4, 0x69, par);	vga_out8(0x3d5, reg->CR69, par);	vga_out8(0x3d4, 0x6f, par);	vga_out8(0x3d5, reg->CR6F, par);	vga_out8(0x3d4, 0x33, par);	vga_out8(0x3d5, reg->CR33, par);	vga_out8(0x3d4, 0x86, par);	vga_out8(0x3d5, reg->CR86, par);	vga_out8(0x3d4, 0x88, par);	vga_out8(0x3d5, reg->CR88, par);	vga_out8(0x3d4, 0x90, par);	vga_out8(0x3d5, reg->CR90, par);	vga_out8(0x3d4, 0x91, par);	vga_out8(0x3d5, reg->CR91, par);	if (par->chip == S3_SAVAGE4) {		vga_out8(0x3d4, 0xb0, par);		vga_out8(0x3d5, reg->CRB0, par);	}	vga_out8(0x3d4, 0x32, par);	vga_out8(0x3d5, reg->CR32, par);	/* unlock extended seq regs */	vga_out8(0x3c4, 0x08, par);	vga_out8(0x3c5, 0x06, par);	/* Restore extended sequencer regs for MCLK. SR10 == 255 indicates	 * that we should leave the default SR10 and SR11 values there.	 */	if (reg->SR10 != 255) {		vga_out8(0x3c4, 0x10, par);		vga_out8(0x3c5, reg->SR10, par);		vga_out8(0x3c4, 0x11, par);		vga_out8(0x3c5, reg->SR11, par);	}	/* restore extended seq regs for dclk */	vga_out8(0x3c4, 0x0e, par);	vga_out8(0x3c5, reg->SR0E, par);	vga_out8(0x3c4, 0x0f, par);	vga_out8(0x3c5, reg->SR0F, par);	vga_out8(0x3c4, 0x12, par);	vga_out8(0x3c5, reg->SR12, par);	vga_out8(0x3c4, 0x13, par);	vga_out8(0x3c5, reg->SR13, par);	vga_out8(0x3c4, 0x29, par);	vga_out8(0x3c5, reg->SR29, par);	vga_out8(0x3c4, 0x18, par);	vga_out8(0x3c5, reg->SR18, par);	/* load new m, n pll values for dclk & mclk */	vga_out8(0x3c4, 0x15, par);	tmp = vga_in8(0x3c5, par) & ~0x21;	vga_out8(0x3c5, tmp | 0x03, par);	vga_out8(0x3c5, tmp | 0x23, par);	vga_out8(0x3c5, tmp | 0x03, par);	vga_out8(0x3c5, reg->SR15, par);	udelay(100);	vga_out8(0x3c4, 0x30, par);	vga_out8(0x3c5, reg->SR30, par);	vga_out8(0x3c4, 0x08, par);	vga_out8(0x3c5, reg->SR08, par);	/* now write out cr67 in full, possibly starting STREAMS */	VerticalRetraceWait(par);	vga_out8(0x3d4, 0x67, par);	vga_out8(0x3d5, reg->CR67, par);	vga_out8(0x3d4, 0x66, par);	cr66 = vga_in8(0x3d5, par);	vga_out8(0x3d5, cr66 | 0x80, par);	vga_out8(0x3d4, 0x3a, par);	cr3a = vga_in8(0x3d5, par);	vga_out8(0x3d5, cr3a | 0x80, par);	if (par->chip != S3_SAVAGE_MX) {		VerticalRetraceWait(par);		savage_out32(FIFO_CONTROL_REG, reg->MMPR0, par);		par->SavageWaitIdle(par);		savage_out32(MIU_CONTROL_REG, reg->MMPR1, par);		par->SavageWaitIdle(par);		savage_out32(STREAMS_TIMEOUT_REG, reg->MMPR2, par);		par->SavageWaitIdle(par);		savage_out32(MISC_TIMEOUT_REG, reg->MMPR3, par);	}	vga_out8(0x3d4, 0x66, par);	vga_out8(0x3d5, cr66, par);	vga_out8(0x3d4, 0x3a, par);	vga_out8(0x3d5, cr3a, par);	SavageSetup2DEngine(par);	vgaHWProtect(par, 0);}static void savagefb_update_start(struct savagefb_par      *par,				  struct fb_var_screeninfo *var){	int base;	base = ((var->yoffset * var->xres_virtual + (var->xoffset & ~1))		* ((var->bits_per_pixel+7) / 8)) >> 2;	/* now program the start address registers */	vga_out16(0x3d4, (base & 0x00ff00) | 0x0c, par);	vga_out16(0x3d4, ((base & 0x00ff) << 8) | 0x0d, par);	vga_out8(0x3d4, 0x69, par);	vga_out8(0x3d5, (base & 0x7f0000) >> 16, par);}static void savagefb_set_fix(struct fb_info *info){	info->fix.line_length = info->var.xres_virtual *		info->var.bits_per_pixel / 8;	if (info->var.bits_per_pixel == 8) {		info->fix.visual      = FB_VISUAL_PSEUDOCOLOR;		info->fix.xpanstep    = 4;	} else {		info->fix.visual      = FB_VISUAL_TRUECOLOR;		info->fix.xpanstep    = 2;	}}static int savagefb_set_par(struct fb_info *info){	struct savagefb_par *par = info->par;	struct fb_var_screeninfo *var = &info->var;	int err;	DBG("savagefb_set_par");	err = savagefb_decode_var(var, par, &par->state);	if (err)		return err;	if (par->dacSpeedBpp <= 0) {		if (var->bits_per_pixel > 24)			par->dacSpeedBpp = par->clock[3];		else if (var->bits_per_pixel >= 24)			par->dacSpeedBpp = par->clock[2];

⌨️ 快捷键说明

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