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

📄 controlfb.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
 *//* A blank_mode of 1+VESA_NO_BLANKING or 1+VESA_POWERDOWN act alike... */	struct fb_info_control *p = (struct fb_info_control *) info;	int	ctrl;	if(blank_mode == 1+VESA_NO_BLANKING)		blank_mode = 1+VESA_POWERDOWN;	ctrl = ld_le32(&p->control_regs->ctrl.r) | 0x33;	if (blank_mode)		--blank_mode;	if (blank_mode & VESA_VSYNC_SUSPEND)		ctrl &= ~3;	if (blank_mode & VESA_HSYNC_SUSPEND)		ctrl &= ~0x30;	out_le32(&p->control_regs->ctrl.r, ctrl);/* TODO: Figure out how the heck to powerdown this thing! */    return;}static int controlfb_getcolreg(u_int regno, u_int *red, u_int *green,			     u_int *blue, u_int *transp, struct fb_info *info){	struct fb_info_control *p = (struct fb_info_control *) info;	if (regno > 255)		return 1;	*red = (p->palette[regno].red<<8) | p->palette[regno].red;	*green = (p->palette[regno].green<<8) | p->palette[regno].green;	*blue = (p->palette[regno].blue<<8) | p->palette[regno].blue;	*transp = 0;	return 0;}static int controlfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,			     u_int transp, struct fb_info *info){	struct fb_info_control *p = (struct fb_info_control *) info;	u_int i;	__u8 r, g, b;	if (regno > 255)		return 1;	r = red >> 8;	g = green >> 8;	b = blue >> 8;	p->palette[regno].red = r;	p->palette[regno].green = g;	p->palette[regno].blue = b;	out_8(&p->cmap_regs->addr, regno);	/* tell clut what addr to fill	*/	out_8(&p->cmap_regs->lut, r);		/* send one color channel at	*/	out_8(&p->cmap_regs->lut, g);		/* a time...			*/	out_8(&p->cmap_regs->lut, b);	if (regno < 16)		switch (p->par.cmode) {#ifdef FBCON_HAS_CFB16			case CMODE_16:				p->fbcon_cmap.cfb16[regno] = (regno << 10) | (regno << 5) | regno;				break;#endif#ifdef FBCON_HAS_CFB32			case CMODE_32:				i = (regno << 8) | regno;				p->fbcon_cmap.cfb32[regno] = (i << 16) | i;				break;#endif		}	return 0;}static void do_install_cmap(int con, struct fb_info *info){	if (con != currcon)		return;	if (fb_display[con].cmap.len)		fb_set_cmap(&fb_display[con].cmap, 1, controlfb_setcolreg,			    info);	else {		int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;		fb_set_cmap(fb_default_cmap(size), 1, controlfb_setcolreg,			    info);	}}static inline int control_vram_reqd(int video_mode, int color_mode){	return (control_reg_init[video_mode-1]->vres		* control_reg_init[video_mode-1]->hres << color_mode)	       + control_reg_init[video_mode-1]->offset[color_mode];}static void set_control_clock(unsigned char *params){	struct adb_request req;	int i;#ifdef CONFIG_ADB_CUDA	for (i = 0; i < 3; ++i) {		cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC,			     0x50, i + 1, params[i]);		while (!req.complete)			cuda_poll();	}#endif	}static void __init init_control(struct fb_info_control *p){	struct fb_par_control parstruct;	struct fb_par_control *par = &parstruct;	struct fb_var_screeninfo var;	p->sense = read_control_sense(p);	printk(KERN_INFO "Monitor sense value = 0x%x, ", p->sense);	/* Try to pick a video mode out of NVRAM if we have one. */	if (default_vmode == VMODE_NVRAM) {		par->vmode = nvram_read_byte(NV_VMODE);		if(par->vmode <= 0 || par->vmode > VMODE_MAX || !control_reg_init[par->vmode - 1])			par->vmode = VMODE_CHOOSE;		if(par->vmode == VMODE_CHOOSE)			par->vmode = mac_map_monitor_sense(p->sense);		if(!control_reg_init[par->vmode - 1])			par->vmode = VMODE_640_480_60;	} else		par->vmode=default_vmode;	if (default_cmode == CMODE_NVRAM){		par->cmode = nvram_read_byte(NV_CMODE);		if(par->cmode < CMODE_8 || par->cmode > CMODE_32)			par->cmode = CMODE_8;}	else		par->cmode=default_cmode;	/*	 * Reduce the pixel size if we don't have enough VRAM.	 */	while(par->cmode > CMODE_8 && control_vram_reqd(par->vmode, par->cmode) > p->total_vram)		par->cmode--;		printk("using video mode %d and color mode %d.\n", par->vmode, par->cmode);		par->vxres = par->xres = control_reg_init[par->vmode - 1]->hres;	par->yres = control_reg_init[par->vmode - 1]->vres;	par->vyres = p->total_vram / (par->vxres << par->cmode);	par->xoffset = par->yoffset = 0;		control_init_info(&p->info, p);		par_set = 1;	/* Debug */		control_par_to_var(par, &var);	var.activate = FB_ACTIVATE_NOW;	control_set_var(&var, -1, &p->info);		p->info.flags = FBINFO_FLAG_DEFAULT;	if (register_framebuffer(&p->info) < 0) {		kfree(p);		return;	}		printk(KERN_INFO "fb%d: control display adapter\n", GET_FB_IDX(p->info.node));	}#define STORE_D2(a,d) \	out_8(&p->cmap_regs->addr, (a)); \	out_8(&p->cmap_regs->d2,   (d))/* Now how about actually saying, Make it so! *//* Some things in here probably don't need to be done each time. */static void control_set_hardware(struct fb_info_control *p, struct fb_par_control *par){	struct control_regvals	*init;	volatile struct preg	*rp;	int			flags, ctrl, i;	int			vmode, cmode;		if(PAR_EQUAL(&p->par, par))		return;		p->par = *par;		vmode = p->par.vmode;	cmode = p->par.cmode;		init = control_reg_init[vmode - 1];		if (control_vram_reqd(vmode, cmode) > 0x200000)		flags = 0x51;	else if (p->control_use_bank2)		flags = 0x39;	else		flags = 0x31;	if (vmode >= VMODE_1280_960_75 && cmode >= CMODE_16)		ctrl = 0x7f;	else		ctrl = 0x3b;	/* Initialize display timing registers */	out_le32(&p->control_regs->ctrl.r, 0x43b);		set_control_clock(init->clock_params);		STORE_D2(0x20, init->radacal_ctrl[cmode]);	STORE_D2(0x21, p->control_use_bank2 ? 0 : 1);	STORE_D2(0x10, 0);	STORE_D2(0x11, 0);	rp = &p->control_regs->vswin;	for (i = 0; i < 16; ++i, ++rp)		out_le32(&rp->r, init->regs[i]);		out_le32(&p->control_regs->pitch.r, par->vxres << cmode);	out_le32(&p->control_regs->mode.r, init->mode[cmode]);	out_le32(&p->control_regs->flags.r, flags);	out_le32(&p->control_regs->start_addr.r,	    par->yoffset * (par->vxres << cmode));	out_le32(&p->control_regs->reg18.r, 0x1e5);	out_le32(&p->control_regs->reg19.r, 0);	for (i = 0; i < 16; ++i) {		controlfb_setcolreg(color_table[i], default_red[i]<<8,				    default_grn[i]<<8, default_blu[i]<<8,				    0, (struct fb_info *)p);	}/* Does the above need to be here each time? -- danj */	/* Turn on display */	out_le32(&p->control_regs->ctrl.r, ctrl);	#ifdef CONFIG_FB_COMPAT_XPMAC	/* And let the world know the truth. */	if (!console_fb_info || console_fb_info == &p->info) {		display_info.height = p->par.yres;		display_info.width = p->par.xres;		display_info.depth = (cmode == CMODE_32) ? 32 :			((cmode == CMODE_16) ? 16 : 8);		display_info.pitch = p->par.vxres << p->par.cmode;		display_info.mode = vmode;		strncpy(display_info.name, "control",			sizeof(display_info.name));		display_info.fb_address = p->frame_buffer_phys			 + control_reg_init[vmode-1]->offset[cmode];		display_info.cmap_adr_address = p->cmap_regs_phys;		display_info.cmap_data_address = p->cmap_regs_phys + 0x30;		display_info.disp_reg_address = p->control_regs_phys;		console_fb_info = &p->info;	}#endif /* CONFIG_FB_COMPAT_XPMAC */}int __init control_init(void){	struct device_node *dp;	dp = find_devices("control");	if (dp != 0)		control_of_init(dp);	return 0;}static void __init control_of_init(struct device_node *dp){	struct fb_info_control	*p;	unsigned long		addr, size;	int			i, bank1, bank2;	if(dp->n_addrs != 2) {		printk(KERN_ERR "expecting 2 address for control (got %d)", dp->n_addrs);		return;	}	p = kmalloc(sizeof(*p), GFP_ATOMIC);	if (p == 0)		return;	memset(p, 0, sizeof(*p));	/* Map in frame buffer and registers */	for (i = 0; i < dp->n_addrs; ++i) {		addr = dp->addrs[i].address;		size = dp->addrs[i].size;		/* Let's assume we can request either all or nothing */		if (!request_mem_region(addr, size, "controlfb")) {		    kfree(p);		    return;		}		if (size >= 0x800000) {			/* use the big-endian aperture (??) */			addr += 0x800000;			/* map at most 8MB for the frame buffer */			p->frame_buffer_phys = addr;			p->frame_buffer = __ioremap(addr, 0x800000, _PAGE_WRITETHRU);		} else {			p->control_regs_phys = addr;			p->control_regs = ioremap(addr, size);		}	}	p->cmap_regs_phys = 0xf301b000;	 /* XXX not in prom? */	request_mem_region(p->cmap_regs_phys, 0x1000, "controlfb cmap");	p->cmap_regs = ioremap(p->cmap_regs_phys, 0x1000);	/* Work out which banks of VRAM we have installed. */	/* According to Andrew Fyfe <bandr@best.com>, the VRAM behaves like so: */	/* afyfe: observations from an 8500:	 * - with 2M vram in bank 1, it appears at offsets 0, 2M and 4M	 * - with 2M vram in bank 2, it appears only at offset 6M	 * - with 4M vram, it appears only as a 4M block at offset 0.	 */	/* We know there is something at 2M if there is something at 0M. */	out_8(&p->frame_buffer[0x200000], 0xa5);	out_8(&p->frame_buffer[0x200001], 0x38);	asm volatile("eieio; dcbi 0,%0" : : "r" (&p->frame_buffer[0x200000]) : "memory" );	out_8(&p->frame_buffer[0], 0x5a);	out_8(&p->frame_buffer[1], 0xc7);	asm volatile("eieio; dcbi 0,%0" : : "r" (&p->frame_buffer[0]) : "memory" );	bank1 =  (in_8(&p->frame_buffer[0x000000]) == 0x5a)		&& (in_8(&p->frame_buffer[0x000001]) == 0xc7);	bank2 =  (in_8(&p->frame_buffer[0x200000]) == 0xa5)		&& (in_8(&p->frame_buffer[0x200001]) == 0x38);	if(bank2 && !bank1)		printk(KERN_INFO "controlfb: Found memory at 2MB but not at 0!  Please contact dan@debian.org\n");	if(!bank1) {		out_8(&p->frame_buffer[0x600000], 0xa5);		out_8(&p->frame_buffer[0x600001], 0x38);		asm volatile("eieio; dcbi 0,%0" : : "r" (&p->frame_buffer[0x600000]) : "memory" );		bank2 = (in_8(&p->frame_buffer[0x600000]) == 0xa5)			&& (in_8(&p->frame_buffer[0x600001]) == 0x38);		/* If we don't have bank 1 installed, we hope we have bank 2 :-) */		p->control_use_bank2 = 1;		p->frame_buffer += 0x600000;		p->frame_buffer_phys += 0x600000;	}		p->total_vram = (bank1 + bank2) * 0x200000;		printk(KERN_INFO "controlfb: Memory bank 1 %s, bank 2 %s, total VRAM %dMB\n",		bank1 ? "present" : "absent", bank2 ? "present" : "absent",		2 * (bank1 + bank2));	init_control(p);}/* * Get the monitor sense value. * Note that this can be called before calibrate_delay, * so we can't use udelay. */static int read_control_sense(struct fb_info_control *p){	int sense;	out_le32(&p->control_regs->mon_sense.r, 7);	/* drive all lines high */	__delay(200);	out_le32(&p->control_regs->mon_sense.r, 077);	/* turn off drivers */	__delay(2000);	sense = (in_le32(&p->control_regs->mon_sense.r) & 0x1c0) << 2;	/* drive each sense line low in turn and collect the other 2 */	out_le32(&p->control_regs->mon_sense.r, 033);	/* drive A low */	__delay(2000);	sense |= (in_le32(&p->control_regs->mon_sense.r) & 0xc0) >> 2;	out_le32(&p->control_regs->mon_sense.r, 055);	/* drive B low */	__delay(2000);	sense |= ((in_le32(&p->control_regs->mon_sense.r) & 0x100) >> 5)		| ((in_le32(&p->control_regs->mon_sense.r) & 0x40) >> 4);	out_le32(&p->control_regs->mon_sense.r, 066);	/* drive C low */	__delay(2000);	sense |= (in_le32(&p->control_regs->mon_sense.r) & 0x180) >> 7;	out_le32(&p->control_regs->mon_sense.r, 077);	/* turn off drivers */		return sense;}/***********************  Various translation functions  ***********************/#if 1/* This routine takes a user-supplied var, and picks the best vmode/cmode from it. */static int control_var_to_par(struct fb_var_screeninfo *var,	struct fb_par_control *par, const struct fb_info *fb_info){	int xres = var->xres;	int yres = var->yres;	int bpp = var->bits_per_pixel;	struct fb_info_control *p = (struct fb_info_control *) fb_info;    /*     *  Get the video params out of 'var'. If a value doesn't fit, round it up,     *  if it's too big, return -EINVAL.     *     *  Suggestion: Round up in the following order: bits_per_pixel, xres,     *  yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale,     *  bitfields, horizontal timing, vertical timing.     */	/* swiped by jonh from atyfb.c */	if (xres <= 640 && yres <= 480)		par->vmode = VMODE_640_480_67;		/* 640x480, 67Hz */	else if (xres <= 640 && yres <= 870)		par->vmode = VMODE_640_870_75P;		/* 640x870, 75Hz (portrait) */	else if (xres <= 800 && yres <= 600)		par->vmode = VMODE_800_600_75;		/* 800x600, 75Hz */	else if (xres <= 832 && yres <= 624)		par->vmode = VMODE_832_624_75;		/* 832x624, 75Hz */	else if (xres <= 1024 && yres <= 768)		par->vmode = VMODE_1024_768_75;		/* 1024x768, 75Hz */	else if (xres <= 1152 && yres <= 870)		par->vmode = VMODE_1152_870_75;		/* 1152x870, 75Hz */	else if (xres <= 1280 && yres <= 960)		par->vmode = VMODE_1280_960_75;		/* 1280x960, 75Hz */	else if (xres <= 1280 && yres <= 1024)		par->vmode = VMODE_1280_1024_75;	/* 1280x1024, 75Hz */	else {		printk(KERN_ERR "Bad x/y res in var_to_par\n");		return -EINVAL;	}	xres = control_reg_init[par->vmode-1]->hres;

⌨️ 快捷键说明

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