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

📄 controlfb.c

📁 S3C44B0X下的LCD (framebuffer)驱动资料与相关代码
💻 C
📖 第 1 页 / 共 3 页
字号:
}static void controlfb_blank(int blank_mode, struct fb_info *info){	struct fb_info_control *p = (struct fb_info_control *) info;	unsigned ctrl;	ctrl = ld_le32(CNTRL_REG(p,ctrl));	if (blank_mode > 0)		switch (blank_mode - 1) {		case VESA_VSYNC_SUSPEND:			ctrl &= ~3;			break;		case VESA_HSYNC_SUSPEND:			ctrl &= ~0x30;			break;		case VESA_POWERDOWN:			ctrl &= ~0x33;			/* fall through */		case VESA_NO_BLANKING:			ctrl |= 0x400;			break;		default:			break;		}	else {		ctrl &= ~0x400;		ctrl |= 0x33;	}	out_le32(CNTRL_REG(p,ctrl), ctrl);	return;}/* * low level cmap set/get ops */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(struct display *disp, struct fb_info *info){	if (disp->cmap.len)		fb_set_cmap(&disp->cmap, 1, controlfb_setcolreg,			    info);	else {		int size = disp->var.bits_per_pixel == 16 ? 32 : 256;		fb_set_cmap(fb_default_cmap(size), 1, controlfb_setcolreg,			    info);	}}static void set_control_clock(unsigned char *params){#ifdef CONFIG_ADB_CUDA	struct adb_request req;	int i;	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	}/* * finish off the driver initialization and register */static int __init init_control(struct fb_info_control *p){	int full, sense, vmode, cmode, vyres;	struct fb_var_screeninfo var;	printk(KERN_INFO "controlfb: ");	full = p->total_vram == 0x400000;#ifdef CONFIG_NVRAM	/* Try to pick a video mode out of NVRAM if we have one. */	if (default_cmode == CMODE_NVRAM)		cmode = nvram_read_byte(NV_CMODE);	if (default_vmode == VMODE_NVRAM) {		vmode = nvram_read_byte(NV_VMODE);		if (vmode < 1 || vmode > VMODE_MAX ||		    control_mac_modes[vmode - 1].m[full] < cmode) {			sense = read_control_sense(p);			printk("Monitor sense value = 0x%x, ", sense);			vmode = mac_map_monitor_sense(sense);			if (control_mac_modes[vmode - 1].m[full] < cmode)				vmode = VMODE_640_480_60;		}	}#endif	/* If we didn't get something from NVRAM, pick a	 * sane default.	 */	if (vmode <= 0 || vmode > VMODE_MAX)		vmode = VMODE_640_480_67;	if (cmode < CMODE_8 || cmode > CMODE_32)		cmode = CMODE_8;	if (mac_vmode_to_var(vmode, cmode, &var) < 0) {		/* This shouldn't happen! */		printk("mac_vmode_to_var(%d, %d,) failed\n", vmode, cmode);try_again:		vmode = VMODE_640_480_60;		cmode = CMODE_8;		if (mac_vmode_to_var(vmode, cmode, &var) < 0) {			printk(KERN_ERR "controlfb: mac_vmode_to_var() failed\n");			return -ENXIO;		}		printk(KERN_INFO "controlfb: ");	}	printk("using video mode %d and color mode %d.\n", vmode, cmode);	vyres = (p->total_vram - CTRLFB_OFF) / (var.xres << cmode);	if (vyres > var.yres)		var.yres_virtual = vyres;	control_init_info(&p->info, p);	currcon = -1;	var.activate = FB_ACTIVATE_NOW;	if (control_set_var(&var, -1, &p->info) < 0) {		if (vmode != VMODE_640_480_60 || cmode != CMODE_8)			goto try_again;		printk(KERN_ERR "controlfb: initilization failed\n");		return -ENXIO;	}	p->info.flags = FBINFO_FLAG_DEFAULT;	if (register_framebuffer(&p->info) < 0)		return -ENXIO;		printk(KERN_INFO "fb%d: control display adapter\n", GET_FB_IDX(p->info.node));		return 0;}#define RADACAL_WRITE(a,d) \	out_8(&p->cmap_regs->addr, (a)); \	out_8(&p->cmap_regs->dat,   (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	*r;	volatile struct preg	*rp;	int			i, cmode;	if (PAR_EQUAL(&p->par, par)) {		/*		 * check if only xoffset or yoffset differs.		 * this prevents flickers in typical VT switch case.		 */		if (p->par.xoffset != par->xoffset ||		    p->par.yoffset != par->yoffset)			set_screen_start(par->xoffset, par->yoffset, p);					return;	}		p->par = *par;	cmode = p->par.cmode;	r = &par->regvals;		/* Turn off display */	out_le32(CNTRL_REG(p,ctrl), 0x400 | par->ctrl);		set_control_clock(r->clock_params);		RADACAL_WRITE(0x20, r->radacal_ctrl);	RADACAL_WRITE(0x21, p->control_use_bank2 ? 0 : 1);	RADACAL_WRITE(0x10, 0);	RADACAL_WRITE(0x11, 0);	rp = &p->control_regs->vswin;	for (i = 0; i < 16; ++i, ++rp)		out_le32(&rp->r, r->regs[i]);		out_le32(CNTRL_REG(p,pitch), par->pitch);	out_le32(CNTRL_REG(p,mode), r->mode);	out_le32(CNTRL_REG(p,vram_attr), p->vram_attr);	out_le32(CNTRL_REG(p,start_addr), par->yoffset * par->pitch		 + (par->xoffset << cmode));	out_le32(CNTRL_REG(p,rfrcnt), 0x1e5);	out_le32(CNTRL_REG(p,intr_ena), 0);	/* Turn on display */	out_le32(CNTRL_REG(p,ctrl), par->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.pitch;		display_info.mode = p->par.vmode;		strncpy(display_info.name, "control",			sizeof(display_info.name));		display_info.fb_address = p->frame_buffer_phys + CTRLFB_OFF;		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 */#ifdef CONFIG_BOOTX_TEXT	btext_update_display(p->frame_buffer_phys + CTRLFB_OFF,			     p->par.xres, p->par.yres,			     (cmode == CMODE_32? 32: cmode == CMODE_16? 16: 8),			     p->par.pitch);#endif /* CONFIG_BOOTX_TEXT */}/* * Called from fbmem.c for probing & intializing */int __init control_init(void){	struct device_node *dp;	dp = find_devices("control");	if (dp != 0 && !control_of_init(dp))		return 0;	return -ENXIO;}/* Work out which banks of VRAM we have installed. *//* danj: I guess the card just ignores writes to nonexistant VRAM... */static void __init find_vram_size(struct fb_info_control *p){	int bank1, bank2;	/*	 * Set VRAM in 2MB (bank 1) mode	 * VRAM Bank 2 will be accessible through offset 0x600000 if present	 * and VRAM Bank 1 will not respond at that offset even if present	 */	out_le32(CNTRL_REG(p,vram_attr), 0x31);	out_8(&p->frame_buffer[0x600000], 0xb3);	out_8(&p->frame_buffer[0x600001], 0x71);	asm volatile("eieio; dcbf 0,%0" : : "r" (&p->frame_buffer[0x600000])					: "memory" );	mb();	asm volatile("eieio; dcbi 0,%0" : : "r" (&p->frame_buffer[0x600000])					: "memory" );	mb();	bank2 = (in_8(&p->frame_buffer[0x600000]) == 0xb3)		&& (in_8(&p->frame_buffer[0x600001]) == 0x71);	/*	 * Set VRAM in 2MB (bank 2) mode	 * VRAM Bank 1 will be accessible through offset 0x000000 if present	 * and VRAM Bank 2 will not respond at that offset even if present	 */	out_le32(CNTRL_REG(p,vram_attr), 0x39);	out_8(&p->frame_buffer[0], 0x5a);	out_8(&p->frame_buffer[1], 0xc7);	asm volatile("eieio; dcbf 0,%0" : : "r" (&p->frame_buffer[0])					: "memory" );	mb();	asm volatile("eieio; dcbi 0,%0" : : "r" (&p->frame_buffer[0])					: "memory" );	mb();	bank1 = (in_8(&p->frame_buffer[0]) == 0x5a)		&& (in_8(&p->frame_buffer[1]) == 0xc7);	if (bank2) {		if (!bank1) {			/*			 * vram bank 2 only			 */			p->control_use_bank2 = 1;			p->vram_attr = 0x39;			p->frame_buffer += 0x600000;			p->frame_buffer_phys += 0x600000;		} else {			/*			 * 4 MB vram			 */			p->vram_attr = 0x51;		}	} else {		/*		 * vram bank 1 only		 */		p->vram_attr = 0x31;	}        p->total_vram = (bank1 + bank2) * 0x200000;	printk(KERN_INFO "controlfb: VRAM Total = %dMB "			"(%dMB @ bank 1, %dMB @ bank 2)\n",			(bank1 + bank2) << 1, bank1 << 1, bank2 << 1);}/* * find "control" and initialize */static int __init control_of_init(struct device_node *dp){	struct fb_info_control	*p;	unsigned long		addr;	int			i;	if (control_fb) {		printk(KERN_ERR "controlfb: only one control is supported\n");		return -ENXIO;	}	if(dp->n_addrs != 2) {		printk(KERN_ERR "expecting 2 address for control (got %d)", dp->n_addrs);		return -ENXIO;	}	p = kmalloc(sizeof(*p), GFP_ATOMIC);	if (p == 0)		return -ENXIO;	control_fb = p;	/* save it for cleanups */	memset(p, 0, sizeof(*p));	/* Map in frame buffer and registers */	for (i = 0; i < dp->n_addrs; ++i) {		addr = dp->addrs[i].address;		if (dp->addrs[i].size >= 0x800000) {			p->fb_orig_base = addr;			p->fb_orig_size = dp->addrs[i].size;			/* use the big-endian aperture (??) */			p->frame_buffer_phys = addr + 0x800000;		} else {			p->control_regs_phys = addr;			p->control_regs_size = dp->addrs[i].size;		}	}	if (!p->fb_orig_base ||	    !request_mem_region(p->fb_orig_base,p->fb_orig_size,"controlfb")) {		p->fb_orig_base = 0;		goto error_out;	}	/* map at most 8MB for the frame buffer */	p->frame_buffer = __ioremap(p->frame_buffer_phys, 0x800000,				    _PAGE_WRITETHRU);	if (!p->control_regs_phys ||	    !request_mem_region(p->control_regs_phys, p->control_regs_size,	    "controlfb regs")) {		p->control_regs_phys = 0;		goto error_out;	}	p->control_regs = ioremap(p->control_regs_phys, p->control_regs_size);	p->cmap_regs_phys = 0xf301b000;	 /* XXX not in prom? */	if (!request_mem_region(p->cmap_regs_phys, 0x1000, "controlfb cmap")) {		p->cmap_regs_phys = 0;		goto error_out;	}	p->cmap_regs = ioremap(p->cmap_regs_phys, 0x1000);	if (!p->cmap_regs || !p->control_regs || !p->frame_buffer)		goto error_out;	find_vram_size(p);	if (!p->total_vram)		goto error_out;	if (init_control(p) < 0)		goto error_out;	return 0;error_out:	control_cleanup();	return -ENXIO;}/* * 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(CNTRL_REG(p,mon_sense), 7);	/* drive all lines high */	__delay(200);	out_le32(CNTRL_REG(p,mon_sense), 077);	/* turn off drivers */	__delay(2000);	sense = (in_le32(CNTRL_REG(p,mon_sense)) & 0x1c0) << 2;	/* drive each sense line low in turn and collect the other 2 */	out_le32(CNTRL_REG(p,mon_sense), 033);	/* drive A low */	__delay(2000);	sense |= (in_le32(CNTRL_REG(p,mon_sense)) & 0xc0) >> 2;	out_le32(CNTRL_REG(p,mon_sense), 055);	/* drive B low */	__delay(2000);	sense |= ((in_le32(CNTRL_REG(p,mon_sense)) & 0x100) >> 5)		| ((in_le32(CNTRL_REG(p,mon_sense)) & 0x40) >> 4);	out_le32(CNTRL_REG(p,mon_sense), 066);	/* drive C low */	__delay(2000);	sense |= (in_le32(CNTRL_REG(p,mon_sense)) & 0x180) >> 7;	out_le32(CNTRL_REG(p,mon_sense), 077);	/* turn off drivers */		return sense;}/**********************  Various translation functions  **********************/#define CONTROL_PIXCLOCK_BASE	256016#define CONTROL_PIXCLOCK_MIN	5000	/* ~ 200 MHz dot clock *//* * calculate the clock paramaters to be sent to CUDA according to given * pixclock in pico second. */static int calc_clock_params(unsigned long clk, unsigned char *param)

⌨️ 快捷键说明

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