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

📄 atyfb_base.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 5 页
字号:
	break;    case ATYIO_FEATR:	if (get_user(info->features, (u32 *)arg))	    return -EFAULT;	break;    case ATYIO_FEATW:	if (put_user(info->features, (u32 *)arg))	    return -EFAULT;	break;#endif /* DEBUG && CONFIG_FB_ATY_CT */    default:	return -EINVAL;    }    return 0;}static int atyfb_rasterimg(struct fb_info *info, int start){    struct fb_info_aty *fb = (struct fb_info_aty *)info;    if (fb->blitter_may_be_busy)	wait_for_idle(fb);    return 0;}#ifdef __sparc__static int atyfb_mmap(struct fb_info *info, struct file *file,		      struct vm_area_struct *vma){	struct fb_info_aty *fb = (struct fb_info_aty *)info;	unsigned int size, page, map_size = 0;	unsigned long map_offset = 0;	unsigned long off;	int i;	if (!fb->mmap_map)		return -ENXIO;	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))		return -EINVAL;	off = vma->vm_pgoff << PAGE_SHIFT;	size = vma->vm_end - vma->vm_start;	/* To stop the swapper from even considering these pages. */	vma->vm_flags |= (VM_SHM | VM_LOCKED);	if (((vma->vm_pgoff == 0) && (size == fb->total_vram)) ||	    ((off == fb->total_vram) && (size == PAGE_SIZE)))		off += 0x8000000000000000UL;	vma->vm_pgoff = off >> PAGE_SHIFT;	/* propagate off changes */	/* Each page, see which map applies */	for (page = 0; page < size; ) {		map_size = 0;		for (i = 0; fb->mmap_map[i].size; i++) {			unsigned long start = fb->mmap_map[i].voff;			unsigned long end = start + fb->mmap_map[i].size;			unsigned long offset = off + page;			if (start > offset)				continue;			if (offset >= end)				continue;			map_size = fb->mmap_map[i].size - (offset - start);			map_offset = fb->mmap_map[i].poff + (offset - start);			break;		}		if (!map_size) {			page += PAGE_SIZE;			continue;		}		if (page + map_size > size)			map_size = size - page;		pgprot_val(vma->vm_page_prot) &= ~(fb->mmap_map[i].prot_mask);		pgprot_val(vma->vm_page_prot) |= fb->mmap_map[i].prot_flag;		if (remap_page_range(vma->vm_start + page, map_offset,				     map_size, vma->vm_page_prot))			return -EAGAIN;		page += map_size;	}	if (!map_size)		return -EINVAL;	vma->vm_flags |= VM_IO;	if (!fb->mmaped) {		int lastconsole = 0;		if (info->display_fg)			lastconsole = info->display_fg->vc_num;		fb->mmaped = 1;		if (fb->consolecnt && fb_display[lastconsole].fb_info == info) {			fb->vtconsole = lastconsole;			vt_cons[lastconsole]->vc_mode = KD_GRAPHICS;		}	}	return 0;}static struct {	u32	yoffset;	u8	r[2][256];	u8	g[2][256];	u8	b[2][256];} atyfb_save;static void atyfb_save_palette(struct fb_info *fb, int enter){	struct fb_info_aty *info = (struct fb_info_aty *)fb;	int i, tmp;	for (i = 0; i < 256; i++) {		tmp = aty_ld_8(DAC_CNTL, info) & 0xfc;		if (M64_HAS(EXTRA_BRIGHT))			tmp |= 0x2;		aty_st_8(DAC_CNTL, tmp, info);		aty_st_8(DAC_MASK, 0xff, info);		writeb(i, &info->aty_cmap_regs->rindex);		atyfb_save.r[enter][i] = readb(&info->aty_cmap_regs->lut);		atyfb_save.g[enter][i] = readb(&info->aty_cmap_regs->lut);		atyfb_save.b[enter][i] = readb(&info->aty_cmap_regs->lut);		writeb(i, &info->aty_cmap_regs->windex);		writeb(atyfb_save.r[1-enter][i], &info->aty_cmap_regs->lut);		writeb(atyfb_save.g[1-enter][i], &info->aty_cmap_regs->lut);		writeb(atyfb_save.b[1-enter][i], &info->aty_cmap_regs->lut);	}}static void atyfb_palette(int enter){	struct fb_info_aty *info;	struct atyfb_par *par;	struct display *d;	int i;	for (i = 0; i < MAX_NR_CONSOLES; i++) {		d = &fb_display[i];		if (d->fb_info &&		    d->fb_info->fbops == &atyfb_ops &&		    d->fb_info->display_fg &&		    d->fb_info->display_fg->vc_num == i) {			atyfb_save_palette(d->fb_info, enter);			info = (struct fb_info_aty *)d->fb_info;			par = &info->current_par;			if (enter) {				atyfb_save.yoffset = par->crtc.yoffset;				par->crtc.yoffset = 0;				set_off_pitch(par, info);			} else {				par->crtc.yoffset = atyfb_save.yoffset;				set_off_pitch(par, info);			}			break;		}	}}#endif /* __sparc__ */#ifdef CONFIG_PMAC_PBOOKstatic struct fb_info_aty* first_display = NULL;/* Power management routines. Those are used for PowerBook sleep. * * It appears that Rage LT and Rage LT Pro have different power * management registers. There's is some confusion about which * chipID is a Rage LT or LT pro :( */static int aty_power_mgmt_LT(int sleep, struct fb_info_aty *info){ 	unsigned int pm;	int timeout;		pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);	pm = (pm & ~PWR_MGT_MODE_MASK) | PWR_MGT_MODE_REG;	aty_st_le32(POWER_MANAGEMENT_LG, pm, info);	pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);		timeout = 200000;	if (sleep) {		/* Sleep */		pm &= ~PWR_MGT_ON;		aty_st_le32(POWER_MANAGEMENT_LG, pm, info);		pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);		udelay(10);		pm &= ~(PWR_BLON | AUTO_PWR_UP);		pm |= SUSPEND_NOW;		aty_st_le32(POWER_MANAGEMENT_LG, pm, info);		pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);		udelay(10);		pm |= PWR_MGT_ON;		aty_st_le32(POWER_MANAGEMENT_LG, pm, info);		do {			pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);			udelay(10);			if ((--timeout) == 0)				break;		} while ((pm & PWR_MGT_STATUS_MASK) != PWR_MGT_STATUS_SUSPEND);	} else {		/* Wakeup */		pm &= ~PWR_MGT_ON;		aty_st_le32(POWER_MANAGEMENT_LG, pm, info);		pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);		udelay(10);		pm |=  (PWR_BLON | AUTO_PWR_UP);		pm &= ~SUSPEND_NOW;		aty_st_le32(POWER_MANAGEMENT_LG, pm, info);		pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);		udelay(10);		pm |= PWR_MGT_ON;		aty_st_le32(POWER_MANAGEMENT_LG, pm, info);		do {			pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);			udelay(10);			if ((--timeout) == 0)				break;		} while ((pm & PWR_MGT_STATUS_MASK) != 0);	}	mdelay(500);	return timeout ? PBOOK_SLEEP_OK : PBOOK_SLEEP_REFUSE;}static int aty_power_mgmt_LTPro(int sleep, struct fb_info_aty *info){ 	unsigned int pm;	int timeout;		pm = aty_ld_lcd(POWER_MANAGEMENT, info);	pm = (pm & ~PWR_MGT_MODE_MASK) | PWR_MGT_MODE_REG;	aty_st_lcd(POWER_MANAGEMENT, pm, info);	pm = aty_ld_lcd(POWER_MANAGEMENT, info);	timeout = 200;	if (sleep) {		/* Sleep */		pm &= ~PWR_MGT_ON;		aty_st_lcd(POWER_MANAGEMENT, pm, info);		pm = aty_ld_lcd(POWER_MANAGEMENT, info);		udelay(10);		pm &= ~(PWR_BLON | AUTO_PWR_UP);		pm |= SUSPEND_NOW;		aty_st_lcd(POWER_MANAGEMENT, pm, info);		pm = aty_ld_lcd(POWER_MANAGEMENT, info);		udelay(10);		pm |= PWR_MGT_ON;		aty_st_lcd(POWER_MANAGEMENT, pm, info);		do {			pm = aty_ld_lcd(POWER_MANAGEMENT, info);			mdelay(1);			if ((--timeout) == 0)				break;		} while ((pm & PWR_MGT_STATUS_MASK) != PWR_MGT_STATUS_SUSPEND);	} else {		/* Wakeup */		pm &= ~PWR_MGT_ON;		aty_st_lcd(POWER_MANAGEMENT, pm, info);		pm = aty_ld_lcd(POWER_MANAGEMENT, info);		udelay(10);		pm &= ~SUSPEND_NOW;		pm |= (PWR_BLON | AUTO_PWR_UP);		aty_st_lcd(POWER_MANAGEMENT, pm, info);		pm = aty_ld_lcd(POWER_MANAGEMENT, info);		udelay(10);		pm |= PWR_MGT_ON;		aty_st_lcd(POWER_MANAGEMENT, pm, info);		do {			pm = aty_ld_lcd(POWER_MANAGEMENT, info);						mdelay(1);			if ((--timeout) == 0)				break;		} while ((pm & PWR_MGT_STATUS_MASK) != 0);	}	return timeout ? PBOOK_SLEEP_OK : PBOOK_SLEEP_REFUSE;}static int aty_power_mgmt(int sleep, struct fb_info_aty *info){    return M64_HAS(LT_SLEEP) ? aty_power_mgmt_LT(sleep, info)			     : aty_power_mgmt_LTPro(sleep, info);}/* * Save the contents of the frame buffer when we go to sleep, * and restore it when we wake up again. */static int aty_sleep_notify(struct pmu_sleep_notifier *self, int when){	struct fb_info_aty *info; 	int result;	result = PBOOK_SLEEP_OK;	for (info = first_display; info != NULL; info = info->next) {		struct fb_fix_screeninfo fix;		int nb;		atyfb_get_fix(&fix, fg_console, (struct fb_info *)info);		nb = fb_display[fg_console].var.yres * fix.line_length;		switch (when) {		case PBOOK_SLEEP_REQUEST:			info->save_framebuffer = vmalloc(nb);			if (info->save_framebuffer == NULL)				return PBOOK_SLEEP_REFUSE;			break;		case PBOOK_SLEEP_REJECT:			if (info->save_framebuffer) {				vfree(info->save_framebuffer);				info->save_framebuffer = 0;			}			break;		case PBOOK_SLEEP_NOW:			if (currcon >= 0)				fb_display[currcon].dispsw = &fbcon_dummy;			if (info->blitter_may_be_busy)				wait_for_idle(info);			/* Stop accel engine (stop bus mastering) */			if (info->current_par.accel_flags & FB_ACCELF_TEXT)				aty_reset_engine(info);			/* Backup fb content */				if (info->save_framebuffer)				memcpy_fromio(info->save_framebuffer,				       (void *)info->frame_buffer, nb);			/* Blank display and LCD */			atyfbcon_blank(VESA_POWERDOWN+1, (struct fb_info *)info);			/* Set chip to "suspend" mode */			result = aty_power_mgmt(1, info);			break;		case PBOOK_WAKE:			/* Wakeup chip */			result = aty_power_mgmt(0, info);			/* Restore fb content */						if (info->save_framebuffer) {				memcpy_toio((void *)info->frame_buffer,				       info->save_framebuffer, nb);				vfree(info->save_framebuffer);				info->save_framebuffer = 0;			}			/* Restore display */			if (currcon >= 0) {				atyfb_set_dispsw(&fb_display[currcon],					info, info->current_par.crtc.bpp,					info->current_par.accel_flags & FB_ACCELF_TEXT);			}			atyfbcon_blank(0, (struct fb_info *)info);			break;		}	}	return result;}static struct pmu_sleep_notifier aty_sleep_notifier = {        aty_sleep_notify, SLEEP_LEVEL_VIDEO,};#endif /* CONFIG_PMAC_PBOOK */#ifdef CONFIG_PMAC_BACKLIGHT    /*     *   LCD backlight control     */static int backlight_conv[] = {	0x00, 0x3f, 0x4c, 0x59, 0x66, 0x73, 0x80, 0x8d,	0x9a, 0xa7, 0xb4, 0xc1, 0xcf, 0xdc, 0xe9, 0xff};static intaty_set_backlight_enable(int on, int level, void* data){	struct fb_info_aty *info = (struct fb_info_aty *)data;	unsigned int reg = aty_ld_lcd(LCD_MISC_CNTL, info);		reg |= (BLMOD_EN | BIASMOD_EN);	if (on && level > BACKLIGHT_OFF) {		reg &= ~BIAS_MOD_LEVEL_MASK;		reg |= (backlight_conv[level] << BIAS_MOD_LEVEL_SHIFT);	} else {		reg &= ~BIAS_MOD_LEVEL_MASK;		reg |= (backlight_conv[0] << BIAS_MOD_LEVEL_SHIFT);	}	aty_st_lcd(LCD_MISC_CNTL, reg, info);	return 0;}static intaty_set_backlight_level(int level, void* data){	return aty_set_backlight_enable(1, level, data);}static struct backlight_controller aty_backlight_controller = {	aty_set_backlight_enable,	aty_set_backlight_level};#endif /* CONFIG_PMAC_BACKLIGHT */    /*     *  Initialisation     */static struct fb_info_aty *fb_list = NULL;static int __init aty_init(struct fb_info_aty *info, const char *name){    u32 chip_id;    u32 i;    int j, k;    struct fb_var_screeninfo var;    struct display *disp;    u16 type;    u8 rev;    const char *chipname = NULL, *ramname = NULL, *xtal;    int pll, mclk, gtb_memsize;#if defined(CONFIG_PPC)    int sense;#endif    u8 pll_ref_div;    info->aty_cmap_regs = (struct aty_cmap_regs *)(info->ati_regbase+0xc0);    chip_id = aty_ld_le32(CONFIG_CHIP_ID, info);    type = chip_id & CFG_CHIP_TYPE;    rev = (chip_id & CFG_CHIP_REV)>>24;    for (j = 0; j < (sizeof(aty_chips)/sizeof(*aty_chips)); j++)	if (type == aty_chips[j].chip_type &&	    (rev & aty_chips[j].rev_mask) == aty_chips[j].rev_val) {	    chipname = aty_chips[j].name;

⌨️ 快捷键说明

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