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

📄 cyber2000fb.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 3 页
字号:
	hw->crtc[3] = BIT(Hblankend,  0, 0x1f,  0) |		      BIT(1,          0, 0x01,  7);	Hsyncend    = (var->xres + var->right_margin + var->hsync_len) >> 3;	hw->crtc[5] = BIT(Hsyncend,   0, 0x1f,  0) |		      BIT(Hblankend,  5, 0x01,  7);	Vdispend    = var->yres - 1;	Vsyncstart  = var->yres + var->lower_margin;	Vsyncend    = var->yres + var->lower_margin + var->vsync_len;	Vtotal      = var->yres + var->lower_margin + var->vsync_len +		      var->upper_margin - 2;	if (Vtotal > 2047)		return -EINVAL;	Vblankstart = var->yres + 6;	Vblankend   = Vtotal - 10;	hw->crtc[6]  = Vtotal;	hw->crtc[7]  = BIT(Vtotal,     8, 0x01,  0) |			BIT(Vdispend,   8, 0x01,  1) |			BIT(Vsyncstart, 8, 0x01,  2) |			BIT(Vblankstart,8, 0x01,  3) |			BIT(1,          0, 0x01,  4) |	        	BIT(Vtotal,     9, 0x01,  5) |			BIT(Vdispend,   9, 0x01,  6) |			BIT(Vsyncstart, 9, 0x01,  7);	hw->crtc[9]  = BIT(0,          0, 0x1f,  0) |		        BIT(Vblankstart,9, 0x01,  5) |			BIT(1,          0, 0x01,  6);	hw->crtc[10] = Vsyncstart;	hw->crtc[11] = BIT(Vsyncend,   0, 0x0f,  0) |		       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 =		BIT(Vtotal,     10, 0x01,  0) |		BIT(Vdispend,   10, 0x01,  1) |		BIT(Vsyncstart, 10, 0x01,  2) |		BIT(Vblankstart,10, 0x01,  3) |		1 << 4;	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;}/* * Decode the info required for the hardware. * This involves the PLL parameters for the dot clock, * CRTC registers, and accelerator settings. */static intcyber2000fb_decode_var(struct fb_var_screeninfo *var, struct cfb_info *cfb,		       struct par_info *hw){	int err;	hw->width = var->xres_virtual;	hw->palette_ctrl = 0x06;	hw->vmode = var->vmode;	switch (var->bits_per_pixel) {#ifdef FBCON_HAS_CFB8	case 8:	/* PSEUDOCOLOUR, 256 */		hw->pixformat		= PIXFORMAT_8BPP;		hw->extseqmisc		= EXT_SEQ_MISC_8;		hw->pitch		= hw->width >> 3;		break;#endif#ifdef FBCON_HAS_CFB16	case 16:		hw->pixformat		= PIXFORMAT_16BPP;		hw->pitch		= hw->width >> 2;//		hw->palette_ctrl	|= 0x10;#ifndef CFB16_IS_CFB15		/* DIRECTCOLOUR, 64k */		if (var->green.length == 6) {			hw->extseqmisc		= EXT_SEQ_MISC_16_RGB565;			break;		}#endif		/* DIRECTCOLOUR, 32k */		hw->extseqmisc		= EXT_SEQ_MISC_16_RGB555;		break;#endif#ifdef FBCON_HAS_CFB24	case 24:/* TRUECOLOUR, 16m */		hw->pixformat		= PIXFORMAT_24BPP;		hw->extseqmisc		= EXT_SEQ_MISC_24_RGB888;		hw->width		*= 3;		hw->pitch		= hw->width >> 3;//		hw->palette_ctrl	|= 0x10;		break;#endif	default:		return -EINVAL;	}	err = cyber2000fb_decode_clock(hw, cfb, var);	if (err)		return err;	err = cyber2000fb_decode_crtc(hw, cfb, var);	if (err)		return err;	hw->width -= 1;	hw->fetch = hw->pitch;	if (!(cfb->mem_ctl2 & MEM_CTL2_64BIT))		hw->fetch <<= 1;	hw->fetch += 1;	return 0;}/* *    Set the User Defined Part of the Display */static intcyber2000fb_set_var(struct fb_var_screeninfo *var, int con,		    struct fb_info *info){	struct cfb_info *cfb = (struct cfb_info *)info;	struct display *display;	struct par_info hw;	int err, chgvar = 0;	/*	 * CONUPDATE and SMOOTH_XPAN are equal.  However,	 * SMOOTH_XPAN is only used internally by fbcon.	 */	if (var->vmode & FB_VMODE_CONUPDATE) {		var->vmode |= FB_VMODE_YWRAP;		var->xoffset = cfb->display->var.xoffset;		var->yoffset = cfb->display->var.yoffset;	}	err = cyber2000fb_decode_var(var, (struct cfb_info *)info, &hw);	if (err)		return err;	if (var->activate & FB_ACTIVATE_TEST)		return 0;	if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW)		return -EINVAL;	if (con < 0) {		display = cfb->fb.disp;		chgvar = 0;	} else {		display = fb_display + con;	}	if (display->var.xres != var->xres)		chgvar = 1;	if (display->var.yres != var->yres)		chgvar = 1;	if (display->var.xres_virtual != var->xres_virtual)		chgvar = 1;	if (display->var.yres_virtual != var->yres_virtual)		chgvar = 1;	if (display->var.bits_per_pixel != var->bits_per_pixel)		chgvar = 1;	if (con < 0)		chgvar = 0;	var->red.msb_right	= 0;	var->green.msb_right	= 0;	var->blue.msb_right	= 0;	switch (var->bits_per_pixel) {#ifdef FBCON_HAS_CFB8	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;		cfb->fb.fix.visual	= FB_VISUAL_PSEUDOCOLOR;		cfb->dispsw		= &fbcon_cfb8;		display->dispsw_data	= NULL;		display->next_line	= var->xres_virtual;		break;#endif#ifdef FBCON_HAS_CFB16	case 16:		var->bits_per_pixel	= 16;		var->red.length		= 5;		var->green.offset	= 5;		var->blue.offset	= 0;		var->blue.length	= 5;		cfb->fb.fix.visual	= FB_VISUAL_DIRECTCOLOR;		cfb->dispsw		= &fbcon_cfb16;		display->dispsw_data	= cfb->fb.pseudo_palette;		display->next_line	= var->xres_virtual * 2;#ifndef CFB16_IS_CFB15		/* DIRECTCOLOUR, 64k */		if (var->green.length == 6) {			var->red.offset		= 11;			var->green.length	= 6;			break;		}#endif		/* DIRECTCOLOUR, 32k */		var->red.offset		= 10;		var->green.length	= 5;		break;#endif#ifdef FBCON_HAS_CFB24	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;		cfb->fb.fix.visual	= FB_VISUAL_TRUECOLOR;		cfb->dispsw		= &fbcon_cfb24;		display->dispsw_data	= cfb->fb.pseudo_palette;		display->next_line	= var->xres_virtual * 3;		break;#endif	default:/* in theory this should never happen */		printk(KERN_WARNING "%s: no support for %dbpp\n",		       cfb->fb.fix.id, var->bits_per_pixel);		cfb->dispsw = &fbcon_dummy;		break;	}	if (var->accel_flags & FB_ACCELF_TEXT && cfb->dispsw != &fbcon_dummy)		display->dispsw = &fbcon_cyber_accel;	else		display->dispsw = cfb->dispsw;	cfb->fb.fix.line_length	= display->next_line;	display->screen_base	= cfb->fb.screen_base;	display->line_length	= cfb->fb.fix.line_length;	display->visual		= cfb->fb.fix.visual;	display->type		= cfb->fb.fix.type;	display->type_aux	= cfb->fb.fix.type_aux;	display->ypanstep	= cfb->fb.fix.ypanstep;	display->ywrapstep	= cfb->fb.fix.ywrapstep;	display->can_soft_blank = 1;	display->inverse	= 0;	display->var		= *var;	display->var.activate	&= ~FB_ACTIVATE_ALL;	cfb->fb.var = display->var;	/*	 * If we are setting all the virtual consoles, also set the	 * defaults used to create new consoles.	 */	if (var->activate & FB_ACTIVATE_ALL)		cfb->fb.disp->var = display->var;	if (chgvar && info && cfb->fb.changevar)		cfb->fb.changevar(con);	cyber2000fb_update_start(cfb, var);	cyber2000fb_set_timing(cfb, &hw);	fb_set_cmap(&cfb->fb.cmap, 1, cyber2000_setcolreg, &cfb->fb);	return 0;}/* *    Pan or Wrap the Display */static intcyber2000fb_pan_display(struct fb_var_screeninfo *var, int con,			struct fb_info *info){	struct cfb_info *cfb = (struct cfb_info *)info;	u_int y_bottom;	y_bottom = var->yoffset;	if (!(var->vmode & FB_VMODE_YWRAP))		y_bottom += var->yres;	if (var->xoffset > (var->xres_virtual - var->xres))		return -EINVAL;	if (y_bottom > cfb->display->var.yres_virtual)		return -EINVAL;	if (cyber2000fb_update_start(cfb, var))		return -EINVAL;	cfb->display->var.xoffset = var->xoffset;	cfb->display->var.yoffset = var->yoffset;	if (var->vmode & FB_VMODE_YWRAP) {		cfb->display->var.vmode |= FB_VMODE_YWRAP;	} else {		cfb->display->var.vmode &= ~FB_VMODE_YWRAP;	}	return 0;}/* *    Update the `var' structure (called by fbcon.c) * *    This call looks only at yoffset and the FB_VMODE_YWRAP flag in `var'. *    Since it's called by a kernel driver, no range checking is done. */static int cyber2000fb_updatevar(int con, struct fb_info *info){	struct cfb_info *cfb = (struct cfb_info *)info;	return cyber2000fb_update_start(cfb, &fb_display[con].var);}static int cyber2000fb_switch(int con, struct fb_info *info){	struct cfb_info *cfb = (struct cfb_info *)info;	struct display *display = cfb->display;	struct fb_cmap *cmap;	if (display) {		/*		 * Save the old colormap and video mode.		 */		if (display->cmap.len)			fb_copy_cmap(&cfb->fb.cmap, &display->cmap, 0);	}	cfb->display = display = fb_display + con;	/*	 * Install the new colormap and change the video mode.  By default,	 * fbcon sets all the colormaps and video modes to the default	 * values at bootup.	 *	 * Really, we want to set the colourmap size depending on the	 * depth of the new video mode.  For now, we leave it at its	 * default 256 entry.	 */	if (display->cmap.len)		cmap = &display->cmap;	else		cmap = fb_default_cmap(1 << display->var.bits_per_pixel);	fb_copy_cmap(cmap, &cfb->fb.cmap, 0);	display->var.activate = FB_ACTIVATE_NOW;	cyber2000fb_set_var(&display->var, con, &cfb->fb);	return 0;}/* *    (Un)Blank the display. */static void cyber2000fb_blank(int blank, struct fb_info *info){	struct cfb_info *cfb = (struct cfb_info *)info;	unsigned int sync = 0;	int i;	/*	 *  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	 */     	switch (blank) {	case 4:	/* powerdown - both sync lines down */		sync = EXT_SYNC_CTL_VS_0 | EXT_SYNC_CTL_HS_0;		break;		case 3:	/* hsync off */		sync = EXT_SYNC_CTL_VS_NORMAL | EXT_SYNC_CTL_HS_0;		break;		case 2:	/* vsync off */		sync = EXT_SYNC_CTL_VS_0 | EXT_SYNC_CTL_HS_NORMAL;		break;	case 1:	/* soft blank */		break;	default: /* unblank */		break;	}	cyber2000_grphw(EXT_SYNC_CTL, sync, cfb);	switch (blank) {	case 4:	case 3:	case 2:	case 1:	/* 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);		}		break;	default: /* 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);		}		break;	}}/* * Get the currently displayed virtual consoles colormap. */static intgen_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info){	fb_copy_cmap(&info->cmap, cmap, kspc ? 0 : 2);	return 0;}/* * Get the currently displayed virtual consoles fixed part of the display. */static intgen_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info){	*fix = info->fix;	return 0;}/* * Get the current user defined part of the display. */static intgen_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info){	*var = info->var;	return 0;}static struct fb_ops cyber2000fb_ops = {	owner:		THIS_MODULE,	fb_set_var:	cyber2000fb_set_var,	fb_set_cmap:	cyber2000fb_set_cmap,	fb_pan_display:	cyber2000fb_pan_display,	fb_get_fix:	gen_get_fix,	fb_get_var:	gen_get_var,	fb_get_cmap:	gen_get_cmap,};/* * 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) {

⌨️ 快捷键说明

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