fbdev.c

来自「优龙2410linux2.6.8内核源代码」· C语言 代码 · 共 2,214 行 · 第 1/4 页

C
2,214
字号
	return 0;}static int rivafb_release(struct fb_info *info, int user){	struct riva_par *par = (struct riva_par *) info->par;	int cnt = atomic_read(&par->ref_count);	NVTRACE_ENTER();	if (!cnt)		return -EINVAL;	if (cnt == 1) {		par->riva.LockUnlock(&par->riva, 0);		par->riva.LoadStateExt(&par->riva, &par->initial_state.ext);		riva_load_state(par, &par->initial_state);		restore_vga(&par->state);		par->riva.LockUnlock(&par->riva, 1);	}	atomic_dec(&par->ref_count);	NVTRACE_LEAVE();	return 0;}static int rivafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info){	struct fb_monspecs *specs = &info->monspecs;	int nom, den;		/* translating from pixels->bytes */	int mode_valid = 0;		NVTRACE_ENTER();	switch (var->bits_per_pixel) {	case 1 ... 8:		var->red.offset = var->green.offset = var->blue.offset = 0;		var->red.length = var->green.length = var->blue.length = 8;		var->bits_per_pixel = 8;		nom = den = 1;		break;	case 9 ... 15:		var->green.length = 5;		/* fall through */	case 16:		var->bits_per_pixel = 16;		if (var->green.length == 5) {			/* 0rrrrrgg gggbbbbb */			var->red.offset = 10;			var->green.offset = 5;			var->blue.offset = 0;			var->red.length = 5;			var->green.length = 5;			var->blue.length = 5;		} else {			/* rrrrrggg gggbbbbb */			var->red.offset = 11;			var->green.offset = 5;			var->blue.offset = 0;			var->red.length = 5;			var->green.length = 6;			var->blue.length = 5;		}		nom = 2;		den = 1;		break;	case 17 ... 32:		var->red.length = var->green.length = var->blue.length = 8;		var->bits_per_pixel = 32;		var->red.offset = 16;		var->green.offset = 8;		var->blue.offset = 0;		nom = 4;		den = 1;		break;	default:		printk(KERN_ERR PFX		       "mode %dx%dx%d rejected...color depth not supported.\n",		       var->xres, var->yres, var->bits_per_pixel);		NVTRACE("EXIT, returning -EINVAL\n");		return -EINVAL;	}	if (!strictmode) {		if (!fb_validate_mode(var, info))			mode_valid = 1;	}	/* find best mode from modedb */	if (!mode_valid && specs->modedb_len) {		int i, best, best_refresh, best_x, best_y, diff_x, diff_y;		best_refresh = best = best_x = best_y = 0;		diff_x = diff_y = -1;		for (i = 0; i < specs->modedb_len; i++) {			if (var->xres <= specs->modedb[i].xres &&			    !(specs->modedb[i].flag & FB_MODE_IS_CALCULATED) &&			    specs->modedb[i].xres - var->xres < diff_x) {				best_x = specs->modedb[i].xres;				diff_x = best_x - var->xres;			}			if (!diff_x) break;		}		if (diff_x != -1) {			for (i = 0; i < specs->modedb_len; i++) {				if (best_x == specs->modedb[i].xres &&				    var->yres <= specs->modedb[i].yres &&				    !(specs->modedb[i].flag &				      FB_MODE_IS_CALCULATED) &&				    specs->modedb[i].yres-var->yres < diff_y) {					best_y = specs->modedb[i].yres;					diff_y = best_y - var->yres;				}				if (!diff_y) break;			}		}		if (diff_y != -1) {			for (i = 0; i < specs->modedb_len; i++) {				if (best_x == specs->modedb[i].xres &&				    best_y == specs->modedb[i].yres &&				    !(specs->modedb[i].flag &				      FB_MODE_IS_CALCULATED) &&				    specs->modedb[i].refresh > best_refresh) {					best_refresh=specs->modedb[i].refresh;					best = i;				}			}		}		if (best_refresh) {			riva_update_var(var, &specs->modedb[best]);			mode_valid = 1;		}	}	/* calculate modeline if supported by monitor */	if (!mode_valid && info->monspecs.gtf) {		if (!fb_get_mode(FB_MAXTIMINGS, 0, var, info))			mode_valid = 1;	}	if (!mode_valid && info->monspecs.modedb_len)		return -EINVAL;	if (var->xres_virtual < var->xres)		var->xres_virtual = var->xres;	if (var->yres_virtual <= var->yres)		var->yres_virtual = -1;	if (rivafb_do_maximize(info, var, nom, den) < 0)		return -EINVAL;	if (var->xoffset < 0)		var->xoffset = 0;	if (var->yoffset < 0)		var->yoffset = 0;	/* truncate xoffset and yoffset to maximum if too high */	if (var->xoffset > var->xres_virtual - var->xres)		var->xoffset = var->xres_virtual - var->xres - 1;	if (var->yoffset > var->yres_virtual - var->yres)		var->yoffset = var->yres_virtual - var->yres - 1;	var->red.msb_right = 	    var->green.msb_right =	    var->blue.msb_right =	    var->transp.offset = var->transp.length = var->transp.msb_right = 0;	NVTRACE_LEAVE();	return 0;}static int rivafb_set_par(struct fb_info *info){	struct riva_par *par = (struct riva_par *) info->par;	NVTRACE_ENTER();	riva_common_setup(par);	RivaGetConfig(&par->riva, par->Chipset);	/* vgaHWunlock() + riva unlock (0x7F) */	CRTCout(par, 0x11, 0xFF);	par->riva.LockUnlock(&par->riva, 0);	riva_load_video_mode(info);	riva_setup_accel(info);		memset_io(par->riva.CURSOR, 0, MAX_CURS * MAX_CURS * 2);	info->fix.line_length = (info->var.xres_virtual * (info->var.bits_per_pixel >> 3));	info->fix.visual = (info->var.bits_per_pixel == 8) ?				FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;	NVTRACE_LEAVE();	return 0;}/** * rivafb_pan_display * @var: standard kernel fb changeable data * @con: TODO * @info: pointer to fb_info object containing info for current riva board * * DESCRIPTION: * Pan (or wrap, depending on the `vmode' field) the display using the * `xoffset' and `yoffset' fields of the `var' structure. * If the values don't fit, return -EINVAL. * * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag */static int rivafb_pan_display(struct fb_var_screeninfo *var,			      struct fb_info *info){	struct riva_par *par = (struct riva_par *)info->par;	unsigned int base;	NVTRACE_ENTER();	if (var->xoffset > (var->xres_virtual - var->xres))		return -EINVAL;	if (var->yoffset > (var->yres_virtual - var->yres))		return -EINVAL;	if (var->vmode & FB_VMODE_YWRAP) {		if (var->yoffset < 0		    || var->yoffset >= info->var.yres_virtual		    || var->xoffset) return -EINVAL;	} else {		if (var->xoffset + info->var.xres > info->var.xres_virtual ||		    var->yoffset + info->var.yres > info->var.yres_virtual)			return -EINVAL;	}	base = var->yoffset * info->fix.line_length + var->xoffset;	par->riva.SetStartAddress(&par->riva, base);	info->var.xoffset = var->xoffset;	info->var.yoffset = var->yoffset;	if (var->vmode & FB_VMODE_YWRAP)		info->var.vmode |= FB_VMODE_YWRAP;	else		info->var.vmode &= ~FB_VMODE_YWRAP;	NVTRACE_LEAVE();	return 0;}static int rivafb_blank(int blank, struct fb_info *info){	struct riva_par *par= (struct riva_par *)info->par;	unsigned char tmp, vesa;	tmp = SEQin(par, 0x01) & ~0x20;	/* screen on/off */	vesa = CRTCin(par, 0x1a) & ~0xc0;	/* sync on/off */	NVTRACE_ENTER();	if (blank) {		tmp |= 0x20;		switch (blank - 1) {		case VESA_NO_BLANKING:			break;		case VESA_VSYNC_SUSPEND:			vesa |= 0x80;			break;		case VESA_HSYNC_SUSPEND:			vesa |= 0x40;			break;		case VESA_POWERDOWN:			vesa |= 0xc0;			break;		}	}	SEQout(par, 0x01, tmp);	CRTCout(par, 0x1a, vesa);#ifdef CONFIG_PMAC_BACKLIGHT	if ( par->FlatPanel && _machine == _MACH_Pmac) {		set_backlight_enable(!blank);	}#endif	NVTRACE_LEAVE();	return 0;}/** * rivafb_setcolreg * @regno: register index * @red: red component * @green: green component * @blue: blue component * @transp: transparency * @info: pointer to fb_info object containing info for current riva board * * DESCRIPTION: * Set a single color register. The values supplied have a 16 bit * magnitude. * * RETURNS: * Return != 0 for invalid regno. * * CALLED FROM: * fbcmap.c:fb_set_cmap() */static int rivafb_setcolreg(unsigned regno, unsigned red, unsigned green,			  unsigned blue, unsigned transp,			  struct fb_info *info){	struct riva_par *par = (struct riva_par *)info->par;	RIVA_HW_INST *chip = &par->riva;	int i;	if (regno >= riva_get_cmap_len(&info->var))		return -EINVAL;	if (info->var.grayscale) {		/* gray = 0.30*R + 0.59*G + 0.11*B */		red = green = blue =		    (red * 77 + green * 151 + blue * 28) >> 8;	}	switch (info->var.bits_per_pixel) {	case 8:		/* "transparent" stuff is completely ignored. */		riva_wclut(chip, regno, red >> 8, green >> 8, blue >> 8);		break;	case 16:		if (info->var.green.length == 5) {			if (regno < 16) {				/* 0rrrrrgg gggbbbbb */				((u32 *)info->pseudo_palette)[regno] =					((red & 0xf800) >> 1) |					((green & 0xf800) >> 6) |					((blue & 0xf800) >> 11);			}			for (i = 0; i < 8; i++) 				riva_wclut(chip, regno*8+i, red >> 8,					   green >> 8, blue >> 8);		} else {			u8 r, g, b;			if (regno < 16) {				/* rrrrrggg gggbbbbb */				((u32 *)info->pseudo_palette)[regno] =					((red & 0xf800) >> 0) |					((green & 0xf800) >> 5) |					((blue & 0xf800) >> 11);			}			if (regno < 32) {				for (i = 0; i < 8; i++) {					riva_wclut(chip, regno*8+i, red >> 8, 						   green >> 8, blue >> 8);				}			}			for (i = 0; i < 4; i++) {				riva_rclut(chip, regno*2+i, &r, &g, &b);				riva_wclut(chip, regno*4+i, r, green >> 8, b);			}		}		break;	case 32:		if (regno < 16) {			((u32 *)info->pseudo_palette)[regno] =				((red & 0xff00) << 8) |				((green & 0xff00)) | ((blue & 0xff00) >> 8);					}		riva_wclut(chip, regno, red >> 8, green >> 8, blue >> 8);		break;	default:		/* do nothing */		break;	}	return 0;}/** * rivafb_fillrect - hardware accelerated color fill function * @info: pointer to fb_info structure * @rect: pointer to fb_fillrect structure * * DESCRIPTION: * This function fills up a region of framebuffer memory with a solid * color with a choice of two different ROP's, copy or invert. * * CALLED FROM: * framebuffer hook */static void rivafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect){	struct riva_par *par = (struct riva_par *) info->par;	u_int color, rop = 0;	if (info->var.bits_per_pixel == 8)		color = rect->color;	else		color = ((u32 *)info->pseudo_palette)[rect->color];	switch (rect->rop) {	case ROP_XOR:		rop = 0x66;		break;	case ROP_COPY:	default:		rop = 0xCC;		break;	}	riva_set_rop_solid(par, rop);	RIVA_FIFO_FREE(par->riva, Bitmap, 1);	par->riva.Bitmap->Color1A = color;	RIVA_FIFO_FREE(par->riva, Bitmap, 2);	par->riva.Bitmap->UnclippedRectangle[0].TopLeft =			(rect->dx << 16) | rect->dy;	mb();	par->riva.Bitmap->UnclippedRectangle[0].WidthHeight =			(rect->width << 16) | rect->height;	mb();	riva_set_rop_solid(par, 0xcc);}/** * rivafb_copyarea - hardware accelerated blit function * @info: pointer to fb_info structure * @region: pointer to fb_copyarea structure * * DESCRIPTION: * This copies an area of pixels from one location to another * * CALLED FROM: * framebuffer hook */static void rivafb_copyarea(struct fb_info *info, const struct fb_copyarea *region){	struct riva_par *par = (struct riva_par *) info->par;	RIVA_FIFO_FREE(par->riva, Blt, 3);	par->riva.Blt->TopLeftSrc  = (region->sy << 16) | region->sx;	par->riva.Blt->TopLeftDst  = (region->dy << 16) | region->dx;	mb();	par->riva.Blt->WidthHeight = (region->height << 16) | region->width;	mb();}static inline void convert_bgcolor_16(u32 *col){	*col = ((*col & 0x0000F800) << 8)		| ((*col & 0x00007E0) << 5)		| ((*col & 0x0000001F) << 3)		|	   0xFF000000;	mb();}/** * rivafb_imageblit: hardware accelerated color expand function * @info: pointer to fb_info structure * @image: pointer to fb_image structure * * DESCRIPTION: * If the source is a monochrome bitmap, the function fills up a a region * of framebuffer memory with pixels whose color is determined by the bit * setting of the bitmap, 1 - foreground, 0 - background. * * If the source is not a monochrome bitmap, color expansion is not done. * In this case, it is channeled to a software function. * * CALLED FROM: * framebuffer hook */static void rivafb_imageblit(struct fb_info *info, 			     const struct fb_image *image){	struct riva_par *par = (struct riva_par *) info->par;	u32 fgx = 0, bgx = 0, width, tmp;	u8 *cdat = (u8 *) image->data;	volatile u32 *d;	int i, size;	if (image->depth != 1) {		cfb_imageblit(info, image);		return;	}	switch (info->var.bits_per_pixel) {	case 8:		fgx = image->fg_color;		bgx = image->bg_color;		break;	case 16:		fgx = ((u32 *)info->pseudo_palette)[image->fg_color];		bgx = ((u32 *)info->pseudo_palette)[image->bg_color];		if (info->var.green.length == 6)			convert_bgcolor_16(&bgx);			break;	case 32:		fgx = ((u32 *)info->pseudo_palette)[image->fg_color];		bgx = ((u32 *)info->pseudo_palette)[image->bg_color];		break;	}	RIVA_FIFO_FREE(par->riva, Bitmap, 7);	par->riva.Bitmap->ClipE.TopLeft     = 		(image->dy << 16) | (image->dx & 0xFFFF);	par->riva.Bitmap->ClipE.BottomRight = 		(((image->dy + image->height) << 16) |		 ((image->dx + image->width) & 0xffff));	par->riva.Bitmap->Color0E           = bgx;	par->riva.Bitmap->Color1E           = fgx;	par->riva.Bitmap->WidthHeightInE    = 		(image->height << 16) | ((image->width + 31) & ~31);	par->riva.Bitmap->WidthHeightOutE   = 		(image->height << 16) | ((image->width + 31) & ~31);	par->riva.Bitmap->PointE            = 		(image->dy << 16) | (image->dx & 0xFFFF);	d = &par->riva.Bitmap->MonochromeData01E;	width = (image->width + 31)/32;	size = width * image->height;	while (size >= 16) {		RIVA_FIFO_FREE(par->riva, Bitmap, 16);		for (i = 0; i < 16; i++) {			tmp = *((u32 *)cdat);			cdat = (u8 *)((u32 *)cdat + 1);			reverse_order(&tmp);			d[i] = tmp;		}		size -= 16;	}	if (size) {		RIVA_FIFO_FREE(par->riva, Bitmap, size);		for (i = 0; i < size; i++) {			tmp = *((u32 *) cdat);			cdat = (u8 *)((u32 *)cdat + 1);			reverse_order(&tmp);			d[i] = tmp;		}	}}/** * rivafb_cursor - hardware cursor function * @info: pointer to info structure * @cursor: pointer to fbcursor structure * * DESCRIPTION: * A cursor function that supports displaying a cursor image via hardware. * Within the kernel, copy and invert rops are supported.  If exported * to user space, only the copy rop will be supported. * * CALLED FROM * framebuffer hook */static int rivafb_cursor(struct fb_info *info, struct fb_cursor *cursor){	struct riva_par *par = (struct riva_par *) info->par;	u8 data[MAX_CURS * MAX_CURS/8];

⌨️ 快捷键说明

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