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

📄 vga16fb.c

📁 S3C44B0X下的LCD (framebuffer)驱动资料与相关代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * linux/drivers/video/vga16.c -- VGA 16-color framebuffer driver *  * Copyright 1999 Ben Pfaff <pfaffben@debian.org> and Petr Vandrovec <VANDROVE@vc.cvut.cz> * Based on VGA info at http://www.goodnet.com/~tinara/FreeVGA/home.htm * Based on VESA framebuffer (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de> * * 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.  */#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 <asm/io.h>#include <video/fbcon.h>#include <video/fbcon-vga-planes.h>#include "vga.h"#define dac_reg	(0x3c8)#define dac_val	(0x3c9)#define VGA_FB_PHYS 0xA0000#define VGA_FB_PHYS_LEN 65536/* --------------------------------------------------------------------- *//* * card parameters */static struct vga16fb_info {	struct fb_info  fb_info;	char *video_vbase;			/* 0xa0000 map address */	int isVGA;		/* structure holding original VGA register settings when the           screen is blanked */	struct {		unsigned char	SeqCtrlIndex;		/* Sequencer Index reg.   */		unsigned char	CrtCtrlIndex;		/* CRT-Contr. Index reg.  */		unsigned char	CrtMiscIO;		/* Miscellaneous register */		unsigned char	HorizontalTotal;	/* CRT-Controller:00h */		unsigned char	HorizDisplayEnd;	/* CRT-Controller:01h */		unsigned char	StartHorizRetrace;	/* CRT-Controller:04h */		unsigned char	EndHorizRetrace;	/* CRT-Controller:05h */		unsigned char	Overflow;		/* CRT-Controller:07h */		unsigned char	StartVertRetrace;	/* CRT-Controller:10h */		unsigned char	EndVertRetrace;		/* CRT-Controller:11h */		unsigned char	ModeControl;		/* CRT-Controller:17h */		unsigned char	ClockingMode;		/* Seq-Controller:01h */	} vga_state;	int palette_blanked;	int vesa_blanked;} vga16fb;struct vga16fb_par {	u8 crtc[VGA_CRT_C];	u8 atc[VGA_ATT_C];	u8 gdc[VGA_GFX_C];	u8 seq[VGA_SEQ_C];	u8 misc;	u8 vss;	struct fb_var_screeninfo var;};/* --------------------------------------------------------------------- */static struct fb_var_screeninfo vga16fb_defined = {	640,480,640,480,/* W,H, W, H (virtual) load xres,xres_virtual*/	0,0,		/* virtual -> visible no offset */	4,		/* depth -> load bits_per_pixel */	0,		/* greyscale ? */	{0,0,0},	/* R */	{0,0,0},	/* G */	{0,0,0},	/* B */	{0,0,0},	/* transparency */	0,		/* standard pixel format */	FB_ACTIVATE_NOW,	-1,-1,	0,	39721, 48, 16, 39, 8,	96, 2, 0,	/* No sync info */	FB_VMODE_NONINTERLACED,	{0,0,0,0,0,0}};static struct display disp;static struct { u_short blue, green, red, pad; } palette[256];static int             currcon   = 0;/* --------------------------------------------------------------------- */static void vga16fb_pan_var(struct fb_info *info, struct fb_var_screeninfo *var){	u32 pos = (var->xres_virtual * var->yoffset + var->xoffset) >> 3;	outb(VGA_CRTC_START_HI, VGA_CRT_IC);	outb(pos >> 8, VGA_CRT_DC);	outb(VGA_CRTC_START_LO, VGA_CRT_IC);	outb(pos & 0xFF, VGA_CRT_DC);#if 0	/* if someone supports xoffset in bit resolution */	inb(VGA_IS1_RC);		/* reset flip-flop */	outb(VGA_ATC_PEL, VGA_ATT_IW);	outb(xoffset & 7, VGA_ATT_IW);	inb(VGA_IS1_RC);	outb(0x20, VGA_ATT_IW);#endif}static int vga16fb_update_var(int con, struct fb_info *info){	vga16fb_pan_var(info, &fb_display[con].var);	return 0;}static int vga16fb_get_fix(struct fb_fix_screeninfo *fix, int con,			   struct fb_info *info){	struct display *p;	if (con < 0)		p = &disp;	else		p = fb_display + con;	memset(fix, 0, sizeof(struct fb_fix_screeninfo));	strcpy(fix->id,"VGA16 VGA");	fix->smem_start = VGA_FB_PHYS;	fix->smem_len = VGA_FB_PHYS_LEN;	fix->type = FB_TYPE_VGA_PLANES;	fix->visual = FB_VISUAL_PSEUDOCOLOR;	fix->xpanstep  = 8;	fix->ypanstep  = 1;	fix->ywrapstep = 0;	fix->line_length = p->var.xres_virtual / 8;	return 0;}static int vga16fb_get_var(struct fb_var_screeninfo *var, int con,			 struct fb_info *info){	if(con==-1)		memcpy(var, &vga16fb_defined, sizeof(struct fb_var_screeninfo));	else		*var=fb_display[con].var;	return 0;}static void vga16fb_set_disp(int con, struct vga16fb_info *info){	struct fb_fix_screeninfo fix;	struct display *display;	if (con < 0)		display = &disp;	else		display = fb_display + con;		vga16fb_get_fix(&fix, con, &info->fb_info);	display->screen_base = info->video_vbase;	display->visual = fix.visual;	display->type = fix.type;	display->type_aux = fix.type_aux;	display->ypanstep = fix.ypanstep;	display->ywrapstep = fix.ywrapstep;	display->line_length = fix.line_length;	display->next_line = fix.line_length;	display->can_soft_blank = 1;	display->inverse = 0;	if (info->isVGA)		display->dispsw = &fbcon_vga_planes;	else		display->dispsw = &fbcon_ega_planes;	display->scrollmode = SCROLL_YREDRAW;}static void vga16fb_encode_var(struct fb_var_screeninfo *var,			       const struct vga16fb_par *par,			       const struct vga16fb_info *info){	*var = par->var;}static void vga16fb_clock_chip(struct vga16fb_par *par,			       unsigned int pixclock,			       const struct vga16fb_info *info){	static struct {		u32 pixclock;		u8  misc;		u8  seq_clock_mode;	} *ptr, *best, vgaclocks[] = {		{ 79442 /* 12.587 */, 0x00, 0x08},		{ 70616 /* 14.161 */, 0x04, 0x08},		{ 39721 /* 25.175 */, 0x00, 0x00},		{ 35308 /* 28.322 */, 0x04, 0x00},		{     0 /* bad */,    0x00, 0x00}};	int err;	best = vgaclocks;	err = pixclock - best->pixclock;	if (err < 0) err = -err;	for (ptr = vgaclocks + 1; ptr->pixclock; ptr++) {		int tmp;		tmp = pixclock - ptr->pixclock;		if (tmp < 0) tmp = -tmp;		if (tmp < err) {			err = tmp;			best = ptr;		}	}	par->misc |= best->misc;	par->seq[VGA_SEQ_CLOCK_MODE] |= best->seq_clock_mode;	par->var.pixclock = best->pixclock;		}			       #define FAIL(X) return -EINVALstatic int vga16fb_decode_var(const struct fb_var_screeninfo *var,			      struct vga16fb_par *par,			      const struct vga16fb_info *info){	u32 xres, right, hslen, left, xtotal;	u32 yres, lower, vslen, upper, ytotal;	u32 vxres, xoffset, vyres, yoffset;	u32 pos;	u8 r7, rMode;	int i;	if (var->bits_per_pixel != 4)		return -EINVAL;	xres = (var->xres + 7) & ~7;	vxres = (var->xres_virtual + 0xF) & ~0xF;	xoffset = (var->xoffset + 7) & ~7;	left = (var->left_margin + 7) & ~7;	right = (var->right_margin + 7) & ~7;	hslen = (var->hsync_len + 7) & ~7;	if (vxres < xres)		vxres = xres;	if (xres + xoffset > vxres)		xoffset = vxres - xres;	par->var.xres = xres;	par->var.right_margin = right;	par->var.hsync_len = hslen;	par->var.left_margin = left;	par->var.xres_virtual = vxres;	par->var.xoffset = xoffset;	xres >>= 3;	right >>= 3;	hslen >>= 3;	left >>= 3;	vxres >>= 3;	xtotal = xres + right + hslen + left;	if (xtotal >= 256)		FAIL("xtotal too big");	if (hslen > 32)		FAIL("hslen too big");	if (right + hslen + left > 64)		FAIL("hblank too big");	par->crtc[VGA_CRTC_H_TOTAL] = xtotal - 5;	par->crtc[VGA_CRTC_H_BLANK_START] = xres - 1;	par->crtc[VGA_CRTC_H_DISP] = xres - 1;	pos = xres + right;	par->crtc[VGA_CRTC_H_SYNC_START] = pos;	pos += hslen;	par->crtc[VGA_CRTC_H_SYNC_END] = pos & 0x1F;	pos += left - 2; /* blank_end + 2 <= total + 5 */	par->crtc[VGA_CRTC_H_BLANK_END] = (pos & 0x1F) | 0x80;	if (pos & 0x20)		par->crtc[VGA_CRTC_H_SYNC_END] |= 0x80;	yres = var->yres;	lower = var->lower_margin;	vslen = var->vsync_len;	upper = var->upper_margin;	vyres = var->yres_virtual;	yoffset = var->yoffset;	if (yres > vyres)		vyres = yres;	if (vxres * vyres > 65536) {		vyres = 65536 / vxres;		if (vyres < yres)			return -ENOMEM;	}	if (yoffset + yres > vyres)		yoffset = vyres - yres;	par->var.yres = yres;	par->var.lower_margin = lower;	par->var.vsync_len = vslen;	par->var.upper_margin = upper;	par->var.yres_virtual = vyres;	par->var.yoffset = yoffset;	if (var->vmode & FB_VMODE_DOUBLE) {		yres <<= 1;		lower <<= 1;		vslen <<= 1;		upper <<= 1;	}	ytotal = yres + lower + vslen + upper;	if (ytotal > 1024) {		ytotal >>= 1;		yres >>= 1;		lower >>= 1;		vslen >>= 1;		upper >>= 1;		rMode = 0x04;	} else		rMode = 0x00;	if (ytotal > 1024)		FAIL("ytotal too big");	if (vslen > 16)		FAIL("vslen too big");	par->crtc[VGA_CRTC_V_TOTAL] = ytotal - 2;	r7 = 0x10;	/* disable linecompare */	if (ytotal & 0x100) r7 |= 0x01;	if (ytotal & 0x200) r7 |= 0x20;	par->crtc[VGA_CRTC_PRESET_ROW] = 0;	par->crtc[VGA_CRTC_MAX_SCAN] = 0x40;	/* 1 scanline, no linecmp */	par->var.vmode = var->vmode;	if (var->vmode & FB_VMODE_DOUBLE)		par->crtc[VGA_CRTC_MAX_SCAN] |= 0x80;	par->crtc[VGA_CRTC_CURSOR_START] = 0x20;	par->crtc[VGA_CRTC_CURSOR_END]   = 0x00;	pos = yoffset * vxres + (xoffset >> 3);	par->crtc[VGA_CRTC_START_HI]     = pos >> 8;	par->crtc[VGA_CRTC_START_LO]     = pos & 0xFF;	par->crtc[VGA_CRTC_CURSOR_HI]    = 0x00;	par->crtc[VGA_CRTC_CURSOR_LO]    = 0x00;	pos = yres - 1;	par->crtc[VGA_CRTC_V_DISP_END] = pos & 0xFF;	par->crtc[VGA_CRTC_V_BLANK_START] = pos & 0xFF;	if (pos & 0x100)		r7 |= 0x0A;	/* 0x02 -> DISP_END, 0x08 -> BLANK_START */	if (pos & 0x200) {		r7 |= 0x40;	/* 0x40 -> DISP_END */		par->crtc[VGA_CRTC_MAX_SCAN] |= 0x20; /* BLANK_START */	}	pos += lower;	par->crtc[VGA_CRTC_V_SYNC_START] = pos & 0xFF;	if (pos & 0x100)		r7 |= 0x04;	if (pos & 0x200)		r7 |= 0x80;	pos += vslen;	par->crtc[VGA_CRTC_V_SYNC_END] = (pos & 0x0F) & ~0x10; /* disabled IRQ */	pos += upper - 1; /* blank_end + 1 <= ytotal + 2 */	par->crtc[VGA_CRTC_V_BLANK_END] = pos & 0xFF; /* 0x7F for original VGA,                     but some SVGA chips requires all 8 bits to set */	if (vxres >= 512)		FAIL("vxres too long");	par->crtc[VGA_CRTC_OFFSET] = vxres >> 1;	par->crtc[VGA_CRTC_UNDERLINE] = 0x1F;	par->crtc[VGA_CRTC_MODE] = rMode | 0xE3;	par->crtc[VGA_CRTC_LINE_COMPARE] = 0xFF;	par->crtc[VGA_CRTC_OVERFLOW] = r7;	par->vss = 0x00;	/* 3DA */	for (i = 0x00; i < 0x10; i++)		par->atc[i] = i;	par->atc[VGA_ATC_MODE] = 0x81;	par->atc[VGA_ATC_OVERSCAN] = 0x00;	/* 0 for EGA, 0xFF for VGA */	par->atc[VGA_ATC_PLANE_ENABLE] = 0x0F;	par->atc[VGA_ATC_PEL] = xoffset & 7;	par->atc[VGA_ATC_COLOR_PAGE] = 0x00;		par->misc = 0xC3;	/* enable CPU, ports 0x3Dx, positive sync */	par->var.sync = var->sync;	if (var->sync & FB_SYNC_HOR_HIGH_ACT)		par->misc &= ~0x40;	if (var->sync & FB_SYNC_VERT_HIGH_ACT)		par->misc &= ~0x80;		par->seq[VGA_SEQ_CLOCK_MODE] = 0x01;	par->seq[VGA_SEQ_PLANE_WRITE] = 0x0F;	par->seq[VGA_SEQ_CHARACTER_MAP] = 0x00;	par->seq[VGA_SEQ_MEMORY_MODE] = 0x06;		par->gdc[VGA_GFX_SR_VALUE] = 0x00;	par->gdc[VGA_GFX_SR_ENABLE] = 0x0F;	par->gdc[VGA_GFX_COMPARE_VALUE] = 0x00;	par->gdc[VGA_GFX_DATA_ROTATE] = 0x20;	par->gdc[VGA_GFX_PLANE_READ] = 0;	par->gdc[VGA_GFX_MODE] = 0x00;	par->gdc[VGA_GFX_MISC] = 0x05;	par->gdc[VGA_GFX_COMPARE_MASK] = 0x0F;	par->gdc[VGA_GFX_BIT_MASK] = 0xFF;	vga16fb_clock_chip(par, var->pixclock, info);	par->var.bits_per_pixel = 4;	par->var.grayscale = var->grayscale;	par->var.red.offset = par->var.green.offset = par->var.blue.offset = 	par->var.transp.offset = 0;	par->var.red.length = par->var.green.length = par->var.blue.length =		(info->isVGA) ? 6 : 2;	par->var.transp.length = 0;	par->var.nonstd = 0;	par->var.activate = FB_ACTIVATE_NOW;	par->var.height = -1;	par->var.width = -1;	par->var.accel_flags = 0;		return 0;}#undef FAILstatic int vga16fb_set_par(const struct vga16fb_par *par,			   struct vga16fb_info *info){	int i;	outb(inb(VGA_MIS_R) | 0x01, VGA_MIS_W);	/* Enable graphics register modification */	if (!info->isVGA) {		outb(0x00, EGA_GFX_E0);		outb(0x01, EGA_GFX_E1);	}		/* update misc output register */	outb(par->misc, VGA_MIS_W);		/* synchronous reset on */	outb(0x00, VGA_SEQ_I);	outb(0x01, VGA_SEQ_D);		/* write sequencer registers */	outb(1, VGA_SEQ_I);	outb(par->seq[1] | 0x20, VGA_SEQ_D);	for (i = 2; i < VGA_SEQ_C; i++) {		outb(i, VGA_SEQ_I);		outb(par->seq[i], VGA_SEQ_D);	}		/* synchronous reset off */	outb(0x00, VGA_SEQ_I);	outb(0x03, VGA_SEQ_D);		/* deprotect CRT registers 0-7 */	outb(0x11, VGA_CRT_IC);	outb(par->crtc[0x11], VGA_CRT_DC);	/* write CRT registers */	for (i = 0; i < VGA_CRT_C; i++) {		outb(i, VGA_CRT_IC);		outb(par->crtc[i], VGA_CRT_DC);	}		/* write graphics controller registers */	for (i = 0; i < VGA_GFX_C; i++) {		outb(i, VGA_GFX_I);		outb(par->gdc[i], VGA_GFX_D);	}		/* write attribute controller registers */	for (i = 0; i < VGA_ATT_C; i++) {		inb_p(VGA_IS1_RC);		/* reset flip-flop */		outb_p(i, VGA_ATT_IW);		outb_p(par->atc[i], VGA_ATT_IW);

⌨️ 快捷键说明

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