📄 atyfb_base.c
字号:
} if (!info->fb_info.display_fg || info->fb_info.display_fg->vc_num == con) { atyfb_set_par(&par, info); atyfb_set_dispsw(display, info, par.crtc.bpp, accel); } if (oldbpp != var->bits_per_pixel) { if ((err = fb_alloc_cmap(&display->cmap, 0, 0))) return err; do_install_cmap(con, &info->fb_info); } } return 0;} /* * Pan or Wrap the Display * * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag */static int atyfb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info *fb){ struct fb_info_aty *info = (struct fb_info_aty *)fb; u32 xres, yres, xoffset, yoffset; struct atyfb_par *par = &info->current_par; xres = (((par->crtc.h_tot_disp>>16) & 0xff)+1)*8; yres = ((par->crtc.v_tot_disp>>16) & 0x7ff)+1; xoffset = (var->xoffset+7) & ~7; yoffset = var->yoffset; if (xoffset+xres > par->crtc.vxres || yoffset+yres > par->crtc.vyres) return -EINVAL; par->crtc.xoffset = xoffset; par->crtc.yoffset = yoffset; set_off_pitch(par, info); return 0;} /* * Get the Colormap */static int atyfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info){ if (!info->display_fg || con == info->display_fg->vc_num) /* current console? */ return fb_get_cmap(cmap, kspc, atyfb_getcolreg, info); else if (fb_display[con].cmap.len) /* non default colormap? */ fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2); else { int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256; fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2); } return 0;} /* * Set the Colormap */static int atyfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info){ int err; struct display *disp; if (con >= 0) disp = &fb_display[con]; else disp = info->disp; if (!disp->cmap.len) { /* no colormap allocated? */ int size = disp->var.bits_per_pixel == 16 ? 32 : 256; if ((err = fb_alloc_cmap(&disp->cmap, size, 0))) return err; } if (!info->display_fg || con == info->display_fg->vc_num) /* current console? */ return fb_set_cmap(cmap, kspc, atyfb_setcolreg, info); else fb_copy_cmap(cmap, &disp->cmap, kspc ? 0 : 1); return 0;}static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long arg, int con, struct fb_info *info2){#if defined(__sparc__) struct fb_info_aty *info = (struct fb_info_aty *)info2;#endif /* __sparc__ || DEBUG */#ifdef __sparc__ struct fbtype fbtyp; struct display *disp; if (con >= 0) disp = &fb_display[con]; else disp = info2->disp;#endif switch (cmd) {#ifdef __sparc__ case FBIOGTYPE: fbtyp.fb_type = FBTYPE_PCI_GENERIC; fbtyp.fb_width = info->current_par.crtc.vxres; fbtyp.fb_height = info->current_par.crtc.vyres; fbtyp.fb_depth = info->current_par.crtc.bpp; fbtyp.fb_cmsize = disp->cmap.len; fbtyp.fb_size = info->total_vram; if (copy_to_user((struct fbtype *)arg, &fbtyp, sizeof(fbtyp))) return -EFAULT; break;#endif /* __sparc__ */ 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -