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

📄 cyber2000fb.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	hw->crtc[6]  = Vtotal;	hw->crtc[7]  = ENCODE_BIT(Vtotal,     8, 0x01,  0) |			ENCODE_BIT(Vdispend,   8, 0x01,  1) |			ENCODE_BIT(Vsyncstart, 8, 0x01,  2) |			ENCODE_BIT(Vblankstart, 8, 0x01,  3) |			ENCODE_BIT(1,          0, 0x01,  4) |			ENCODE_BIT(Vtotal,     9, 0x01,  5) |			ENCODE_BIT(Vdispend,   9, 0x01,  6) |			ENCODE_BIT(Vsyncstart, 9, 0x01,  7);	hw->crtc[9]  = ENCODE_BIT(0,          0, 0x1f,  0) |			ENCODE_BIT(Vblankstart, 9, 0x01,  5) |			ENCODE_BIT(1,          0, 0x01,  6);	hw->crtc[10] = Vsyncstart;	hw->crtc[11] = ENCODE_BIT(Vsyncend,   0, 0x0f,  0) |		       ENCODE_BIT(1,          0, 0x01,  7);	hw->crtc[12] = Vdispend;	hw->crtc[15] = Vblankstart;	hw->crtc[16] = Vblankend;	hw->crtc[18] = 0xff;	/*	 * overflow - graphics reg 0x11	 * 0=VTOTAL:10 1=VDEND:10 2=VRSTART:10 3=VBSTART:10	 * 4=LINECOMP:10 5-IVIDEO 6=FIXCNT	 */	hw->crtc_ofl =		ENCODE_BIT(Vtotal, 10, 0x01, 0) |		ENCODE_BIT(Vdispend, 10, 0x01, 1) |		ENCODE_BIT(Vsyncstart, 10, 0x01, 2) |		ENCODE_BIT(Vblankstart, 10, 0x01, 3) |		EXT_CRT_VRTOFL_LINECOMP10;	/* woody: set the interlaced bit... */	/* FIXME: what about doublescan? */	if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)		hw->crtc_ofl |= EXT_CRT_VRTOFL_INTERLACE;	return 0;}/* * The following was discovered by a good monitor, bit twiddling, theorising * and but mostly luck.  Strangely, it looks like everyone elses' PLL! * * Clock registers: *   fclock = fpll / div2 *   fpll   = fref * mult / div1 * where: *   fref = 14.318MHz (69842ps) *   mult = reg0xb0.7:0 *   div1 = (reg0xb1.5:0 + 1) *   div2 =  2^(reg0xb1.7:6) *   fpll should be between 115 and 260 MHz *  (8696ps and 3846ps) */static intcyber2000fb_decode_clock(struct par_info *hw, struct cfb_info *cfb,			 struct fb_var_screeninfo *var){	u_long pll_ps = var->pixclock;	const u_long ref_ps = cfb->ref_ps;	u_int div2, t_div1, best_div1, best_mult;	int best_diff;	int vco;	/*	 * Step 1:	 *   find div2 such that 115MHz < fpll < 260MHz	 *   and 0 <= div2 < 4	 */	for (div2 = 0; div2 < 4; div2++) {		u_long new_pll;		new_pll = pll_ps / cfb->divisors[div2];		if (8696 > new_pll && new_pll > 3846) {			pll_ps = new_pll;			break;		}	}	if (div2 == 4)		return -EINVAL;	/*	 * Step 2:	 *  Given pll_ps and ref_ps, find:	 *    pll_ps * 0.995 < pll_ps_calc < pll_ps * 1.005	 *  where { 1 < best_div1 < 32, 1 < best_mult < 256 }	 *    pll_ps_calc = best_div1 / (ref_ps * best_mult)	 */	best_diff = 0x7fffffff;	best_mult = 32;	best_div1 = 255;	for (t_div1 = 32; t_div1 > 1; t_div1 -= 1) {		u_int rr, t_mult, t_pll_ps;		int diff;		/*		 * Find the multiplier for this divisor		 */		rr = ref_ps * t_div1;		t_mult = (rr + pll_ps / 2) / pll_ps;		/*		 * Is the multiplier within the correct range?		 */		if (t_mult > 256 || t_mult < 2)			continue;		/*		 * Calculate the actual clock period from this multiplier		 * and divisor, and estimate the error.		 */		t_pll_ps = (rr + t_mult / 2) / t_mult;		diff = pll_ps - t_pll_ps;		if (diff < 0)			diff = -diff;		if (diff < best_diff) {			best_diff = diff;			best_mult = t_mult;			best_div1 = t_div1;		}		/*		 * If we hit an exact value, there is no point in continuing.		 */		if (diff == 0)			break;	}	/*	 * Step 3:	 *  combine values	 */	hw->clock_mult = best_mult - 1;	hw->clock_div  = div2 << 6 | (best_div1 - 1);	vco = ref_ps * best_div1 / best_mult;	if ((ref_ps == 40690) && (vco < 5556))		/* Set VFSEL when VCO > 180MHz (5.556 ps). */		hw->clock_div |= EXT_DCLK_DIV_VFSEL;	return 0;}/* *    Set the User Defined Part of the Display */static intcyber2000fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info){	struct cfb_info *cfb = (struct cfb_info *)info;	struct par_info hw;	unsigned int mem;	int err;	var->transp.msb_right	= 0;	var->red.msb_right	= 0;	var->green.msb_right	= 0;	var->blue.msb_right	= 0;	var->transp.offset	= 0;	var->transp.length	= 0;	switch (var->bits_per_pixel) {	case 8:	/* PSEUDOCOLOUR, 256 */		var->red.offset		= 0;		var->red.length		= 8;		var->green.offset	= 0;		var->green.length	= 8;		var->blue.offset	= 0;		var->blue.length	= 8;		break;	case 16:/* DIRECTCOLOUR, 64k or 32k */		switch (var->green.length) {		case 6: /* RGB565, 64k */			var->red.offset		= 11;			var->red.length		= 5;			var->green.offset	= 5;			var->green.length	= 6;			var->blue.offset	= 0;			var->blue.length	= 5;			break;		default:		case 5: /* RGB555, 32k */			var->red.offset		= 10;			var->red.length		= 5;			var->green.offset	= 5;			var->green.length	= 5;			var->blue.offset	= 0;			var->blue.length	= 5;			break;		case 4: /* RGB444, 4k + transparency? */			var->transp.offset	= 12;			var->transp.length	= 4;			var->red.offset		= 8;			var->red.length		= 4;			var->green.offset	= 4;			var->green.length	= 4;			var->blue.offset	= 0;			var->blue.length	= 4;			break;		}		break;	case 24:/* TRUECOLOUR, 16m */		var->red.offset		= 16;		var->red.length		= 8;		var->green.offset	= 8;		var->green.length	= 8;		var->blue.offset	= 0;		var->blue.length	= 8;		break;	case 32:/* TRUECOLOUR, 16m */		var->transp.offset	= 24;		var->transp.length	= 8;		var->red.offset		= 16;		var->red.length		= 8;		var->green.offset	= 8;		var->green.length	= 8;		var->blue.offset	= 0;		var->blue.length	= 8;		break;	default:		return -EINVAL;	}	mem = var->xres_virtual * var->yres_virtual * (var->bits_per_pixel / 8);	if (mem > cfb->fb.fix.smem_len)		var->yres_virtual = cfb->fb.fix.smem_len * 8 /				    (var->bits_per_pixel * var->xres_virtual);	if (var->yres > var->yres_virtual)		var->yres = var->yres_virtual;	if (var->xres > var->xres_virtual)		var->xres = var->xres_virtual;	err = cyber2000fb_decode_clock(&hw, cfb, var);	if (err)		return err;	err = cyber2000fb_decode_crtc(&hw, cfb, var);	if (err)		return err;	return 0;}static int cyber2000fb_set_par(struct fb_info *info){	struct cfb_info *cfb = (struct cfb_info *)info;	struct fb_var_screeninfo *var = &cfb->fb.var;	struct par_info hw;	unsigned int mem;	hw.width = var->xres_virtual;	hw.ramdac = RAMDAC_VREFEN | RAMDAC_DAC8BIT;	switch (var->bits_per_pixel) {	case 8:		hw.co_pixfmt		= CO_PIXFMT_8BPP;		hw.pitch		= hw.width >> 3;		hw.extseqmisc		= EXT_SEQ_MISC_8;		break;	case 16:		hw.co_pixfmt		= CO_PIXFMT_16BPP;		hw.pitch		= hw.width >> 2;		switch (var->green.length) {		case 6: /* RGB565, 64k */			hw.extseqmisc	= EXT_SEQ_MISC_16_RGB565;			break;		case 5: /* RGB555, 32k */			hw.extseqmisc	= EXT_SEQ_MISC_16_RGB555;			break;		case 4: /* RGB444, 4k + transparency? */			hw.extseqmisc	= EXT_SEQ_MISC_16_RGB444;			break;		default:			BUG();		}		break;	case 24:/* TRUECOLOUR, 16m */		hw.co_pixfmt		= CO_PIXFMT_24BPP;		hw.width		*= 3;		hw.pitch		= hw.width >> 3;		hw.ramdac		|= (RAMDAC_BYPASS | RAMDAC_RAMPWRDN);		hw.extseqmisc		= EXT_SEQ_MISC_24_RGB888;		break;	case 32:/* TRUECOLOUR, 16m */		hw.co_pixfmt		= CO_PIXFMT_32BPP;		hw.pitch		= hw.width >> 1;		hw.ramdac		|= (RAMDAC_BYPASS | RAMDAC_RAMPWRDN);		hw.extseqmisc		= EXT_SEQ_MISC_32;		break;	default:		BUG();	}	/*	 * Sigh, this is absolutely disgusting, but caused by	 * the way the fbcon developers want to separate out	 * the "checking" and the "setting" of the video mode.	 *	 * If the mode is not suitable for the hardware here,	 * we can't prevent it being set by returning an error.	 *	 * In theory, since NetWinders contain just one VGA card,	 * we should never end up hitting this problem.	 */	BUG_ON(cyber2000fb_decode_clock(&hw, cfb, var) != 0);	BUG_ON(cyber2000fb_decode_crtc(&hw, cfb, var) != 0);	hw.width -= 1;	hw.fetch = hw.pitch;	if (!(cfb->mem_ctl2 & MEM_CTL2_64BIT))		hw.fetch <<= 1;	hw.fetch += 1;	cfb->fb.fix.line_length = var->xres_virtual * var->bits_per_pixel / 8;	/*	 * Same here - if the size of the video mode exceeds the	 * available RAM, we can't prevent this mode being set.	 *	 * In theory, since NetWinders contain just one VGA card,	 * we should never end up hitting this problem.	 */	mem = cfb->fb.fix.line_length * var->yres_virtual;	BUG_ON(mem > cfb->fb.fix.smem_len);	/*	 * 8bpp displays are always pseudo colour.  16bpp and above	 * are direct colour or true colour, depending on whether	 * the RAMDAC palettes are bypassed.  (Direct colour has	 * palettes, true colour does not.)	 */	if (var->bits_per_pixel == 8)		cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;	else if (hw.ramdac & RAMDAC_BYPASS)		cfb->fb.fix.visual = FB_VISUAL_TRUECOLOR;	else		cfb->fb.fix.visual = FB_VISUAL_DIRECTCOLOR;	cyber2000fb_set_timing(cfb, &hw);	cyber2000fb_update_start(cfb, var);	return 0;}/* *    Pan or Wrap the Display */static intcyber2000fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info){	struct cfb_info *cfb = (struct cfb_info *)info;	if (cyber2000fb_update_start(cfb, var))		return -EINVAL;	cfb->fb.var.xoffset = var->xoffset;	cfb->fb.var.yoffset = var->yoffset;	if (var->vmode & FB_VMODE_YWRAP) {		cfb->fb.var.vmode |= FB_VMODE_YWRAP;	} else {		cfb->fb.var.vmode &= ~FB_VMODE_YWRAP;	}	return 0;}/* *    (Un)Blank the display. * *  Blank the screen if blank_mode != 0, else unblank. If *  blank == NULL then the caller blanks by setting the CLUT *  (Color Look Up Table) to all black. Return 0 if blanking *  succeeded, != 0 if un-/blanking failed due to e.g. a *  video mode which doesn't support it. Implements VESA *  suspend and powerdown modes on hardware that supports *  disabling hsync/vsync: *    blank_mode == 2: suspend vsync *    blank_mode == 3: suspend hsync *    blank_mode == 4: powerdown * *  wms...Enable VESA DMPS compatible powerdown mode *  run "setterm -powersave powerdown" to take advantage */static int cyber2000fb_blank(int blank, struct fb_info *info){	struct cfb_info *cfb = (struct cfb_info *)info;	unsigned int sync = 0;	int i;	switch (blank) {	case FB_BLANK_POWERDOWN:	/* powerdown - both sync lines down */		sync = EXT_SYNC_CTL_VS_0 | EXT_SYNC_CTL_HS_0;		break;	case FB_BLANK_HSYNC_SUSPEND:	/* hsync off */		sync = EXT_SYNC_CTL_VS_NORMAL | EXT_SYNC_CTL_HS_0;		break;	case FB_BLANK_VSYNC_SUSPEND:	/* vsync off */		sync = EXT_SYNC_CTL_VS_0 | EXT_SYNC_CTL_HS_NORMAL;		break;	case FB_BLANK_NORMAL:		/* soft blank */	default:			/* unblank */		break;	}	cyber2000_grphw(EXT_SYNC_CTL, sync, cfb);	if (blank <= 1) {		/* turn on ramdacs */		cfb->ramdac_powerdown &= ~(RAMDAC_DACPWRDN | RAMDAC_BYPASS |					   RAMDAC_RAMPWRDN);		cyber2000fb_write_ramdac_ctrl(cfb);	}	/*	 * Soft blank/unblank the display.	 */	if (blank) {	/* soft blank */		for (i = 0; i < NR_PALETTE; i++) {			cyber2000fb_writeb(i, 0x3c8, cfb);			cyber2000fb_writeb(0, 0x3c9, cfb);			cyber2000fb_writeb(0, 0x3c9, cfb);			cyber2000fb_writeb(0, 0x3c9, cfb);		}	} else {	/* unblank */		for (i = 0; i < NR_PALETTE; i++) {			cyber2000fb_writeb(i, 0x3c8, cfb);			cyber2000fb_writeb(cfb->palette[i].red, 0x3c9, cfb);			cyber2000fb_writeb(cfb->palette[i].green, 0x3c9, cfb);			cyber2000fb_writeb(cfb->palette[i].blue, 0x3c9, cfb);		}	}	if (blank >= 2) {		/* turn off ramdacs */		cfb->ramdac_powerdown |= RAMDAC_DACPWRDN | RAMDAC_BYPASS |					 RAMDAC_RAMPWRDN;		cyber2000fb_write_ramdac_ctrl(cfb);	}	return 0;}static struct fb_ops cyber2000fb_ops = {	.owner		= THIS_MODULE,	.fb_check_var	= cyber2000fb_check_var,	.fb_set_par	= cyber2000fb_set_par,	.fb_setcolreg	= cyber2000fb_setcolreg,	.fb_blank	= cyber2000fb_blank,	.fb_pan_display	= cyber2000fb_pan_display,	.fb_fillrect	= cyber2000fb_fillrect,	.fb_copyarea	= cyber2000fb_copyarea,	.fb_imageblit	= cyber2000fb_imageblit,	.fb_sync	= cyber2000fb_sync,};/* * This is the only "static" reference to the internal data structures * of this driver.  It is here solely at the moment to support the other * CyberPro modules external to this driver. */static struct cfb_info *int_cfb_info;/* * Enable access to the extended registers */void cyber2000fb_enable_extregs(struct cfb_info *cfb){	cfb->func_use_count += 1;	if (cfb->func_use_count == 1) {		int old;		old = cyber2000_grphr(EXT_FUNC_CTL, cfb);		old |= EXT_FUNC_CTL_EXTREGENBL;		cyber2000_grphw(EXT_FUNC_CTL, old, cfb);	}}EXPORT_SYMBOL(cyber2000fb_enable_extregs);/* * Disable access to the extended registers */void cyber2000fb_disable_extregs(struct cfb_info *cfb){	if (cfb->func_use_count == 1) {		int old;		old = cyber2000_grphr(EXT_FUNC_CTL, cfb);		old &= ~EXT_FUNC_CTL_EXTREGENBL;		cyber2000_grphw(EXT_FUNC_CTL, old, cfb);	}	if (cfb->func_use_count == 0)		printk(KERN_ERR "disable_extregs: count = 0\n");	else		cfb->func_use_count -= 1;}EXPORT_SYMBOL(cyber2000fb_disable_extregs);void cyber2000fb_get_fb_var(struct cfb_info *cfb, struct fb_var_screeninfo *var){	memcpy(var, &cfb->fb.var, sizeof(struct fb_var_screeninfo));}EXPORT_SYMBOL(cyber2000fb_get_fb_var);/* * Attach a capture/tv driver to the core CyberX0X0 driver. */int cyber2000fb_attach(struct cyberpro_info *info, int idx){	if (int_cfb_info != NULL) {		info->dev	      = int_cfb_info->dev;		info->regs	      = int_cfb_info->regs;		info->fb	      = int_cfb_info->fb.screen_base;		info->fb_size	      = int_cfb_info->fb.fix.smem_len;		info->enable_extregs  = cyber2000fb_enable_extregs;		info->disable_extregs = cyber2000fb_disable_extregs;		info->info	      = int_cfb_info;		strlcpy(info->dev_name, int_cfb_info->fb.fix.id,			sizeof(info->dev_name));	}	return int_cfb_info != NULL;}EXPORT_SYMBOL(cyber2000fb_attach);/* * Detach a capture/tv driver from the core CyberX0X0 driver. */void cyber2000fb_detach(int idx){}EXPORT_SYMBOL(cyber2000fb_detach);/* * These parameters give * 640x480, hsync 31.5kHz, vsync 60Hz */static struct fb_videomode __devinitdata cyber2000fb_default_mode = {	.refresh	= 60,	.xres		= 640,	.yres		= 480,	.pixclock	= 39722,	.left_margin	= 56,	.right_margin	= 16,	.upper_margin	= 34,	.lower_margin	= 9,	.hsync_len	= 88,	.vsync_len	= 2,	.sync		= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,	.vmode		= FB_VMODE_NONINTERLACED};static char igs_regs[] = {	EXT_CRT_IRQ,		0,	EXT_CRT_TEST,		0,	EXT_SYNC_CTL,		0,	EXT_SEG_WRITE_PTR,	0,	EXT_SEG_READ_PTR,	0,	EXT_BIU_MISC,		EXT_BIU_MISC_LIN_ENABLE |				EXT_BIU_MISC_COP_ENABLE |				EXT_BIU_MISC_COP_BFC,	EXT_FUNC_CTL,		0,	CURS_H_START,		0,	CURS_H_START + 1,	0,	CURS_H_PRESET,		0,	CURS_V_START,		0,	CURS_V_START + 1,	0,	CURS_V_PRESET,		0,	CURS_CTL,		0,	EXT_ATTRIB_CTL,		EXT_ATTRIB_CTL_EXT,	EXT_OVERSCAN_RED,	0,

⌨️ 快捷键说明

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