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

📄 savagefb_driver.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * linux/drivers/video/savagefb.c -- S3 Savage Framebuffer Driver * * Copyright (c) 2001-2002  Denis Oliver Kropp <dok@directfb.org> *                          Sven Neumann <neo@directfb.org> * * * Card specific code is based on XFree86's savage driver. * Framebuffer framework code is based on code of cyber2000fb and tdfxfb. * * This file is subject to the terms and conditions of the GNU General * Public License.  See the file COPYING in the main directory of this * archive for more details. * * 0.4.0 (neo) *  - hardware accelerated clear and move * * 0.3.2 (dok) *  - wait for vertical retrace before writing to cr67 *    at the beginning of savagefb_set_par *  - use synchronization registers cr23 and cr26 * * 0.3.1 (dok) *  - reset 3D engine *  - don't return alpha bits for 32bit format * * 0.3.0 (dok) *  - added WaitIdle functions for all Savage types *  - do WaitIdle before mode switching *  - code cleanup * * 0.2.0 (dok) *  - first working version * * * TODO * - clock validations in decode_var * * BUGS * - white margin on bootup * */#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/pci.h>#include <linux/init.h>#include <linux/console.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/pgtable.h>#include <asm/system.h>#include <asm/uaccess.h>#ifdef CONFIG_MTRR#include <asm/mtrr.h>#endif#include "savagefb.h"#define SAVAGEFB_VERSION "0.4.0_2.6"/* --------------------------------------------------------------------- */static char *mode_option __initdata = NULL;#ifdef MODULEMODULE_AUTHOR("(c) 2001-2002  Denis Oliver Kropp <dok@directfb.org>");MODULE_LICENSE("GPL");MODULE_DESCRIPTION("FBDev driver for S3 Savage PCI/AGP Chips");#endif/* --------------------------------------------------------------------- */static void vgaHWSeqReset (struct savagefb_par *par, int start){	if (start)		VGAwSEQ (0x00, 0x01, par);	/* Synchronous Reset */	else		VGAwSEQ (0x00, 0x03, par);	/* End Reset */}static void vgaHWProtect (struct savagefb_par *par, int on){	unsigned char tmp;	if (on) {		/*		 * Turn off screen and disable sequencer.		 */		tmp = VGArSEQ (0x01, par);		vgaHWSeqReset (par, 1);	        /* start synchronous reset */		VGAwSEQ (0x01, tmp | 0x20, par);/* disable the display */		VGAenablePalette(par);	} else {		/*		 * Reenable sequencer, then turn on screen.		 */		tmp = VGArSEQ (0x01, par);		VGAwSEQ (0x01, tmp & ~0x20, par);/* reenable display */		vgaHWSeqReset (par, 0);	        /* clear synchronous reset */		VGAdisablePalette(par);	}}static void vgaHWRestore (struct savagefb_par  *par){	int i;	VGAwMISC (par->MiscOutReg, par);	for (i = 1; i < 5; i++)		VGAwSEQ (i, par->Sequencer[i], par);	/* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 or	   CRTC[17] */	VGAwCR (17, par->CRTC[17] & ~0x80, par);	for (i = 0; i < 25; i++)		VGAwCR (i, par->CRTC[i], par);	for (i = 0; i < 9; i++)		VGAwGR (i, par->Graphics[i], par);	VGAenablePalette(par);	for (i = 0; i < 21; i++)		VGAwATTR (i, par->Attribute[i], par);	VGAdisablePalette(par);}static void vgaHWInit (struct fb_var_screeninfo *var,		       struct savagefb_par            *par,		       struct xtimings                *timings){	par->MiscOutReg = 0x23;	if (!(timings->sync & FB_SYNC_HOR_HIGH_ACT))		par->MiscOutReg |= 0x40;	if (!(timings->sync & FB_SYNC_VERT_HIGH_ACT))		par->MiscOutReg |= 0x80;	/*	 * Time Sequencer	 */	par->Sequencer[0x00] = 0x00;	par->Sequencer[0x01] = 0x01;	par->Sequencer[0x02] = 0x0F;	par->Sequencer[0x03] = 0x00;          /* Font select */	par->Sequencer[0x04] = 0x0E;          /* Misc */	/*	 * CRTC Controller	 */	par->CRTC[0x00] = (timings->HTotal >> 3) - 5;	par->CRTC[0x01] = (timings->HDisplay >> 3) - 1;	par->CRTC[0x02] = (timings->HSyncStart >> 3) - 1;	par->CRTC[0x03] = (((timings->HSyncEnd >> 3)  - 1) & 0x1f) | 0x80;	par->CRTC[0x04] = (timings->HSyncStart >> 3);	par->CRTC[0x05] = ((((timings->HSyncEnd >> 3) - 1) & 0x20) << 2) |		(((timings->HSyncEnd >> 3)) & 0x1f);	par->CRTC[0x06] = (timings->VTotal - 2) & 0xFF;	par->CRTC[0x07] = (((timings->VTotal - 2) & 0x100) >> 8) |		(((timings->VDisplay - 1) & 0x100) >> 7) |		((timings->VSyncStart & 0x100) >> 6) |		(((timings->VSyncStart - 1) & 0x100) >> 5) |		0x10 |		(((timings->VTotal - 2) & 0x200) >> 4) |		(((timings->VDisplay - 1) & 0x200) >> 3) |		((timings->VSyncStart & 0x200) >> 2);	par->CRTC[0x08] = 0x00;	par->CRTC[0x09] = (((timings->VSyncStart - 1) & 0x200) >> 4) | 0x40;	if (timings->dblscan)		par->CRTC[0x09] |= 0x80;	par->CRTC[0x0a] = 0x00;	par->CRTC[0x0b] = 0x00;	par->CRTC[0x0c] = 0x00;	par->CRTC[0x0d] = 0x00;	par->CRTC[0x0e] = 0x00;	par->CRTC[0x0f] = 0x00;	par->CRTC[0x10] = timings->VSyncStart & 0xff;	par->CRTC[0x11] = (timings->VSyncEnd & 0x0f) | 0x20;	par->CRTC[0x12] = (timings->VDisplay - 1) & 0xff;	par->CRTC[0x13] = var->xres_virtual >> 4;	par->CRTC[0x14] = 0x00;	par->CRTC[0x15] = (timings->VSyncStart - 1) & 0xff;	par->CRTC[0x16] = (timings->VSyncEnd - 1) & 0xff;	par->CRTC[0x17] = 0xc3;	par->CRTC[0x18] = 0xff;	/*	 * are these unnecessary?	 * vgaHWHBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN|KGA_ENABLE_ON_ZERO);	 * vgaHWVBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN|KGA_ENABLE_ON_ZERO);	 */	/*	 * Graphics Display Controller	 */	par->Graphics[0x00] = 0x00;	par->Graphics[0x01] = 0x00;	par->Graphics[0x02] = 0x00;	par->Graphics[0x03] = 0x00;	par->Graphics[0x04] = 0x00;	par->Graphics[0x05] = 0x40;	par->Graphics[0x06] = 0x05;   /* only map 64k VGA memory !!!! */	par->Graphics[0x07] = 0x0F;	par->Graphics[0x08] = 0xFF;	par->Attribute[0x00]  = 0x00; /* standard colormap translation */	par->Attribute[0x01]  = 0x01;	par->Attribute[0x02]  = 0x02;	par->Attribute[0x03]  = 0x03;	par->Attribute[0x04]  = 0x04;	par->Attribute[0x05]  = 0x05;	par->Attribute[0x06]  = 0x06;	par->Attribute[0x07]  = 0x07;	par->Attribute[0x08]  = 0x08;	par->Attribute[0x09]  = 0x09;	par->Attribute[0x0a] = 0x0A;	par->Attribute[0x0b] = 0x0B;	par->Attribute[0x0c] = 0x0C;	par->Attribute[0x0d] = 0x0D;	par->Attribute[0x0e] = 0x0E;	par->Attribute[0x0f] = 0x0F;	par->Attribute[0x10] = 0x41;	par->Attribute[0x11] = 0xFF;	par->Attribute[0x12] = 0x0F;	par->Attribute[0x13] = 0x00;	par->Attribute[0x14] = 0x00;}/* -------------------- Hardware specific routines ------------------------- *//* * Hardware Acceleration for SavageFB *//* Wait for fifo space */static voidsavage3D_waitfifo(struct savagefb_par *par, int space){	int slots = MAXFIFO - space;	while ((savage_in32(0x48C00, par) & 0x0000ffff) > slots);}static voidsavage4_waitfifo(struct savagefb_par *par, int space){	int slots = MAXFIFO - space;	while ((savage_in32(0x48C60, par) & 0x001fffff) > slots);}static voidsavage2000_waitfifo(struct savagefb_par *par, int space){	int slots = MAXFIFO - space;	while ((savage_in32(0x48C60, par) & 0x0000ffff) > slots);}/* Wait for idle accelerator */static voidsavage3D_waitidle(struct savagefb_par *par){	while ((savage_in32(0x48C00, par) & 0x0008ffff) != 0x80000);}static voidsavage4_waitidle(struct savagefb_par *par){	while ((savage_in32(0x48C60, par) & 0x00a00000) != 0x00a00000);}static voidsavage2000_waitidle(struct savagefb_par *par){	while ((savage_in32(0x48C60, par) & 0x009fffff));}static voidSavageSetup2DEngine (struct savagefb_par  *par){	unsigned long GlobalBitmapDescriptor;	GlobalBitmapDescriptor = 1 | 8 | BCI_BD_BW_DISABLE;	BCI_BD_SET_BPP (GlobalBitmapDescriptor, par->depth);	BCI_BD_SET_STRIDE (GlobalBitmapDescriptor, par->vwidth);	switch(par->chip) {	case S3_SAVAGE3D:	case S3_SAVAGE_MX:		/* Disable BCI */		savage_out32(0x48C18, savage_in32(0x48C18, par) & 0x3FF0, par);		/* Setup BCI command overflow buffer */		savage_out32(0x48C14,			     (par->cob_offset >> 11) | (par->cob_index << 29),			     par);		/* Program shadow status update. */		savage_out32(0x48C10, 0x78207220, par);		savage_out32(0x48C0C, 0, par);		/* Enable BCI and command overflow buffer */		savage_out32(0x48C18, savage_in32(0x48C18, par) | 0x0C, par);		break;	case S3_SAVAGE4:	case S3_PROSAVAGE:	case S3_SUPERSAVAGE:		/* Disable BCI */		savage_out32(0x48C18, savage_in32(0x48C18, par) & 0x3FF0, par);		/* Program shadow status update */		savage_out32(0x48C10, 0x00700040, par);		savage_out32(0x48C0C, 0, par);		/* Enable BCI without the COB */		savage_out32(0x48C18, savage_in32(0x48C18, par) | 0x08, par);		break;	case S3_SAVAGE2000:		/* Disable BCI */		savage_out32(0x48C18, 0, par);		/* Setup BCI command overflow buffer */		savage_out32(0x48C18,			     (par->cob_offset >> 7) | (par->cob_index),			     par);		/* Disable shadow status update */		savage_out32(0x48A30, 0, par);		/* Enable BCI and command overflow buffer */		savage_out32(0x48C18, savage_in32(0x48C18, par) | 0x00280000,			     par);		break;	    default:		break;	}	/* Turn on 16-bit register access. */	vga_out8(0x3d4, 0x31, par);	vga_out8(0x3d5, 0x0c, par);	/* Set stride to use GBD. */	vga_out8 (0x3d4, 0x50, par);	vga_out8 (0x3d5, vga_in8(0x3d5, par) | 0xC1, par);	/* Enable 2D engine. */	vga_out8 (0x3d4, 0x40, par);	vga_out8 (0x3d5, 0x01, par);	savage_out32 (MONO_PAT_0, ~0, par);	savage_out32 (MONO_PAT_1, ~0, par);	/* Setup plane masks */	savage_out32 (0x8128, ~0, par); /* enable all write planes */	savage_out32 (0x812C, ~0, par); /* enable all read planes */	savage_out16 (0x8134, 0x27, par);	savage_out16 (0x8136, 0x07, par);	/* Now set the GBD */	par->bci_ptr = 0;	par->SavageWaitFifo (par, 4);	BCI_SEND( BCI_CMD_SETREG | (1 << 16) | BCI_GBD1 );	BCI_SEND( 0 );	BCI_SEND( BCI_CMD_SETREG | (1 << 16) | BCI_GBD2 );	BCI_SEND( GlobalBitmapDescriptor );}static void SavageCalcClock(long freq, int min_m, int min_n1, int max_n1,			    int min_n2, int max_n2, long freq_min,			    long freq_max, unsigned int *mdiv,			    unsigned int *ndiv, unsigned int *r){	long diff, best_diff;	unsigned int m;	unsigned char n1, n2, best_n1=16+2, best_n2=2, best_m=125+2;	if (freq < freq_min / (1 << max_n2)) {		printk (KERN_ERR "invalid frequency %ld Khz\n", freq);		freq = freq_min / (1 << max_n2);	}	if (freq > freq_max / (1 << min_n2)) {		printk (KERN_ERR "invalid frequency %ld Khz\n", freq);		freq = freq_max / (1 << min_n2);	}	/* work out suitable timings */	best_diff = freq;	for (n2=min_n2; n2<=max_n2; n2++) {		for (n1=min_n1+2; n1<=max_n1+2; n1++) {			m = (freq * n1 * (1 << n2) + HALF_BASE_FREQ) /				BASE_FREQ;			if (m < min_m+2 || m > 127+2)				continue;			if ((m * BASE_FREQ >= freq_min * n1) &&			    (m * BASE_FREQ <= freq_max * n1)) {				diff = freq * (1 << n2) * n1 - BASE_FREQ * m;				if (diff < 0)					diff = -diff;				if (diff < best_diff) {					best_diff = diff;					best_m = m;					best_n1 = n1;					best_n2 = n2;				}			}		}	}	*ndiv = best_n1 - 2;	*r = best_n2;	*mdiv = best_m - 2;}static int common_calc_clock(long freq, int min_m, int min_n1, int max_n1,			     int min_n2, int max_n2, long freq_min,			     long freq_max, unsigned char *mdiv,			     unsigned char *ndiv){	long diff, best_diff;	unsigned int m;	unsigned char n1, n2;	unsigned char best_n1 = 16+2, best_n2 = 2, best_m = 125+2;	best_diff = freq;	for (n2 = min_n2; n2 <= max_n2; n2++) {		for (n1 = min_n1+2; n1 <= max_n1+2; n1++) {			m = (freq * n1 * (1 << n2) + HALF_BASE_FREQ) /				BASE_FREQ;			if (m < min_m + 2 || m > 127+2)				continue;			if((m * BASE_FREQ >= freq_min * n1) &&			   (m * BASE_FREQ <= freq_max * n1)) {				diff = freq * (1 << n2) * n1 - BASE_FREQ * m;				if(diff < 0)					diff = -diff;				if(diff < best_diff) {					best_diff = diff;					best_m = m;					best_n1 = n1;					best_n2 = n2;				}			}		}	}	if(max_n1 == 63)		*ndiv = (best_n1 - 2) | (best_n2 << 6);	else		*ndiv = (best_n1 - 2) | (best_n2 << 5);	*mdiv = best_m - 2;	return 0;}#ifdef SAVAGEFB_DEBUG/* This function is used to debug, it prints out the contents of s3 regs */static void SavagePrintRegs(void){	unsigned char i;	int vgaCRIndex = 0x3d4;	int vgaCRReg = 0x3d5;	printk(KERN_DEBUG "SR    x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE "	       "xF" );	for( i = 0; i < 0x70; i++ ) {		if( !(i % 16) )			printk(KERN_DEBUG "\nSR%xx ", i >> 4 );		vga_out8( 0x3c4, i, par);		printk(KERN_DEBUG " %02x", vga_in8(0x3c5, par) );	}	printk(KERN_DEBUG "\n\nCR    x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC "	       "xD xE xF" );	for( i = 0; i < 0xB7; i++ ) {		if( !(i % 16) )			printk(KERN_DEBUG "\nCR%xx ", i >> 4 );		vga_out8( vgaCRIndex, i, par);		printk(KERN_DEBUG " %02x", vga_in8(vgaCRReg, par) );	}	printk(KERN_DEBUG "\n\n");}#endif/* --------------------------------------------------------------------- */static void savage_get_default_par(struct savagefb_par *par){	unsigned char cr3a, cr53, cr66;	vga_out16 (0x3d4, 0x4838, par);	vga_out16 (0x3d4, 0xa039, par);	vga_out16 (0x3c4, 0x0608, 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);	vga_out8 (0x3d4, 0x53, par);	cr53 = vga_in8 (0x3d5, par);	vga_out8 (0x3d5, cr53 & 0x7f, par);	vga_out8 (0x3d4, 0x66, par);	vga_out8 (0x3d5, cr66, par);	vga_out8 (0x3d4, 0x3a, par);	vga_out8 (0x3d5, cr3a, par);	vga_out8 (0x3d4, 0x66, par);	vga_out8 (0x3d5, cr66, par);	vga_out8 (0x3d4, 0x3a, par);	vga_out8 (0x3d5, cr3a, par);	/* unlock extended seq regs */	vga_out8 (0x3c4, 0x08, par);	par->SR08 = vga_in8 (0x3c5, par);	vga_out8 (0x3c5, 0x06, par);	/* now save all the extended regs we need */	vga_out8 (0x3d4, 0x31, par);	par->CR31 = vga_in8 (0x3d5, par);	vga_out8 (0x3d4, 0x32, par);	par->CR32 = vga_in8 (0x3d5, par);	vga_out8 (0x3d4, 0x34, par);	par->CR34 = vga_in8 (0x3d5, par);	vga_out8 (0x3d4, 0x36, par);	par->CR36 = vga_in8 (0x3d5, par);	vga_out8 (0x3d4, 0x3a, par);	par->CR3A = vga_in8 (0x3d5, par);	vga_out8 (0x3d4, 0x40, par);	par->CR40 = vga_in8 (0x3d5, par);	vga_out8 (0x3d4, 0x42, par);	par->CR42 = vga_in8 (0x3d5, par);	vga_out8 (0x3d4, 0x45, par);	par->CR45 = vga_in8 (0x3d5, par);	vga_out8 (0x3d4, 0x50, par);	par->CR50 = vga_in8 (0x3d5, par);	vga_out8 (0x3d4, 0x51, par);	par->CR51 = vga_in8 (0x3d5, par);	vga_out8 (0x3d4, 0x53, par);	par->CR53 = vga_in8 (0x3d5, par);	vga_out8 (0x3d4, 0x58, par);	par->CR58 = vga_in8 (0x3d5, par);	vga_out8 (0x3d4, 0x60, par);	par->CR60 = vga_in8 (0x3d5, par);	vga_out8 (0x3d4, 0x66, par);	par->CR66 = vga_in8 (0x3d5, par);	vga_out8 (0x3d4, 0x67, par);	par->CR67 = vga_in8 (0x3d5, par);	vga_out8 (0x3d4, 0x68, par);	par->CR68 = vga_in8 (0x3d5, par);	vga_out8 (0x3d4, 0x69, par);	par->CR69 = vga_in8 (0x3d5, par);	vga_out8 (0x3d4, 0x6f, par);	par->CR6F = vga_in8 (0x3d5, par);	vga_out8 (0x3d4, 0x33, par);	par->CR33 = vga_in8 (0x3d5, par);	vga_out8 (0x3d4, 0x86, par);	par->CR86 = vga_in8 (0x3d5, par);	vga_out8 (0x3d4, 0x88, par);	par->CR88 = vga_in8 (0x3d5, par);	vga_out8 (0x3d4, 0x90, par);	par->CR90 = vga_in8 (0x3d5, par);	vga_out8 (0x3d4, 0x91, par);

⌨️ 快捷键说明

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