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

📄 matroxfb_crtc2.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200, G400 and G450. * * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz> * * Portions Copyright (c) 2001 Matrox Graphics Inc. * * Version: 1.64 2002/06/10 * */#include "matroxfb_maven.h"#include "matroxfb_crtc2.h"#include "matroxfb_misc.h"#include "matroxfb_DAC1064.h"#include <linux/matroxfb.h>#include <asm/uaccess.h>/* **************************************************** */static int mem = 8192;MODULE_PARM(mem, "i");MODULE_PARM_DESC(mem, "Memory size reserved for dualhead (default=8MB)");/* **************************************************** */static int matroxfb_dh_getcolreg(unsigned regno, unsigned *red, unsigned *green,		unsigned *blue, unsigned *transp, struct fb_info* info) {#define m2info (list_entry(info, struct matroxfb_dh_fb_info, fbcon))	if (regno >= 16)		return 1;	*red = m2info->palette[regno].red;	*blue = m2info->palette[regno].blue;	*green = m2info->palette[regno].green;	*transp = m2info->palette[regno].transp;	return 0;#undef m2info}static int matroxfb_dh_setcolreg(unsigned regno, unsigned red, unsigned green,		unsigned blue, unsigned transp, struct fb_info* info) {#define m2info (list_entry(info, struct matroxfb_dh_fb_info, fbcon))	struct display* p;	if (regno >= 16)		return 1;	m2info->palette[regno].red = red;	m2info->palette[regno].blue = blue;	m2info->palette[regno].green = green;	m2info->palette[regno].transp = transp;	p = m2info->currcon_display;	if (p->var.grayscale) {		/* gray = 0.30*R + 0.59*G + 0.11*B */		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;	}	red = CNVT_TOHW(red, p->var.red.length);	green = CNVT_TOHW(green, p->var.green.length);	blue = CNVT_TOHW(blue, p->var.blue.length);	transp = CNVT_TOHW(transp, p->var.transp.length);	switch (p->var.bits_per_pixel) {#ifdef FBCON_HAS_CFB16		case 16:			m2info->cmap.cfb16[regno] =				(red << p->var.red.offset)     |				(green << p->var.green.offset) |				(blue << p->var.blue.offset)   |				(transp << p->var.transp.offset);			break;#endif#ifdef FBCON_HAS_CFB32		case 32:			m2info->cmap.cfb32[regno] =				(red << p->var.red.offset)     |				(green << p->var.green.offset) |				(blue << p->var.blue.offset)   |				(transp << p->var.transp.offset);			break;#endif	}	return 0;#undef m2info}static inline void my_install_cmap(struct matroxfb_dh_fb_info* m2info){	/* Do not touch this code if you do not understand what it does! */	/* Never try to use do_install_cmap() instead. It is crap. */	struct fb_cmap* cmap = &m2info->currcon_display->cmap;		if (cmap->len)		fb_set_cmap(cmap, 1, matroxfb_dh_setcolreg, &m2info->fbcon);	else		fb_set_cmap(fb_default_cmap(16), 1, matroxfb_dh_setcolreg, &m2info->fbcon);}static void matroxfb_dh_restore(struct matroxfb_dh_fb_info* m2info,		struct my_timming* mt,		struct display* p,		int mode,		unsigned int pos) {	struct matrox_crtc2 c2;	MINFO_FROM(m2info->primary_dev);	switch (mode) {		case 15:			c2.ctl = 0x00200000;			break;		case 16:			c2.ctl = 0x00400000;			break;/*		case 32: */		default:			c2.ctl = 0x00800000;			break;	}	c2.ctl |= 0x00000001;	/* enable CRTC2 */	c2.datactl = 0;	if (ACCESS_FBINFO(outputs[1]).src == MATROXFB_SRC_CRTC2) {		if (ACCESS_FBINFO(devflags.g450dac)) {			c2.ctl |= 0x00000006; /* source from secondary pixel PLL */			/* no vidrst when in monitor mode */			if (ACCESS_FBINFO(outputs[1]).mode != MATROXFB_OUTPUT_MODE_MONITOR) {				c2.ctl |=  0xC0001000; /* Enable H/V vidrst */			}		} else {			c2.ctl |= 0x00000002; /* source from VDOCLK */			c2.ctl |= 0xC0000000; /* enable vvidrst & hvidrst */			/* MGA TVO is our clock source */		}	} else if (ACCESS_FBINFO(outputs[0]).src == MATROXFB_SRC_CRTC2) {		c2.ctl |= 0x00000004; /* source from pixclock */		/* PIXPLL is our clock source */	}	if (ACCESS_FBINFO(outputs[0]).src == MATROXFB_SRC_CRTC2) {		c2.ctl |= 0x00100000;	/* connect CRTC2 to DAC */	}	if (mt->interlaced) {		c2.ctl |= 0x02000000;	/* interlaced, second field is bigger, as G450 apparently ignores it */		mt->VDisplay >>= 1;		mt->VSyncStart >>= 1;		mt->VSyncEnd >>= 1;		mt->VTotal >>= 1;	}	if ((mt->HTotal & 7) == 2) {		c2.datactl |= 0x00000010;		mt->HTotal &= ~7;	}	c2.ctl |= 0x10000000;	/* 0x10000000 is VIDRST polarity */	c2.hparam = ((mt->HDisplay - 8) << 16) | (mt->HTotal - 8);	c2.hsync = ((mt->HSyncEnd - 8) << 16) | (mt->HSyncStart - 8);	c2.vparam = ((mt->VDisplay - 1) << 16) | (mt->VTotal - 1);	c2.vsync = ((mt->VSyncEnd - 1) << 16) | (mt->VSyncStart - 1);	c2.preload = ((mt->VSyncStart) << 16) | (mt->HSyncStart);	mga_outl(0x3C14, c2.hparam);	mga_outl(0x3C18, c2.hsync);	mga_outl(0x3C1C, c2.vparam);	mga_outl(0x3C20, c2.vsync);	mga_outl(0x3C24, c2.preload);	{		u_int32_t linelen = p->var.xres_virtual * (p->var.bits_per_pixel >> 3);		if (c2.ctl & 0x02000000) {			/* field #0 is smaller, so... */			mga_outl(0x3C2C, pos);			/* field #1 vmemory start */			mga_outl(0x3C28, pos + linelen);	/* field #0 vmemory start */			linelen <<= 1;			m2info->interlaced = 1;		} else {			mga_outl(0x3C28, pos);		/* vmemory start */			m2info->interlaced = 0;		}		mga_outl(0x3C40, linelen);	}	mga_outl(0x3C4C, c2.datactl);		/* data control */	if (c2.ctl & 0x02000000) {		int i;		mga_outl(0x3C10, c2.ctl & ~0x02000000);                for (i = 0; i < 2; i++) {                        unsigned int nl;                        unsigned int lastl = 0;                        while ((nl = mga_inl(0x3C48) & 0xFFF) >= lastl) {                                lastl = nl;                        }                }	}        mga_outl(0x3C10, c2.ctl);	ACCESS_FBINFO(hw).crtc2.ctl = c2.ctl;	{		u_int32_t tmp;		tmp = mt->VDisplay << 16;		/* line compare */		if (mt->sync & FB_SYNC_HOR_HIGH_ACT)			tmp |= 0x00000100;		if (mt->sync & FB_SYNC_VERT_HIGH_ACT)			tmp |= 0x00000200;		mga_outl(0x3C44, tmp);	}}static void matroxfb_dh_disable(struct matroxfb_dh_fb_info* m2info) {	MINFO_FROM(m2info->primary_dev);	mga_outl(0x3C10, 0x00000004);	/* disable CRTC2, CRTC1->DAC1, PLL as clock source */	ACCESS_FBINFO(hw).crtc2.ctl = 0x00000004;}static void matroxfb_dh_cfbX_init(struct matroxfb_dh_fb_info* m2info,		struct display* p) {	/* no acceleration for secondary head... */}static void matroxfb_dh_pan_var(struct matroxfb_dh_fb_info* m2info,		struct fb_var_screeninfo* var) {	unsigned int pos;	unsigned int linelen;	unsigned int pixelsize;	MINFO_FROM(m2info->primary_dev);	pixelsize = var->bits_per_pixel >> 3;	linelen = var->xres_virtual * pixelsize;	pos = var->yoffset * linelen + var->xoffset * pixelsize;	pos += m2info->video.offbase;	if (m2info->interlaced) {		mga_outl(0x3C2C, pos);		mga_outl(0x3C28, pos + linelen);	} else {		mga_outl(0x3C28, pos);	}}static int matroxfb_dh_decode_var(struct matroxfb_dh_fb_info* m2info,		struct display* p,		struct fb_var_screeninfo* var,		int *visual,		int *video_cmap_len,		int *mode) {	unsigned int mask;	unsigned int memlen;	unsigned int vramlen;	switch (var->bits_per_pixel) {#ifdef FBCON_HAS_CFB16		case 16:	mask = 0x1F;				break;#endif#ifdef FBCON_HAS_CFB32		case 32:	mask = 0x0F;				break;#endif		default:	return -EINVAL;	}	vramlen = m2info->video.len_usable;	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 + mask) & ~mask;	if (var->yres_virtual > 32767)		return -EINVAL;	memlen = var->xres_virtual * var->yres_virtual * (var->bits_per_pixel >> 3);	if (memlen > vramlen)		return -EINVAL;	if (var->xoffset + var->xres > var->xres_virtual)		var->xoffset = var->xres_virtual - var->xres;	if (var->yoffset + var->yres > var->yres_virtual)		var->yoffset = var->yres_virtual - var->yres;	var->xres &= ~7;	var->left_margin &= ~7;	var->right_margin &= ~7;	var->hsync_len &= ~7;	*mode = var->bits_per_pixel;	if (var->bits_per_pixel == 16) {		if (var->green.length == 5) {			var->red.offset = 10;			var->red.length = 5;			var->green.offset = 5;			var->green.length = 5;			var->blue.offset = 0;			var->blue.length = 5;			var->transp.offset = 15;			var->transp.length = 1;			*mode = 15;		} else {			var->red.offset = 11;			var->red.length = 5;			var->green.offset = 5;			var->green.length = 6;			var->blue.offset = 0;			var->blue.length = 5;			var->transp.offset = 0;			var->transp.length = 0;		}	} else {			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.offset = 24;			var->transp.length = 8;	}	*visual = FB_VISUAL_TRUECOLOR;	*video_cmap_len = 16;	return 0;}static void initMatroxDH(struct matroxfb_dh_fb_info* m2info, struct display* p) {	switch (p->var.bits_per_pixel) {#ifdef FBCON_HAS_CFB16		case 16:			p->dispsw_data = m2info->cmap.cfb16;			p->dispsw = &fbcon_cfb16;			break;#endif#ifdef FBCON_HAS_CFB32		case 32:			p->dispsw_data = m2info->cmap.cfb32;			p->dispsw = &fbcon_cfb32;			break;#endif		default:			p->dispsw_data = NULL;			p->dispsw = &fbcon_dummy;			break;	}}static int matroxfb_dh_open(struct fb_info* info, int user) {#define m2info (list_entry(info, struct matroxfb_dh_fb_info, fbcon))	MINFO_FROM(m2info->primary_dev);	if (MINFO) {		int err; 		if (ACCESS_FBINFO(dead)) { 			return -ENXIO; 		}		err = ACCESS_FBINFO(fbcon.fbops)->fb_open(&ACCESS_FBINFO(fbcon), user);		if (err) {			return err;		}	}	return 0;#undef m2info}static int matroxfb_dh_release(struct fb_info* info, int user) {#define m2info (list_entry(info, struct matroxfb_dh_fb_info, fbcon))	int err = 0;	MINFO_FROM(m2info->primary_dev);	if (MINFO) {		err = ACCESS_FBINFO(fbcon.fbops)->fb_release(&ACCESS_FBINFO(fbcon), user);	}	return err;#undef m2info}static int matroxfb_dh_get_fix(struct fb_fix_screeninfo* fix, int con,		struct fb_info* info) {#define m2info (list_entry(info, struct matroxfb_dh_fb_info, fbcon))	struct display* p;	if (con >= 0)		p = fb_display + con;	else		p = m2info->fbcon.disp;	memset(fix, 0, sizeof(*fix));	strcpy(fix->id, "MATROX DH");	fix->smem_start = m2info->video.base;	fix->smem_len = m2info->video.len_usable;	fix->type = p->type;	fix->type_aux = p->type_aux;	fix->visual = p->visual;	fix->xpanstep = 8;	/* TBD */	fix->ypanstep = 1;	fix->ywrapstep = 0;	fix->line_length = p->line_length;	fix->mmio_start = m2info->mmio.base;	fix->mmio_len = m2info->mmio.len;	fix->accel = 0;		/* no accel... */	return 0;#undef m2info}static int matroxfb_dh_get_var(struct fb_var_screeninfo* var, int con,		struct fb_info* info) {#define m2info (list_entry(info, struct matroxfb_dh_fb_info, fbcon))	if (con < 0)		*var = m2info->fbcon.disp->var;	else		*var = fb_display[con].var;	return 0;#undef m2info}static int matroxfb_dh_set_var(struct fb_var_screeninfo* var, int con,		struct fb_info* info) {#define m2info (list_entry(info, struct matroxfb_dh_fb_info, fbcon))	struct display* p;	int chgvar;	int visual;	int cmap_len;	int mode;	int err;	MINFO_FROM(m2info->primary_dev);	if (con < 0)		p = m2info->fbcon.disp;	else		p = fb_display + con;	if ((err = matroxfb_dh_decode_var(m2info, p, var, &visual, &cmap_len, &mode)) != 0)		return err;	switch (var->activate & FB_ACTIVATE_MASK) {		case FB_ACTIVATE_TEST:	return 0;		case FB_ACTIVATE_NXTOPEN:		case FB_ACTIVATE_NOW:	break;		default:		return -EINVAL;	}	if (con >= 0) {		chgvar = (p->var.xres != var->xres) ||			(p->var.yres != var->yres) ||			(p->var.xres_virtual != var->xres_virtual) ||			(p->var.yres_virtual != var->yres_virtual) ||			(p->var.bits_per_pixel != var->bits_per_pixel) ||			memcmp(&p->var.red, &var->red, sizeof(var->red)) ||			memcmp(&p->var.green, &var->green, sizeof(var->green)) ||			memcmp(&p->var.blue, &var->blue, sizeof(var->blue));	} else		chgvar = 0;	p->var = *var;	/* cmap */	p->screen_base = m2info->fbcon.screen_base = vaddr_va(m2info->video.vbase);	p->visual = visual;	p->ypanstep = 1;	p->ywrapstep = 0;	p->type = FB_TYPE_PACKED_PIXELS;	p->type_aux = 0;	p->next_line = p->line_length = (var->xres_virtual * var->bits_per_pixel) >> 3;	p->can_soft_blank = 0;	p->inverse = 0;	/* TBD */	initMatroxDH(m2info, p);	if (chgvar && info && info->changevar)		info->changevar(con);	if (con == m2info->currcon) {		struct my_timming mt;		unsigned int pos;		int out;		int cnt;		matroxfb_var2my(var, &mt);		mt.crtc = MATROXFB_SRC_CRTC2;		/* CRTC2 delay */		mt.delay = 34;		pos = (var->yoffset * var->xres_virtual + var->xoffset) * var->bits_per_pixel >> 3;		pos += m2info->video.offbase;		cnt = 0;		down_read(&ACCESS_FBINFO(altout).lock);		for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {			if (ACCESS_FBINFO(outputs[out]).src == MATROXFB_SRC_CRTC2) {				cnt++;				if (ACCESS_FBINFO(outputs[out]).output->compute) {					ACCESS_FBINFO(outputs[out]).output->compute(ACCESS_FBINFO(outputs[out]).data, &mt);				}			}		}		ACCESS_FBINFO(crtc2).pixclock = mt.pixclock;		ACCESS_FBINFO(crtc2).mnp = mt.mnp;		up_read(&ACCESS_FBINFO(altout).lock);		if (cnt) {			matroxfb_dh_restore(m2info, &mt, p, mode, pos);		} else {			matroxfb_dh_disable(m2info);		}

⌨️ 快捷键说明

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