fbdev.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 2,183 行 · 第 1/4 页

C
2,183
字号
		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;	}	/* 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) {		mode = fb_find_best_mode(var, &info->modelist);		if (mode) {			riva_update_var(var, mode);			mode_valid = 1;		}	}	if (!mode_valid && !list_empty(&info->modelist))		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;	}	if (regno < 16 && info->fix.visual == FB_VISUAL_DIRECTCOLOR) {		((u32 *) info->pseudo_palette)[regno] =			(regno << info->var.red.offset) |			(regno << info->var.green.offset) |			(regno << info->var.blue.offset);		/*		 * The Riva128 2D engine requires color information in		 * TrueColor format even if framebuffer is in DirectColor		 */		if (par->riva.Architecture == NV_ARCH_03) {			switch (info->var.bits_per_pixel) {			case 16:				par->palette[regno] = ((red & 0xf800) >> 1) |					((green & 0xf800) >> 6) |					((blue & 0xf800) >> 11);				break;			case 32:				par->palette[regno] = ((red & 0xff00) << 8) |					((green & 0xff00)) |					((blue & 0xff00) >> 8);				break;			}		}	}	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) {			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 < 32) {				for (i = 0; i < 8; i++) {					riva_wclut(chip, regno*8+i,						   red >> 8, green >> 8,						   blue >> 8);				}			}			riva_rclut(chip, regno*4, &r, &g, &b);			for (i = 0; i < 4; i++)				riva_wclut(chip, regno*4+i, r,					   green >> 8, b);		}		break;	case 32:		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 {		if (par->riva.Architecture != NV_ARCH_03)			color = ((u32 *)info->pseudo_palette)[rect->color];		else			color = par->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:	case 32:		if (par->riva.Architecture != NV_ARCH_03) {			fgx = ((u32 *)info->pseudo_palette)[image->fg_color];			bgx = ((u32 *)info->pseudo_palette)[image->bg_color];		} else {			fgx = par->palette[image->fg_color];			bgx = par->palette[image->bg_color];		}		if (info->var.green.length == 6)			convert_bgcolor_16(&bgx);			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];	u16 fg, bg;	int i;	par->riva.ShowHideCursor(&par->riva, 0);	if (cursor->set & FB_CUR_SETPOS) {		u32 xx, yy, temp;		info->cursor.image.dx = cursor->image.dx;		info->cursor.image.dy = cursor->image.dy;		yy = cursor->image.dy - info->var.yoffset;		xx = cursor->image.dx - info->var.xoffset;		temp = xx & 0xFFFF;		temp |= yy << 16;		par->riva.PRAMDAC[0x0000300/4] = temp;	}	if (cursor->set & FB_CUR_SETSIZE) {		info->cursor.image.height = cursor->image.height;		info->cursor.image.width = cursor->image.width;		memset_io(par->riva.CURSOR, 0, MAX_CURS * MAX_CURS * 2);	}	if (cursor->set & FB_CUR_SETCMAP) {		info->cursor.image.bg_color = cursor->image.bg_color;		info->cursor.image.fg_color = cursor->image.fg_color;	}	if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP | FB_CUR_SETCUR)) {		u32 bg_idx = info->cursor.image.bg_color;		u32 fg_idx = info->cursor.image.fg_color;		u32 s_pitch = (info->cursor.image.width+7) >> 3;		u32 d_pitch = MAX_CURS/8;		u8 *dat = (u8 *) cursor->image.data;		u8 *msk = (u8 *) info->cursor.mask;		u8 src[64];					info->cursor.image.data = cursor->image.data;		switch (info->cursor.rop) {		case ROP_XOR:			for (i = 0; i < s_pitch * info->cursor.image.height;			     i++)				src[i] = dat[i] ^ msk[i];			break;		case ROP_COPY:		default:			for (i = 0; i < s_pitch * info->cursor.image.height;			     i++)				src[i] = dat[i] & msk[i];			break;		}				fb_sysmove_buf_aligned(info, &info->sprite, data, d_pitch, src,				       s_pitch, info->cursor.image.height);		bg = ((info->cmap.red[bg_idx] & 0xf8) << 7) |		     ((info->cmap.green[bg_idx] & 0xf8) << 2) |		     ((info->cmap.blue[bg_idx] & 0xf8) >> 3) | 1 << 15;		fg = ((info->cmap.red[fg_idx] & 0xf8) << 7) |		     ((info->cmap.green[fg_idx] & 0xf8) << 2) |		     ((info->cmap.blue[fg_idx] & 0xf8) >> 3) | 1 << 15;		par->riva.LockUnlock(&par->riva, 0);		rivafb_load_cursor_image(par, data, bg, fg,					 info->cursor.image.width, 					 info->cursor.image.height);	}	if (info->cursor.enable)		par->riva.ShowHideCursor(&par->riva, 1);	return 0;}static int rivafb_sync(struct fb_info *info){	struct riva_par *par = (struct riva_par *)info->par;	wait_for_idle(par);	return 0;}/* ------------------------------------------------------------------------- * *

⌨️ 快捷键说明

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