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

📄 matroxfb_crtc2.c

📁 linux-2.6.15.6
💻 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.65 2002/08/14 * */#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_param(mem, int, 0);MODULE_PARM_DESC(mem, "Memory size reserved for dualhead (default=8MB)");/* **************************************************** */static int matroxfb_dh_setcolreg(unsigned regno, unsigned red, unsigned green,		unsigned blue, unsigned transp, struct fb_info* info) {	u_int32_t col;#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon))	if (regno >= 16)		return 1;	if (m2info->fbcon.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, m2info->fbcon.var.red.length);	green = CNVT_TOHW(green, m2info->fbcon.var.green.length);	blue = CNVT_TOHW(blue, m2info->fbcon.var.blue.length);	transp = CNVT_TOHW(transp, m2info->fbcon.var.transp.length);	col = (red << m2info->fbcon.var.red.offset)     |	      (green << m2info->fbcon.var.green.offset) |	      (blue << m2info->fbcon.var.blue.offset)   |	      (transp << m2info->fbcon.var.transp.offset);	switch (m2info->fbcon.var.bits_per_pixel) {		case 16:			m2info->cmap[regno] = col | (col << 16);			break;		case 32:			m2info->cmap[regno] = col;			break;	}	return 0;#undef m2info}static void matroxfb_dh_restore(struct matroxfb_dh_fb_info* m2info,		struct my_timming* mt,		int mode,		unsigned int pos) {	u_int32_t tmp;	u_int32_t datactl;	MINFO_FROM(m2info->primary_dev);	switch (mode) {		case 15:			tmp = 0x00200000;			break;		case 16:			tmp = 0x00400000;			break;/*		case 32: */		default:			tmp = 0x00800000;			break;	}	tmp |= 0x00000001;	/* enable CRTC2 */	datactl = 0;	if (ACCESS_FBINFO(outputs[1]).src == MATROXFB_SRC_CRTC2) {		if (ACCESS_FBINFO(devflags.g450dac)) {			tmp |= 0x00000006; /* source from secondary pixel PLL */			/* no vidrst when in monitor mode */			if (ACCESS_FBINFO(outputs[1]).mode != MATROXFB_OUTPUT_MODE_MONITOR) {				tmp |=  0xC0001000; /* Enable H/V vidrst */			}		} else {			tmp |= 0x00000002; /* source from VDOCLK */			tmp |= 0xC0000000; /* enable vvidrst & hvidrst */			/* MGA TVO is our clock source */		}	} else if (ACCESS_FBINFO(outputs[0]).src == MATROXFB_SRC_CRTC2) {		tmp |= 0x00000004; /* source from pixclock */		/* PIXPLL is our clock source */	}	if (ACCESS_FBINFO(outputs[0]).src == MATROXFB_SRC_CRTC2) {		tmp |= 0x00100000;	/* connect CRTC2 to DAC */	}	if (mt->interlaced) {		tmp |= 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) {		datactl |= 0x00000010;		mt->HTotal &= ~7;	}	tmp |= 0x10000000;	/* 0x10000000 is VIDRST polarity */	mga_outl(0x3C14, ((mt->HDisplay - 8) << 16) | (mt->HTotal - 8));	mga_outl(0x3C18, ((mt->HSyncEnd - 8) << 16) | (mt->HSyncStart - 8));	mga_outl(0x3C1C, ((mt->VDisplay - 1) << 16) | (mt->VTotal - 1));	mga_outl(0x3C20, ((mt->VSyncEnd - 1) << 16) | (mt->VSyncStart - 1));	mga_outl(0x3C24, ((mt->VSyncStart) << 16) | (mt->HSyncStart));	/* preload */	{		u_int32_t linelen = m2info->fbcon.var.xres_virtual * (m2info->fbcon.var.bits_per_pixel >> 3);		if (tmp & 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, datactl);	/* data control */	if (tmp & 0x02000000) {		int i;		mga_outl(0x3C10, tmp & ~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, tmp);	ACCESS_FBINFO(hw).crtc2.ctl = 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) {	/* no acceleration for secondary head... */	m2info->cmap[16] = 0xFFFFFFFF;}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);	m2info->fbcon.var.xoffset = var->xoffset;	m2info->fbcon.var.yoffset = var->yoffset;	pixelsize = m2info->fbcon.var.bits_per_pixel >> 3;	linelen = m2info->fbcon.var.xres_virtual * pixelsize;	pos = m2info->fbcon.var.yoffset * linelen + m2info->fbcon.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 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) {		case 16:	mask = 0x1F;				break;		case 32:	mask = 0x0F;				break;		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 int matroxfb_dh_open(struct fb_info* info, int user) {#define m2info (container_of(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(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 (container_of(info, struct matroxfb_dh_fb_info, fbcon))	int err = 0;	MINFO_FROM(m2info->primary_dev);	if (MINFO) {		err = ACCESS_FBINFO(fbops).fb_release(&ACCESS_FBINFO(fbcon), user);	}	return err;#undef m2info}static void matroxfb_dh_init_fix(struct matroxfb_dh_fb_info *m2info) {	struct fb_fix_screeninfo *fix = &m2info->fbcon.fix;	strcpy(fix->id, "MATROX DH");	fix->smem_start = m2info->video.base;	fix->smem_len = m2info->video.len_usable;	fix->ypanstep = 1;	fix->ywrapstep = 0;	fix->xpanstep = 8;	/* TBD */	fix->mmio_start = m2info->mmio.base;	fix->mmio_len = m2info->mmio.len;	fix->accel = 0;		/* no accel... */}static int matroxfb_dh_check_var(struct fb_var_screeninfo* var, struct fb_info* info) {#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon))	int visual;	int cmap_len;	int mode;	return matroxfb_dh_decode_var(m2info, var, &visual, &cmap_len, &mode);#undef m2info}static int matroxfb_dh_set_par(struct fb_info* info) {#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon))	int visual;	int cmap_len;	int mode;	int err;	struct fb_var_screeninfo* var = &info->var;	MINFO_FROM(m2info->primary_dev);	if ((err = matroxfb_dh_decode_var(m2info, var, &visual, &cmap_len, &mode)) != 0)		return err;	/* cmap */	{		m2info->fbcon.screen_base = vaddr_va(m2info->video.vbase);		m2info->fbcon.fix.visual = visual;		m2info->fbcon.fix.type = FB_TYPE_PACKED_PIXELS;		m2info->fbcon.fix.type_aux = 0;		m2info->fbcon.fix.line_length = (var->xres_virtual * var->bits_per_pixel) >> 3;	}	{		struct my_timming mt;		unsigned int pos;		int out;		int cnt;		matroxfb_var2my(&m2info->fbcon.var, &mt);		mt.crtc = MATROXFB_SRC_CRTC2;		/* CRTC2 delay */		mt.delay = 34;		pos = (m2info->fbcon.var.yoffset * m2info->fbcon.var.xres_virtual + m2info->fbcon.var.xoffset) * m2info->fbcon.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, mode, pos);		} else {			matroxfb_dh_disable(m2info);		}

⌨️ 快捷键说明

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