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

📄 imsttfb.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		case 1280:			init = yres == 960 ? &tvp_reg_init_19 : &tvp_reg_init_20;			break;		default:			return NULL;	}	par->init = *init;	return init;}static struct imstt_regvals *compute_imstt_regvals (struct imstt_par *par, u_int xres, u_int yres){	if (par->ramdac == IBM)		return compute_imstt_regvals_ibm(par, xres, yres);	else		return compute_imstt_regvals_tvp(par, xres, yres);}static voidset_imstt_regvals_ibm (struct imstt_par *par, u_int bpp){	struct imstt_regvals *init = &par->init;	__u8 pformat = (bpp >> 3) + 2;	par->cmap_regs[PIDXHI] = 0;		eieio();	par->cmap_regs[PIDXLO] = PIXM0;		eieio();	par->cmap_regs[PIDXDATA] = init->pclk_m;eieio();	par->cmap_regs[PIDXLO] = PIXN0;		eieio();	par->cmap_regs[PIDXDATA] = init->pclk_n;eieio();	par->cmap_regs[PIDXLO] = PIXP0;		eieio();	par->cmap_regs[PIDXDATA] = init->pclk_p;eieio();	par->cmap_regs[PIDXLO] = PIXC0;		eieio();	par->cmap_regs[PIDXDATA] = 0x02;	eieio();	par->cmap_regs[PIDXLO] = PIXFMT;	eieio();	par->cmap_regs[PIDXDATA] = pformat;	eieio();}static voidset_imstt_regvals_tvp (struct imstt_par *par, u_int bpp){	struct imstt_regvals *init = &par->init;	__u8 tcc, mxc, lckl_n, mic;	__u8 mlc, lckl_p;	switch (bpp) {		default:		case 8:			tcc = 0x80;			mxc = 0x4d;			lckl_n = 0xc1;			mlc = init->mlc[0];			lckl_p = init->lckl_p[0];			break;		case 16:			tcc = 0x44;			mxc = 0x55;			lckl_n = 0xe1;			mlc = init->mlc[1];			lckl_p = init->lckl_p[1];			break;		case 24:			tcc = 0x5e;			mxc = 0x5d;			lckl_n = 0xf1;			mlc = init->mlc[2];			lckl_p = init->lckl_p[2];			break;		case 32:			tcc = 0x46;			mxc = 0x5d;			lckl_n = 0xf1;			mlc = init->mlc[2];			lckl_p = init->lckl_p[2];			break;	}	mic = 0x08;	par->cmap_regs[TVPADDRW] = TVPIRPLA;		eieio();	par->cmap_regs[TVPIDATA] = 0x00;		eieio();	par->cmap_regs[TVPADDRW] = TVPIRPPD;		eieio();	par->cmap_regs[TVPIDATA] = init->pclk_m;	eieio();	par->cmap_regs[TVPADDRW] = TVPIRPPD;		eieio();	par->cmap_regs[TVPIDATA] = init->pclk_n;	eieio();	par->cmap_regs[TVPADDRW] = TVPIRPPD;		eieio();	par->cmap_regs[TVPIDATA] = init->pclk_p;	eieio();	par->cmap_regs[TVPADDRW] = TVPIRTCC;		eieio();	par->cmap_regs[TVPIDATA] = tcc;			eieio();	par->cmap_regs[TVPADDRW] = TVPIRMXC;		eieio();	par->cmap_regs[TVPIDATA] = mxc;			eieio();	par->cmap_regs[TVPADDRW] = TVPIRMIC;		eieio();	par->cmap_regs[TVPIDATA] = mic;			eieio();	par->cmap_regs[TVPADDRW] = TVPIRPLA;		eieio();	par->cmap_regs[TVPIDATA] = 0x00;		eieio();	par->cmap_regs[TVPADDRW] = TVPIRLPD;		eieio();	par->cmap_regs[TVPIDATA] = lckl_n;		eieio();	par->cmap_regs[TVPADDRW] = TVPIRPLA;		eieio();	par->cmap_regs[TVPIDATA] = 0x15;		eieio();	par->cmap_regs[TVPADDRW] = TVPIRMLC;		eieio();	par->cmap_regs[TVPIDATA] = mlc;			eieio();	par->cmap_regs[TVPADDRW] = TVPIRPLA;		eieio();	par->cmap_regs[TVPIDATA] = 0x2a;		eieio();	par->cmap_regs[TVPADDRW] = TVPIRLPD;		eieio();	par->cmap_regs[TVPIDATA] = lckl_p;		eieio();}static voidset_imstt_regvals (struct fb_info *info, u_int bpp){	struct imstt_par *par = info->par;	struct imstt_regvals *init = &par->init;	__u32 ctl, pitch, byteswap, scr;	if (par->ramdac == IBM)		set_imstt_regvals_ibm(par, bpp);	else		set_imstt_regvals_tvp(par, bpp);  /*   * From what I (jsk) can gather poking around with MacsBug,   * bits 8 and 9 in the SCR register control endianness   * correction (byte swapping).  These bits must be set according   * to the color depth as follows:   *     Color depth    Bit 9   Bit 8   *     ==========     =====   =====   *        8bpp          0       0   *       16bpp          0       1   *       32bpp          1       1   */	switch (bpp) {		default:		case 8:			ctl = 0x17b1;			pitch = init->pitch >> 2;			byteswap = 0x000;			break;		case 16:			ctl = 0x17b3;			pitch = init->pitch >> 1;			byteswap = 0x100;			break;		case 24:			ctl = 0x17b9;			pitch = init->pitch - (init->pitch >> 2);			byteswap = 0x200;			break;		case 32:			ctl = 0x17b5;			pitch = init->pitch;			byteswap = 0x300;			break;	}	if (par->ramdac == TVP)		ctl -= 0x30;	write_reg_le32(par->dc_regs, HES, init->hes);	write_reg_le32(par->dc_regs, HEB, init->heb);	write_reg_le32(par->dc_regs, HSB, init->hsb);	write_reg_le32(par->dc_regs, HT, init->ht);	write_reg_le32(par->dc_regs, VES, init->ves);	write_reg_le32(par->dc_regs, VEB, init->veb);	write_reg_le32(par->dc_regs, VSB, init->vsb);	write_reg_le32(par->dc_regs, VT, init->vt);	write_reg_le32(par->dc_regs, VIL, init->vil);	write_reg_le32(par->dc_regs, HCIV, 1);	write_reg_le32(par->dc_regs, VCIV, 1);	write_reg_le32(par->dc_regs, TCDR, 4);	write_reg_le32(par->dc_regs, RRCIV, 1);	write_reg_le32(par->dc_regs, RRSC, 0x980);	write_reg_le32(par->dc_regs, RRCR, 0x11);	if (par->ramdac == IBM) {		write_reg_le32(par->dc_regs, HRIR, 0x0100);		write_reg_le32(par->dc_regs, CMR, 0x00ff);		write_reg_le32(par->dc_regs, SRGCTL, 0x0073);	} else {		write_reg_le32(par->dc_regs, HRIR, 0x0200);		write_reg_le32(par->dc_regs, CMR, 0x01ff);		write_reg_le32(par->dc_regs, SRGCTL, 0x0003);	}	switch (info->fix.smem_len) {		case 0x200000:			scr = 0x059d | byteswap;			break;		/* case 0x400000:		   case 0x800000: */		default:			pitch >>= 1;			scr = 0x150dd | byteswap;			break;	}	write_reg_le32(par->dc_regs, SCR, scr);	write_reg_le32(par->dc_regs, SPR, pitch);	write_reg_le32(par->dc_regs, STGCTL, ctl);}static inline voidset_offset (struct fb_var_screeninfo *var, struct fb_info *info){	struct imstt_par *par = info->par;	__u32 off = var->yoffset * (info->fix.line_length >> 3)		    + ((var->xoffset * (var->bits_per_pixel >> 3)) >> 3);	write_reg_le32(par->dc_regs, SSR, off);}static inline voidset_555 (struct imstt_par *par){	if (par->ramdac == IBM) {		par->cmap_regs[PIDXHI] = 0;		eieio();		par->cmap_regs[PIDXLO] = BPP16;		eieio();		par->cmap_regs[PIDXDATA] = 0x01;	eieio();	} else {		par->cmap_regs[TVPADDRW] = TVPIRTCC;	eieio();		par->cmap_regs[TVPIDATA] = 0x44;	eieio();	}}static inline voidset_565 (struct imstt_par *par){	if (par->ramdac == IBM) {		par->cmap_regs[PIDXHI] = 0;		eieio();		par->cmap_regs[PIDXLO] = BPP16;		eieio();		par->cmap_regs[PIDXDATA] = 0x03;	eieio();	} else {		par->cmap_regs[TVPADDRW] = TVPIRTCC;	eieio();		par->cmap_regs[TVPIDATA] = 0x45;	eieio();	}}static intimsttfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info){	if ((var->bits_per_pixel != 8 && var->bits_per_pixel != 16	    && var->bits_per_pixel != 24 && var->bits_per_pixel != 32)	    || var->xres_virtual < var->xres || var->yres_virtual < var->yres	    || var->nonstd	    || (var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)		return -EINVAL;	if ((var->xres * var->yres) * (var->bits_per_pixel >> 3) > info->fix.smem_len	    || (var->xres_virtual * var->yres_virtual) * (var->bits_per_pixel >> 3) > info->fix.smem_len)		return -EINVAL;	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:	/* RGB 555 or 565 */			if (var->green.length != 6)				var->red.offset = 10;			var->red.length = 5;			var->green.offset = 5;			if (var->green.length != 6)				var->green.length = 5;			var->blue.offset = 0;			var->blue.length = 5;			var->transp.offset = 0;			var->transp.length = 0;			break;		case 24:	/* RGB 888 */			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 = 0;			var->transp.length = 0;			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.offset = 24;			var->transp.length = 8;			break;	}	if (var->yres == var->yres_virtual) {		__u32 vram = (info->fix.smem_len - (PAGE_SIZE << 2));		var->yres_virtual = ((vram << 3) / var->bits_per_pixel) / var->xres_virtual;		if (var->yres_virtual < var->yres)			var->yres_virtual = var->yres;	}	var->red.msb_right = 0;	var->green.msb_right = 0;	var->blue.msb_right = 0;	var->transp.msb_right = 0;	var->height = -1;	var->width = -1;	var->vmode = FB_VMODE_NONINTERLACED;	var->left_margin = var->right_margin = 16;	var->upper_margin = var->lower_margin = 16;	var->hsync_len = var->vsync_len = 8;	return 0;}static intimsttfb_set_par(struct fb_info *info) {	struct imstt_par *par = info->par;			if (!compute_imstt_regvals(par, info->var.xres, info->var.yres))		return -EINVAL;	if (info->var.green.length == 6)		set_565(par);	else		set_555(par);	set_imstt_regvals(info, info->var.bits_per_pixel);	info->var.pixclock = 1000000 / getclkMHz(par);	return 0;}static intimsttfb_setcolreg (u_int regno, u_int red, u_int green, u_int blue,		   u_int transp, struct fb_info *info){	struct imstt_par *par = info->par;	u_int bpp = info->var.bits_per_pixel;	if (regno > 255)		return 1;	red >>= 8;	green >>= 8;	blue >>= 8;	/* PADDRW/PDATA are the same as TVPPADDRW/TVPPDATA */	if (0 && bpp == 16)	/* screws up X */		par->cmap_regs[PADDRW] = regno << 3;	else		par->cmap_regs[PADDRW] = regno;	eieio();	par->cmap_regs[PDATA] = red;	eieio();	par->cmap_regs[PDATA] = green;	eieio();	par->cmap_regs[PDATA] = blue;	eieio();	if (regno < 16)		switch (bpp) {			case 16:				par->palette[regno] =					(regno << (info->var.green.length ==					5 ? 10 : 11)) | (regno << 5) | regno;				break;			case 24:				par->palette[regno] =					(regno << 16) | (regno << 8) | regno;				break;			case 32: {				int i = (regno << 8) | regno;				par->palette[regno] = (i << 16) |i;				break;			}		}	return 0;}static intimsttfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info){	if (var->xoffset + info->var.xres > info->var.xres_virtual	    || var->yoffset + info->var.yres > info->var.yres_virtual)		return -EINVAL;	info->var.xoffset = var->xoffset;	info->var.yoffset = var->yoffset;	set_offset(var, info);	return 0;}static int imsttfb_blank(int blank, struct fb_info *info){	struct imstt_par *par = info->par;	__u32 ctrl;	ctrl = read_reg_le32(par->dc_regs, STGCTL);	if (blank > 0) {		switch (blank) {		case FB_BLANK_NORMAL:		case FB_BLANK_POWERDOWN:			ctrl &= ~0x00000380;			if (par->ramdac == IBM) {				par->cmap_regs[PIDXHI] = 0;		eieio();				par->cmap_regs[PIDXLO] = MISCTL2;	eieio();				par->cmap_regs[PIDXDATA] = 0x55;	eieio();				par->cmap_regs[PIDXLO] = MISCTL1;	eieio();				par->cmap_regs[PIDXDATA] = 0x11;	eieio();				par->cmap_regs[PIDXLO] = SYNCCTL;	eieio();				par->cmap_regs[PIDXDATA] = 0x0f;	eieio();				par->cmap_regs[PIDXLO] = PWRMNGMT;	eieio();				par->cmap_regs[PIDXDATA] = 0x1f;	eieio();				par->cmap_regs[PIDXLO] = CLKCTL;	eieio();				par->cmap_regs[PIDXDATA] = 0xc0;			}			break;		case FB_BLANK_VSYNC_SUSPEND:			ctrl &= ~0x00000020;			break;		case FB_BLANK_HSYNC_SUSPEND:			ctrl &= ~0x00000010;			break;		}	} else {		if (par->ramdac == IBM) {			ctrl |= 0x000017b0;			par->cmap_regs[PIDXHI] = 0;		eieio();			par->cmap_regs[PIDXLO] = CLKCTL;	eieio();			par->cmap_regs[PIDXDATA] = 0x01;	eieio();			par->cmap_regs[PIDXLO] = PWRMNGMT;	eieio();			par->cmap_regs[PIDXDATA] = 0x00;	eieio();			par->cmap_regs[PIDXLO] = SYNCCTL;	eieio();			par->cmap_regs[PIDXDATA] = 0x00;	eieio();			par->cmap_regs[PIDXLO] = MISCTL1;	eieio();			par->cmap_regs[PIDXDATA] = 0x01;	eieio();			par->cmap_regs[PIDXLO] = MISCTL2;	eieio();			par->cmap_regs[PIDXDATA] = 0x45;	eieio();		} else			ctrl |= 0x00001780;	}	write_reg_le32(par->dc_regs, STGCTL, ctrl);	return 0;}static voidimsttfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect){ 	struct imstt_par *par = info->par;	__u32 Bpp, line_pitch, bgc, dx, dy, width, height;	bgc = rect->color;	bgc |= (bgc << 8);	bgc |= (bgc << 16);	Bpp = info->var.bits_per_pixel >> 3,	line_pitch = info->fix.line_length;	dy = rect->dy * line_pitch;	dx = rect->dx * Bpp;	height = rect->height;	height--;	width = rect->width * Bpp;	width--;	if (rect->rop == ROP_COPY) {		while(read_reg_le32(par->dc_regs, SSTATUS) & 0x80);		write_reg_le32(par->dc_regs, DSA, dy + dx);		write_reg_le32(par->dc_regs, CNT, (height << 16) | width);		write_reg_le32(par->dc_regs, DP_OCTL, line_pitch);		write_reg_le32(par->dc_regs, BI, 0xffffffff);		write_reg_le32(par->dc_regs, MBC, 0xffffffff);		write_reg_le32(par->dc_regs, CLR, bgc);		write_reg_le32(par->dc_regs, BLTCTL, 0x840); /* 0x200000 */		while(read_reg_le32(par->dc_regs, SSTATUS) & 0x80);		while(read_reg_le32(par->dc_regs, SSTATUS) & 0x40);	} else {		while(read_reg_le32(par->dc_regs, SSTATUS) & 0x80);		write_reg_le32(par->dc_regs, DSA, dy + dx);		write_reg_le32(par->dc_regs, S1SA, dy + dx);		write_reg_le32(par->dc_regs, CNT, (height << 16) | width);		write_reg_le32(par->dc_regs, DP_OCTL, line_pitch);		write_reg_le32(par->dc_regs, SP, line_pitch);		write_reg_le32(par->dc_regs, BLTCTL, 0x40005);		while(read_reg_le32(par->dc_regs, SSTATUS) & 0x80);		while(read_reg_le32(par->dc_regs, SSTATUS) & 0x40);	}}static voidimsttfb_copyarea(struct fb_info *info, const struct fb_copyarea *area){	struct imstt_par *par = info->par;	__u32 Bpp, line_pitch, fb_offset_old, fb_offset_new, sp, dp_octl; 	__u32 cnt, bltctl, sx, sy, dx, dy, height, width;	Bpp = info->var.bits_per_pixel >> 3,	sx = area->sx * Bpp;	sy = area->sy;	dx = area->dx * Bpp;	dy = area->dy;	height = area->height;	height--;	width = area->width * Bpp;	width--;	line_pitch = info->fix.line_length;	bltctl = 0x05;	sp = line_pitch << 16;	cnt = height << 16;	if (sy < dy) {		sy += height;		dy += height;		sp |= -(line_pitch) & 0xffff;		dp_octl = -(line_pitch) & 0xffff;	} else {		sp |= line_pitch;		dp_octl = line_pitch;	}	if (sx < dx) {		sx += width;		dx += width;		bltctl |= 0x80;		cnt |= -(width) & 0xffff;	} else {		cnt |= width;	}	fb_offset_old = sy * line_pitch + sx;	fb_offset_new = dy * line_pitch + dx;	while(read_reg_le32(par->dc_regs, SSTATUS) & 0x80);	write_reg_le32(par->dc_regs, S1SA, fb_offset_old);	write_reg_le32(par->dc_regs, SP, sp);	write_reg_le32(par->dc_regs, DSA, fb_offset_new);	write_reg_le32(par->dc_regs, CNT, cnt);	write_reg_le32(par->dc_regs, DP_OCTL, dp_octl);	write_reg_le32(par->dc_regs, BLTCTL, bltctl);	while(read_reg_le32(par->dc_regs, SSTATUS) & 0x80);	while(read_reg_le32(par->dc_regs, SSTATUS) & 0x40);}

⌨️ 快捷键说明

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