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

📄 nvidia.c

📁 底层驱动开发
💻 C
📖 第 1 页 / 共 4 页
字号:
	state->gra[0x05] = 0x40;	state->gra[0x06] = 0x05;	state->gra[0x07] = 0x0f;	state->gra[0x08] = 0xff;	state->seq[0x00] = 0x03;	state->seq[0x01] = 0x01;	state->seq[0x02] = 0x0f;	state->seq[0x03] = 0x00;	state->seq[0x04] = 0x0e;	state->misc_output = 0xeb;}static int nvidiafb_cursor(struct fb_info *info, struct fb_cursor *cursor){	struct nvidia_par *par = info->par;	u8 data[MAX_CURS * MAX_CURS / 8];	int i, set = cursor->set;	u16 fg, bg;	if (cursor->image.width > MAX_CURS || cursor->image.height > MAX_CURS)		return -ENXIO;	NVShowHideCursor(par, 0);	if (par->cursor_reset) {		set = FB_CUR_SETALL;		par->cursor_reset = 0;	}	if (set & FB_CUR_SETSIZE)		memset_io(par->CURSOR, 0, MAX_CURS * MAX_CURS * 2);	if (set & FB_CUR_SETPOS) {		u32 xx, yy, temp;		yy = cursor->image.dy - info->var.yoffset;		xx = cursor->image.dx - info->var.xoffset;		temp = xx & 0xFFFF;		temp |= yy << 16;		NV_WR32(par->PRAMDAC, 0x0000300, temp);	}	if (set & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP | FB_CUR_SETIMAGE)) {		u32 bg_idx = cursor->image.bg_color;		u32 fg_idx = cursor->image.fg_color;		u32 s_pitch = (cursor->image.width + 7) >> 3;		u32 d_pitch = MAX_CURS / 8;		u8 *dat = (u8 *) cursor->image.data;		u8 *msk = (u8 *) cursor->mask;		u8 *src;		src = kmalloc(s_pitch * cursor->image.height, GFP_ATOMIC);		if (src) {			switch (cursor->rop) {			case ROP_XOR:				for (i = 0; i < s_pitch * cursor->image.height; i++)					src[i] = dat[i] ^ msk[i];				break;			case ROP_COPY:			default:				for (i = 0; i < s_pitch * cursor->image.height; i++)					src[i] = dat[i] & msk[i];				break;			}			fb_pad_aligned_buffer(data, d_pitch, src, s_pitch,						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;			NVLockUnlock(par, 0);			nvidiafb_load_cursor_image(par, data, bg, fg,						   cursor->image.width,						   cursor->image.height);			kfree(src);		}	}	if (cursor->enable)		NVShowHideCursor(par, 1);	return 0;}static int nvidiafb_set_par(struct fb_info *info){	struct nvidia_par *par = info->par;	NVTRACE_ENTER();	NVLockUnlock(par, 1);	if (!par->FlatPanel || (info->var.bits_per_pixel != 24) ||	    !par->twoHeads)		par->FPDither = 0;	info->fix.visual = (info->var.bits_per_pixel == 8) ?	    FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;	nvidia_init_vga(info);	nvidia_calc_regs(info);	nvidia_write_regs(par);	NVLockUnlock(par, 0);	if (par->twoHeads) {		VGA_WR08(par->PCIO, 0x03D4, 0x44);		VGA_WR08(par->PCIO, 0x03D5, par->ModeReg.crtcOwner);		NVLockUnlock(par, 0);	}	NVWriteCrtc(par, 0x11, 0x00);	info->fix.line_length = (info->var.xres_virtual *				 info->var.bits_per_pixel) >> 3;	if (info->var.accel_flags) {		info->fbops->fb_imageblit = nvidiafb_imageblit;		info->fbops->fb_fillrect = nvidiafb_fillrect;		info->fbops->fb_copyarea = nvidiafb_copyarea;		info->fbops->fb_sync = nvidiafb_sync;		info->pixmap.scan_align = 4;		info->flags &= ~FBINFO_HWACCEL_DISABLED;		NVResetGraphics(info);	} else {		info->fbops->fb_imageblit = cfb_imageblit;		info->fbops->fb_fillrect = cfb_fillrect;		info->fbops->fb_copyarea = cfb_copyarea;		info->fbops->fb_sync = NULL;		info->pixmap.scan_align = 1;		info->flags |= FBINFO_HWACCEL_DISABLED;	}	par->cursor_reset = 1;	NVWriteCrtc(par, 0x11, 0xff);	NVTRACE_LEAVE();	return 0;}static int nvidiafb_setcolreg(unsigned regno, unsigned red, unsigned green,			      unsigned blue, unsigned transp,			      struct fb_info *info){	struct nvidia_par *par = info->par;	int i;	NVTRACE_ENTER();	if (regno >= (1 << info->var.green.length))		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);	}	switch (info->var.bits_per_pixel) {	case 8:		/* "transparent" stuff is completely ignored. */		nvidia_write_clut(par, regno, red >> 8, green >> 8, blue >> 8);		break;	case 16:		if (info->var.green.length == 5) {			for (i = 0; i < 8; i++) {				nvidia_write_clut(par, regno * 8 + i, red >> 8,						  green >> 8, blue >> 8);			}		} else {			u8 r, g, b;			if (regno < 32) {				for (i = 0; i < 8; i++) {					nvidia_write_clut(par, regno * 8 + i,							  red >> 8, green >> 8,							  blue >> 8);				}			}			nvidia_read_clut(par, regno * 4, &r, &g, &b);			for (i = 0; i < 4; i++)				nvidia_write_clut(par, regno * 4 + i, r,						  green >> 8, b);		}		break;	case 32:		nvidia_write_clut(par, regno, red >> 8, green >> 8, blue >> 8);		break;	default:		/* do nothing */		break;	}	NVTRACE_LEAVE();	return 0;}static int nvidiafb_check_var(struct fb_var_screeninfo *var,			      struct fb_info *info){	struct nvidia_par *par = info->par;	int memlen, vramlen, mode_valid = 0;	int pitch, err = 0;	NVTRACE_ENTER();	var->transp.offset = 0;	var->transp.length = 0;	var->xres &= ~7;	if (var->bits_per_pixel <= 8)		var->bits_per_pixel = 8;	else if (var->bits_per_pixel <= 16)		var->bits_per_pixel = 16;	else		var->bits_per_pixel = 32;	switch (var->bits_per_pixel) {	case 8:		var->red.offset = 0;		var->red.length = 8;		var->green.offset = 0;		var->green.length = 8;		var->blue.offset = 0;		var->blue.length = 8;		var->transp.offset = 0;		var->transp.length = 0;		break;	case 16:		var->green.length = (var->green.length < 6) ? 5 : 6;		var->red.length = 5;		var->blue.length = 5;		var->transp.length = 6 - var->green.length;		var->blue.offset = 0;		var->green.offset = 5;		var->red.offset = 5 + var->green.length;		var->transp.offset = (5 + var->red.offset) & 15;		break;	case 32:		/* RGBA 8888 */		var->red.offset = 16;		var->red.length = 8;		var->green.offset = 8;		var->green.length = 8;		var->blue.offset = 0;		var->blue.length = 8;		var->transp.length = 8;		var->transp.offset = 24;		break;	}	var->red.msb_right = 0;	var->green.msb_right = 0;	var->blue.msb_right = 0;	var->transp.msb_right = 0;	if (!info->monspecs.hfmax || !info->monspecs.vfmax ||	    !info->monspecs.dclkmax || !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) {		struct fb_videomode *mode;		mode = fb_find_best_mode(var, &info->modelist);		if (mode) {			fb_videomode_to_var(var, mode);			mode_valid = 1;		}	}	if (!mode_valid && info->monspecs.modedb_len)		return -EINVAL;	if (par->fpWidth && par->fpHeight && (par->fpWidth < var->xres ||					      par->fpHeight < var->yres))		return -EINVAL;	if (var->yres_virtual < var->yres)		var->yres_virtual = var->yres;	if (var->xres_virtual < var->xres)		var->xres_virtual = var->xres;	var->xres_virtual = (var->xres_virtual + 63) & ~63;	vramlen = info->screen_size;	pitch = ((var->xres_virtual * var->bits_per_pixel) + 7) / 8;	memlen = pitch * var->yres_virtual;	if (memlen > vramlen) {		var->yres_virtual = vramlen / pitch;		if (var->yres_virtual < var->yres) {			var->yres_virtual = var->yres;			var->xres_virtual = vramlen / var->yres_virtual;			var->xres_virtual /= var->bits_per_pixel / 8;			var->xres_virtual &= ~63;			pitch = (var->xres_virtual *				 var->bits_per_pixel + 7) / 8;			memlen = pitch * var->yres;			if (var->xres_virtual < var->xres) {				printk("nvidiafb: required video memory, "				       "%d bytes, for %dx%d-%d (virtual) "				       "is out of range\n",				       memlen, var->xres_virtual,				       var->yres_virtual, var->bits_per_pixel);				err = -ENOMEM;			}		}	}	if (var->accel_flags) {		if (var->yres_virtual > 0x7fff)			var->yres_virtual = 0x7fff;		if (var->xres_virtual > 0x7fff)			var->xres_virtual = 0x7fff;	}	var->xres_virtual &= ~63;	NVTRACE_LEAVE();	return err;}static int nvidiafb_pan_display(struct fb_var_screeninfo *var,				struct fb_info *info){	struct nvidia_par *par = info->par;	u32 total;	total = info->var.yoffset * info->fix.line_length + info->var.xoffset;	NVSetStartAddress(par, total);	return 0;}static int nvidiafb_blank(int blank, struct fb_info *info){	struct nvidia_par *par = info->par;	unsigned char tmp, vesa;	tmp = NVReadSeq(par, 0x01) & ~0x20;	/* screen on/off */	vesa = NVReadCrtc(par, 0x1a) & ~0xc0;	/* sync on/off */	NVTRACE_ENTER();	if (blank)		tmp |= 0x20;	switch (blank) {	case FB_BLANK_UNBLANK:	case FB_BLANK_NORMAL:		break;	case FB_BLANK_VSYNC_SUSPEND:		vesa |= 0x80;		break;	case FB_BLANK_HSYNC_SUSPEND:		vesa |= 0x40;		break;	case FB_BLANK_POWERDOWN:		vesa |= 0xc0;		break;	}	NVWriteSeq(par, 0x01, tmp);	NVWriteCrtc(par, 0x1a, vesa);#ifdef CONFIG_PMAC_BACKLIGHT	if (par->FlatPanel && _machine == _MACH_Pmac) {		set_backlight_enable(!blank);	}#endif	NVTRACE_LEAVE();	return 0;}static struct fb_ops nvidia_fb_ops = {	.owner          = THIS_MODULE,	.fb_check_var   = nvidiafb_check_var,	.fb_set_par     = nvidiafb_set_par,	.fb_setcolreg   = nvidiafb_setcolreg,	.fb_pan_display = nvidiafb_pan_display,	.fb_blank       = nvidiafb_blank,	.fb_fillrect    = nvidiafb_fillrect,	.fb_copyarea    = nvidiafb_copyarea,	.fb_imageblit   = nvidiafb_imageblit,	.fb_cursor      = nvidiafb_cursor,	.fb_sync        = nvidiafb_sync,};static int __devinit nvidia_set_fbinfo(struct fb_info *info){	struct fb_monspecs *specs = &info->monspecs;	struct fb_videomode modedb;	struct nvidia_par *par = info->par;	int lpitch;	NVTRACE_ENTER();	info->flags = FBINFO_DEFAULT	    | FBINFO_HWACCEL_IMAGEBLIT	    | FBINFO_HWACCEL_FILLRECT	    | FBINFO_HWACCEL_COPYAREA	    | FBINFO_HWACCEL_YPAN;	fb_videomode_to_modelist(info->monspecs.modedb,				 info->monspecs.modedb_len, &info->modelist);	fb_var_to_videomode(&modedb, &nvidiafb_default_var);	if (specs->modedb != NULL) {		/* get preferred timing */		if (specs->misc & FB_MISC_1ST_DETAIL) {

⌨️ 快捷键说明

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