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

📄 atafb.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		     (hfreq * 2) / (par->VFT + 1 + 4 * lines) >		     fb_info.monspecs.vfmax;		     lines += 2)			;		upper_margin += lines;		lower_margin += lines;		goto again;	} else if (vfreq > fb_info.monspecs.vfmax && interlace) {		/* Interlace, too high -> enlarge margins */		int lines;		for (lines = 0;		     (hfreq * 2) / (par->VFT + 1 + 4 * lines) >		     fb_info.monspecs.vfmax;		     lines++)			;		upper_margin += lines;		lower_margin += lines;		goto again;	} else if (vfreq < fb_info.monspecs.vfmin ||		   vfreq > fb_info.monspecs.vfmax)		return -EINVAL;set_screen_base:	linelen = xres_virtual * bpp / 8;	if (yres_virtual * linelen > screen_len && screen_len)		return -EINVAL;	if (yres * linelen > screen_len && screen_len)		return -EINVAL;	if (var->yoffset + yres > yres_virtual && yres_virtual)		return -EINVAL;	par->yres_virtual = yres_virtual;	par->screen_base = screen_base + var->yoffset * linelen;	par->hw.falcon.xoffset = 0;	par->next_line = linelen;	return 0;}static int falcon_encode_var(struct fb_var_screeninfo *var,			     struct atafb_par *par){/* !!! only for VGA !!! */	int linelen;	int prescale, plen;	int hdb_off, hde_off, base_off;	struct falcon_hw *hw = &par->hw.falcon;	memset(var, 0, sizeof(struct fb_var_screeninfo));	/* possible frequencies: 25.175 or 32MHz */	var->pixclock = hw->sync & 0x1 ? fext.t :	                hw->vid_control & VCO_CLOCK25 ? f25.t : f32.t;	var->height = -1;	var->width = -1;	var->sync = 0;	if (hw->vid_control & VCO_HSYPOS)		var->sync |= FB_SYNC_HOR_HIGH_ACT;	if (hw->vid_control & VCO_VSYPOS)		var->sync |= FB_SYNC_VERT_HIGH_ACT;	var->vmode = FB_VMODE_NONINTERLACED;	if (hw->vid_mode & VMO_INTER)		var->vmode |= FB_VMODE_INTERLACED;	if (hw->vid_mode & VMO_DOUBLE)		var->vmode |= FB_VMODE_DOUBLE;	/* visible y resolution:	 * Graphics display starts at line VDB and ends at line	 * VDE. If interlace mode off unit of VC-registers is	 * half lines, else lines.	 */	var->yres = hw->vde - hw->vdb;	if (!(var->vmode & FB_VMODE_INTERLACED))		var->yres >>= 1;	if (var->vmode & FB_VMODE_DOUBLE)		var->yres >>= 1;	/*	 * to get bpp, we must examine f_shift and st_shift.	 * f_shift is valid if any of bits no. 10, 8 or 4	 * is set. Priority in f_shift is: 10 ">" 8 ">" 4, i.e.	 * if bit 10 set then bit 8 and bit 4 don't care...	 * If all these bits are 0 get display depth from st_shift	 * (as for ST and STE)	 */	if (hw->f_shift & 0x400)	/* 2 colors */		var->bits_per_pixel = 1;	else if (hw->f_shift & 0x100)	/* hicolor */		var->bits_per_pixel = 16;	else if (hw->f_shift & 0x010)	/* 8 bitplanes */		var->bits_per_pixel = 8;	else if (hw->st_shift == 0)		var->bits_per_pixel = 4;	else if (hw->st_shift == 0x100)		var->bits_per_pixel = 2;	else				/* if (hw->st_shift == 0x200) */		var->bits_per_pixel = 1;	var->xres = hw->line_width * 16 / var->bits_per_pixel;	var->xres_virtual = var->xres + hw->line_offset * 16 / var->bits_per_pixel;	if (hw->xoffset)		var->xres_virtual += 16;	if (var->bits_per_pixel == 16) {		var->red.offset = 11;		var->red.length = 5;		var->red.msb_right = 0;		var->green.offset = 5;		var->green.length = 6;		var->green.msb_right = 0;		var->blue.offset = 0;		var->blue.length = 5;		var->blue.msb_right = 0;	} else {		var->red.offset = 0;		var->red.length = hw->ste_mode ? 4 : 6;		if (var->red.length > var->bits_per_pixel)			var->red.length = var->bits_per_pixel;		var->red.msb_right = 0;		var->grayscale = 0;		var->blue = var->green = var->red;	}	var->transp.offset = 0;	var->transp.length = 0;	var->transp.msb_right = 0;	linelen = var->xres_virtual * var->bits_per_pixel / 8;	if (screen_len) {		if (par->yres_virtual)			var->yres_virtual = par->yres_virtual;		else			/* yres_virtual == 0 means use maximum */			var->yres_virtual = screen_len / linelen;	} else {		if (hwscroll < 0)			var->yres_virtual = 2 * var->yres;		else			var->yres_virtual = var->yres + hwscroll * 16;	}	var->xoffset = 0;		/* TODO change this */	/* hdX-offsets */	prescale = hxx_prescale(hw);	plen = 4 >> (hw->vid_mode >> 2 & 0x3);	base_off = hw->vid_control & VCO_SHORTOFFS ? 64 : 128;	if (hw->f_shift & 0x100) {		hde_off = 0;		hdb_off = (base_off + 16 * plen) + prescale;	} else {		hde_off = ((128 / var->bits_per_pixel + 2) * plen);		if (hw->ste_mode)			hdb_off = (64 + base_off + (128 / var->bits_per_pixel + 2) * plen)					 + prescale;		else			hdb_off = (base_off + (128 / var->bits_per_pixel + 18) * plen)					 + prescale;	}	/* Right margin includes hsync */	var->left_margin = hdb_off + prescale * ((hw->hdb & 0x1ff) -					   (hw->hdb & 0x200 ? 2 + hw->hht : 0));	if (hw->ste_mode || mon_type != F_MON_VGA)		var->right_margin = prescale * (hw->hht + 2 - hw->hde) - hde_off;	else		/* can't use this in ste_mode, because hbb is +1 off */		var->right_margin = prescale * (hw->hht + 2 - hw->hbb);	var->hsync_len = prescale * (hw->hht + 2 - hw->hss);	/* Lower margin includes vsync */	var->upper_margin = hw->vdb / 2;	/* round down to full lines */	var->lower_margin = (hw->vft + 1 - hw->vde + 1) / 2;	/* round up */	var->vsync_len = (hw->vft + 1 - hw->vss + 1) / 2;	/* round up */	if (var->vmode & FB_VMODE_INTERLACED) {		var->upper_margin *= 2;		var->lower_margin *= 2;		var->vsync_len *= 2;	} else if (var->vmode & FB_VMODE_DOUBLE) {		var->upper_margin = (var->upper_margin + 1) / 2;		var->lower_margin = (var->lower_margin + 1) / 2;		var->vsync_len = (var->vsync_len + 1) / 2;	}	var->pixclock *= plen;	var->left_margin /= plen;	var->right_margin /= plen;	var->hsync_len /= plen;	var->right_margin -= var->hsync_len;	var->lower_margin -= var->vsync_len;	if (screen_base)		var->yoffset = (par->screen_base - screen_base) / linelen;	else		var->yoffset = 0;	var->nonstd = 0;		/* what is this for? */	var->activate = 0;	return 0;}static int f_change_mode;static struct falcon_hw f_new_mode;static int f_pan_display;static void falcon_get_par(struct atafb_par *par){	unsigned long addr;	struct falcon_hw *hw = &par->hw.falcon;	hw->line_width = shifter_f030.scn_width;	hw->line_offset = shifter_f030.off_next;	hw->st_shift = videl.st_shift & 0x300;	hw->f_shift = videl.f_shift;	hw->vid_control = videl.control;	hw->vid_mode = videl.mode;	hw->sync = shifter.syncmode & 0x1;	hw->xoffset = videl.xoffset & 0xf;	hw->hht = videl.hht;	hw->hbb = videl.hbb;	hw->hbe = videl.hbe;	hw->hdb = videl.hdb;	hw->hde = videl.hde;	hw->hss = videl.hss;	hw->vft = videl.vft;	hw->vbb = videl.vbb;	hw->vbe = videl.vbe;	hw->vdb = videl.vdb;	hw->vde = videl.vde;	hw->vss = videl.vss;	addr = (shifter.bas_hi & 0xff) << 16 |	       (shifter.bas_md & 0xff) << 8  |	       (shifter.bas_lo & 0xff);	par->screen_base = phys_to_virt(addr);	/* derived parameters */	hw->ste_mode = (hw->f_shift & 0x510) == 0 && hw->st_shift == 0x100;	hw->mono = (hw->f_shift & 0x400) ||	           ((hw->f_shift & 0x510) == 0 && hw->st_shift == 0x200);}static void falcon_set_par(struct atafb_par *par){	f_change_mode = 0;	/* only set screen_base if really necessary */	if (current_par.screen_base != par->screen_base)		fbhw->set_screen_base(par->screen_base);	/* Don't touch any other registers if we keep the default resolution */	if (DontCalcRes)		return;	/* Tell vbl-handler to change video mode.	 * We change modes only on next VBL, to avoid desynchronisation	 * (a shift to the right and wrap around by a random number of pixels	 * in all monochrome modes).	 * This seems to work on my Falcon.	 */	f_new_mode = par->hw.falcon;	f_change_mode = 1;}static irqreturn_t falcon_vbl_switcher(int irq, void *dummy){	struct falcon_hw *hw = &f_new_mode;	if (f_change_mode) {		f_change_mode = 0;		if (hw->sync & 0x1) {			/* Enable external pixelclock. This code only for ScreenWonder */			*(volatile unsigned short *)0xffff9202 = 0xffbf;		} else {			/* Turn off external clocks. Read sets all output bits to 1. */			*(volatile unsigned short *)0xffff9202;		}		shifter.syncmode = hw->sync;		videl.hht = hw->hht;		videl.hbb = hw->hbb;		videl.hbe = hw->hbe;		videl.hdb = hw->hdb;		videl.hde = hw->hde;		videl.hss = hw->hss;		videl.vft = hw->vft;		videl.vbb = hw->vbb;		videl.vbe = hw->vbe;		videl.vdb = hw->vdb;		videl.vde = hw->vde;		videl.vss = hw->vss;		videl.f_shift = 0;	/* write enables Falcon palette, 0: 4 planes */		if (hw->ste_mode) {			videl.st_shift = hw->st_shift;	/* write enables STE palette */		} else {			/* IMPORTANT:			 * set st_shift 0, so we can tell the screen-depth if f_shift == 0.			 * Writing 0 to f_shift enables 4 plane Falcon mode but			 * doesn't set st_shift. st_shift != 0 (!= 4planes) is impossible			 * with Falcon palette.			 */			videl.st_shift = 0;			/* now back to Falcon palette mode */			videl.f_shift = hw->f_shift;		}		/* writing to st_shift changed scn_width and vid_mode */		videl.xoffset = hw->xoffset;		shifter_f030.scn_width = hw->line_width;		shifter_f030.off_next = hw->line_offset;		videl.control = hw->vid_control;		videl.mode = hw->vid_mode;	}	if (f_pan_display) {		f_pan_display = 0;		videl.xoffset = current_par.hw.falcon.xoffset;		shifter_f030.off_next = current_par.hw.falcon.line_offset;	}	return IRQ_HANDLED;}static int falcon_pan_display(struct fb_var_screeninfo *var,			      struct fb_info *info){	struct atafb_par *par = (struct atafb_par *)info->par;	int xoffset;	int bpp = info->var.bits_per_pixel;	if (bpp == 1)		var->xoffset = up(var->xoffset, 32);	if (bpp != 16)		par->hw.falcon.xoffset = var->xoffset & 15;	else {		par->hw.falcon.xoffset = 0;		var->xoffset = up(var->xoffset, 2);	}	par->hw.falcon.line_offset = bpp *		(info->var.xres_virtual - info->var.xres) / 16;	if (par->hw.falcon.xoffset)		par->hw.falcon.line_offset -= bpp;	xoffset = var->xoffset - par->hw.falcon.xoffset;	par->screen_base = screen_base +	        (var->yoffset * info->var.xres_virtual + xoffset) * bpp / 8;	if (fbhw->set_screen_base)		fbhw->set_screen_base(par->screen_base);	else		return -EINVAL;		/* shouldn't happen */	f_pan_display = 1;	return 0;}static int falcon_setcolreg(unsigned int regno, unsigned int red,			    unsigned int green, unsigned int blue,			    unsigned int transp, struct fb_info *info){	if (regno > 255)		return 1;	f030_col[regno] = (((red & 0xfc00) << 16) |			   ((green & 0xfc00) << 8) |			   ((blue & 0xfc00) >> 8));	if (regno < 16) {		shifter_tt.color_reg[regno] =			(((red & 0xe000) >> 13) | ((red & 0x1000) >> 12) << 8) |			(((green & 0xe000) >> 13) | ((green & 0x1000) >> 12) << 4) |			((blue & 0xe000) >> 13) | ((blue & 0x1000) >> 12);#ifdef ATAFB_FALCON		((u32 *)info->pseudo_palette)[regno] = ((red & 0xf800) |						       ((green & 0xfc00) >> 5) |						       ((blue & 0xf800) >> 11));#endif	}	return 0;}static int falcon_blank(int blank_mode){	/* ++guenther: we can switch off graphics by changing VDB and VDE,	 * so VIDEL doesn't hog the bus while saving.	 * (this may affect usleep()).	 */	int vdb, vss, hbe, hss;	if (mon_type == F_MON_SM)	/* this doesn't work on SM124 */		return 1;	vdb = current_par.VDB;	vss = current_par.VSS;	hbe = current_par.HBE;	hss = current_par.HSS;	if (blank_mode >= 1) {		/* disable graphics output (this speeds up the CPU) ... */		vdb = current_par.VFT + 1;		/* ... and blank all lines */		hbe = current_par.HHT + 2;	}	/* use VESA suspend modes on VGA monitors */	if (mon_type == F_MON_VGA) {		if (blank_mode == 2 || blank_mode == 4)			vss = current_par.VFT + 1;		if (blank_mode == 3 || blank_mode == 4)			hss = current_par.HHT + 2;	}	videl.vdb = vdb;	videl.vss = vss;	videl.hbe = hbe;	videl.hss = hss;	return 0;}static int falcon_detect(void){	struct atafb_par par;	unsigned char fhw;	/* Determine connected monitor and set monitor parameters */	fhw = *(unsigned char *)0xffff8006;	mon_type = fhw >> 6 & 0x3;	/* bit 1 of fhw: 1=32 bit ram bus, 0=16 bit */	f030_bus_width = fhw << 6 & 0x80;	switch (mon_type) {	case F_MON_SM:		fb_info.monspecs.vfmin = 70;		fb_info.monspecs.vfmax = 72;		fb_info.monspecs.hfmin = 35713;		fb_info.monspecs.hfmax = 35715;		break;	case F_MON_SC:	case F_MON_TV:		/* PAL...NTSC */		fb_info.monspecs.vfmin = 49;	/* not 50, since TOS defaults to 49.9x Hz */		fb_info.monspecs.vfmax = 60;		fb_info.monspecs.hfmin = 15620;		fb_info.monspecs.hfmax = 15755;		break;	}	/* initialize hsync-len */	f25.hsync = h_syncs[mon_type] / f25.t;	f32.hsync = h_syncs[mon_type] / f32.t;	if (fext.t)		fext.hsync = h_syncs[mon_type] / fext.t;	falcon_get_par(&par);	falcon_encode_var(&atafb_predefined[0], &par);	/* Detected mode is always the "autodetect" slot */	return 1;}

⌨️ 快捷键说明

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