📄 fbdev.c
字号:
for (i = 0; i < NUM_ATC_REGS; i++) regs->attr[i] = ATTRin(par, i); for (i = 0; i < NUM_GRC_REGS; i++) regs->gra[i] = GRAin(par, i); for (i = 0; i < NUM_SEQ_REGS; i++) regs->seq[i] = SEQin(par, i); NVTRACE_LEAVE();}/** * riva_load_state - loads current chip state * @par: pointer to riva_par object containing info for current riva board * @regs: pointer to riva_regs object * * DESCRIPTION: * Loads chip state from @regs. * * CALLED FROM: * riva_load_video_mode() * rivafb_probe() * rivafb_remove() *//* from GGI */static void riva_load_state(struct riva_par *par, struct riva_regs *regs){ RIVA_HW_STATE *state = ®s->ext; int i; NVTRACE_ENTER(); CRTCout(par, 0x11, 0x00); par->riva.LockUnlock(&par->riva, 0); par->riva.LoadStateExt(&par->riva, state); MISCout(par, regs->misc_output); for (i = 0; i < NUM_CRT_REGS; i++) { switch (i) { case 0x19: case 0x20 ... 0x40: break; default: CRTCout(par, i, regs->crtc[i]); } } for (i = 0; i < NUM_ATC_REGS; i++) ATTRout(par, i, regs->attr[i]); for (i = 0; i < NUM_GRC_REGS; i++) GRAout(par, i, regs->gra[i]); for (i = 0; i < NUM_SEQ_REGS; i++) SEQout(par, i, regs->seq[i]); NVTRACE_LEAVE();}/** * riva_load_video_mode - calculate timings * @info: pointer to fb_info object containing info for current riva board * * DESCRIPTION: * Calculate some timings and then send em off to riva_load_state(). * * CALLED FROM: * rivafb_set_par() */static void riva_load_video_mode(struct fb_info *info){ int bpp, width, hDisplaySize, hDisplay, hStart, hEnd, hTotal, height, vDisplay, vStart, vEnd, vTotal, dotClock; int hBlankStart, hBlankEnd, vBlankStart, vBlankEnd; struct riva_par *par = (struct riva_par *) info->par; struct riva_regs newmode; NVTRACE_ENTER(); /* time to calculate */ rivafb_blank(1, info); bpp = info->var.bits_per_pixel; if (bpp == 16 && info->var.green.length == 5) bpp = 15; width = info->var.xres_virtual; hDisplaySize = info->var.xres; hDisplay = (hDisplaySize / 8) - 1; hStart = (hDisplaySize + info->var.right_margin) / 8 - 1; hEnd = (hDisplaySize + info->var.right_margin + info->var.hsync_len) / 8 - 1; hTotal = (hDisplaySize + info->var.right_margin + info->var.hsync_len + info->var.left_margin) / 8 - 5; hBlankStart = hDisplay; hBlankEnd = hTotal + 4; height = info->var.yres_virtual; vDisplay = info->var.yres - 1; vStart = info->var.yres + info->var.lower_margin - 1; vEnd = info->var.yres + info->var.lower_margin + info->var.vsync_len - 1; vTotal = info->var.yres + info->var.lower_margin + info->var.vsync_len + info->var.upper_margin + 2; vBlankStart = vDisplay; vBlankEnd = vTotal + 1; dotClock = 1000000000 / info->var.pixclock; memcpy(&newmode, ®_template, sizeof(struct riva_regs)); if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) vTotal |= 1; if (par->FlatPanel) { vStart = vTotal - 3; vEnd = vTotal - 2; vBlankStart = vStart; hStart = hTotal - 3; hEnd = hTotal - 2; hBlankEnd = hTotal + 4; } newmode.crtc[0x0] = Set8Bits (hTotal); newmode.crtc[0x1] = Set8Bits (hDisplay); newmode.crtc[0x2] = Set8Bits (hBlankStart); newmode.crtc[0x3] = SetBitField (hBlankEnd, 4: 0, 4:0) | SetBit (7); newmode.crtc[0x4] = Set8Bits (hStart); newmode.crtc[0x5] = SetBitField (hBlankEnd, 5: 5, 7:7) | SetBitField (hEnd, 4: 0, 4:0); newmode.crtc[0x6] = SetBitField (vTotal, 7: 0, 7:0); newmode.crtc[0x7] = SetBitField (vTotal, 8: 8, 0:0) | SetBitField (vDisplay, 8: 8, 1:1) | SetBitField (vStart, 8: 8, 2:2) | SetBitField (vBlankStart, 8: 8, 3:3) | SetBit (4) | SetBitField (vTotal, 9: 9, 5:5) | SetBitField (vDisplay, 9: 9, 6:6) | SetBitField (vStart, 9: 9, 7:7); newmode.crtc[0x9] = SetBitField (vBlankStart, 9: 9, 5:5) | SetBit (6); newmode.crtc[0x10] = Set8Bits (vStart); newmode.crtc[0x11] = SetBitField (vEnd, 3: 0, 3:0) | SetBit (5); newmode.crtc[0x12] = Set8Bits (vDisplay); newmode.crtc[0x13] = (width / 8) * ((bpp + 1) / 8); newmode.crtc[0x15] = Set8Bits (vBlankStart); newmode.crtc[0x16] = Set8Bits (vBlankEnd); newmode.ext.screen = SetBitField(hBlankEnd,6:6,4:4) | SetBitField(vBlankStart,10:10,3:3) | SetBitField(vStart,10:10,2:2) | SetBitField(vDisplay,10:10,1:1) | SetBitField(vTotal,10:10,0:0); newmode.ext.horiz = SetBitField(hTotal,8:8,0:0) | SetBitField(hDisplay,8:8,1:1) | SetBitField(hBlankStart,8:8,2:2) | SetBitField(hStart,8:8,3:3); newmode.ext.extra = SetBitField(vTotal,11:11,0:0) | SetBitField(vDisplay,11:11,2:2) | SetBitField(vStart,11:11,4:4) | SetBitField(vBlankStart,11:11,6:6); if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) { int tmp = (hTotal >> 1) & ~1; newmode.ext.interlace = Set8Bits(tmp); newmode.ext.horiz |= SetBitField(tmp, 8:8,4:4); } else newmode.ext.interlace = 0xff; /* interlace off */ if (par->riva.Architecture >= NV_ARCH_10) par->riva.CURSOR = (U032 __iomem *)(info->screen_base + par->riva.CursorStart); if (info->var.sync & FB_SYNC_HOR_HIGH_ACT) newmode.misc_output &= ~0x40; else newmode.misc_output |= 0x40; if (info->var.sync & FB_SYNC_VERT_HIGH_ACT) newmode.misc_output &= ~0x80; else newmode.misc_output |= 0x80; par->riva.CalcStateExt(&par->riva, &newmode.ext, bpp, width, hDisplaySize, height, dotClock); newmode.ext.scale = NV_RD32(par->riva.PRAMDAC, 0x00000848) & 0xfff000ff; if (par->FlatPanel == 1) { newmode.ext.pixel |= (1 << 7); newmode.ext.scale |= (1 << 8); } if (par->SecondCRTC) { newmode.ext.head = NV_RD32(par->riva.PCRTC0, 0x00000860) & ~0x00001000; newmode.ext.head2 = NV_RD32(par->riva.PCRTC0, 0x00002860) | 0x00001000; newmode.ext.crtcOwner = 3; newmode.ext.pllsel |= 0x20000800; newmode.ext.vpll2 = newmode.ext.vpll; } else if (par->riva.twoHeads) { newmode.ext.head = NV_RD32(par->riva.PCRTC0, 0x00000860) | 0x00001000; newmode.ext.head2 = NV_RD32(par->riva.PCRTC0, 0x00002860) & ~0x00001000; newmode.ext.crtcOwner = 0; newmode.ext.vpll2 = NV_RD32(par->riva.PRAMDAC0, 0x00000520); } if (par->FlatPanel == 1) { newmode.ext.pixel |= (1 << 7); newmode.ext.scale |= (1 << 8); } newmode.ext.cursorConfig = 0x02000100; par->current_state = newmode; riva_load_state(par, &par->current_state); par->riva.LockUnlock(&par->riva, 0); /* important for HW cursor */ rivafb_blank(0, info); NVTRACE_LEAVE();}static void riva_update_var(struct fb_var_screeninfo *var, struct fb_videomode *modedb){ NVTRACE_ENTER(); var->xres = var->xres_virtual = modedb->xres; var->yres = modedb->yres; if (var->yres_virtual < var->yres) var->yres_virtual = var->yres; var->xoffset = var->yoffset = 0; var->pixclock = modedb->pixclock; var->left_margin = modedb->left_margin; var->right_margin = modedb->right_margin; var->upper_margin = modedb->upper_margin; var->lower_margin = modedb->lower_margin; var->hsync_len = modedb->hsync_len; var->vsync_len = modedb->vsync_len; var->sync = modedb->sync; var->vmode = modedb->vmode; NVTRACE_LEAVE();}/** * rivafb_do_maximize - * @info: pointer to fb_info object containing info for current riva board * @var: * @nom: * @den: * * DESCRIPTION: * . * * RETURNS: * -EINVAL on failure, 0 on success * * * CALLED FROM: * rivafb_check_var() */static int rivafb_do_maximize(struct fb_info *info, struct fb_var_screeninfo *var, int nom, int den){ static struct { int xres, yres; } modes[] = { {1600, 1280}, {1280, 1024}, {1024, 768}, {800, 600}, {640, 480}, {-1, -1} }; int i; NVTRACE_ENTER(); /* use highest possible virtual resolution */ if (var->xres_virtual == -1 && var->yres_virtual == -1) { printk(KERN_WARNING PFX "using maximum available virtual resolution\n"); for (i = 0; modes[i].xres != -1; i++) { if (modes[i].xres * nom / den * modes[i].yres < info->fix.smem_len) break; } if (modes[i].xres == -1) { printk(KERN_ERR PFX "could not find a virtual resolution that fits into video memory!!\n"); NVTRACE("EXIT - EINVAL error\n"); return -EINVAL; } var->xres_virtual = modes[i].xres; var->yres_virtual = modes[i].yres; printk(KERN_INFO PFX "virtual resolution set to maximum of %dx%d\n", var->xres_virtual, var->yres_virtual); } else if (var->xres_virtual == -1) { var->xres_virtual = (info->fix.smem_len * den / (nom * var->yres_virtual)) & ~15; printk(KERN_WARNING PFX "setting virtual X resolution to %d\n", var->xres_virtual); } else if (var->yres_virtual == -1) { var->xres_virtual = (var->xres_virtual + 15) & ~15; var->yres_virtual = info->fix.smem_len * den / (nom * var->xres_virtual); printk(KERN_WARNING PFX "setting virtual Y resolution to %d\n", var->yres_virtual); } else { var->xres_virtual = (var->xres_virtual + 15) & ~15; if (var->xres_virtual * nom / den * var->yres_virtual > info->fix.smem_len) { printk(KERN_ERR PFX "mode %dx%dx%d rejected...resolution too high to fit into video memory!\n", var->xres, var->yres, var->bits_per_pixel); NVTRACE("EXIT - EINVAL error\n"); return -EINVAL; } } if (var->xres_virtual * nom / den >= 8192) { printk(KERN_WARNING PFX "virtual X resolution (%d) is too high, lowering to %d\n", var->xres_virtual, 8192 * den / nom - 16); var->xres_virtual = 8192 * den / nom - 16; } if (var->xres_virtual < var->xres) { printk(KERN_ERR PFX "virtual X resolution (%d) is smaller than real\n", var->xres_virtual); return -EINVAL; } if (var->yres_virtual < var->yres) { printk(KERN_ERR PFX "virtual Y resolution (%d) is smaller than real\n", var->yres_virtual); return -EINVAL; } if (var->yres_virtual > 0x7fff/nom) var->yres_virtual = 0x7fff/nom; if (var->xres_virtual > 0x7fff/nom) var->xres_virtual = 0x7fff/nom; NVTRACE_LEAVE(); return 0;}static voidriva_set_pattern(struct riva_par *par, int clr0, int clr1, int pat0, int pat1){ RIVA_FIFO_FREE(par->riva, Patt, 4); NV_WR32(&par->riva.Patt->Color0, 0, clr0); NV_WR32(&par->riva.Patt->Color1, 0, clr1); NV_WR32(par->riva.Patt->Monochrome, 0, pat0); NV_WR32(par->riva.Patt->Monochrome, 4, pat1);}/* acceleration routines */static inline void wait_for_idle(struct riva_par *par){ while (par->riva.Busy(&par->riva));}/* * Set ROP. Translate X rop into ROP3. Internal routine. */static voidriva_set_rop_solid(struct riva_par *par, int rop){ riva_set_pattern(par, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF); RIVA_FIFO_FREE(par->riva, Rop, 1); NV_WR32(&par->riva.Rop->Rop3, 0, rop);}static void riva_setup_accel(struct fb_info *info){ struct riva_par *par = (struct riva_par *) info->par; RIVA_FIFO_FREE(par->riva, Clip, 2); NV_WR32(&par->riva.Clip->TopLeft, 0, 0x0); NV_WR32(&par->riva.Clip->WidthHeight, 0, (info->var.xres_virtual & 0xffff) | (info->var.yres_virtual << 16)); riva_set_rop_solid(par, 0xcc); wait_for_idle(par);}/** * riva_get_cmap_len - query current color map length * @var: standard kernel fb changeable data * * DESCRIPTION: * Get current color map length. * * RETURNS: * Length of color map * * CALLED FROM: * rivafb_setcolreg() */static int riva_get_cmap_len(const struct fb_var_screeninfo *var){ int rc = 256; /* reasonable default */ switch (var->green.length) { case 8: rc = 256; /* 256 entries (2^8), 8 bpp and RGB8888 */ break; case 5: rc = 32; /* 32 entries (2^5), 16 bpp, RGB555 */ break; case 6: rc = 64; /* 64 entries (2^6), 16 bpp, RGB565 */ break; default: /* should not occur */ break; } return rc;}/* ------------------------------------------------------------------------- * * * Backlight operations * * ------------------------------------------------------------------------- */#ifdef CONFIG_PMAC_BACKLIGHTstatic int riva_set_backlight_enable(int on, int level, void *data){ struct riva_par *par = (struct riva_par *)data; U032 tmp_pcrt, tmp_pmc; tmp_pmc = par->riva.PMC[0x10F0/4] & 0x0000FFFF; tmp_pcrt = par->riva.PCRTC0[0x081C/4] & 0xFFFFFFFC; if(on && (level > BACKLIGHT_OFF)) { tmp_pcrt |= 0x1; tmp_pmc |= (1 << 31); // backlight bit tmp_pmc |= riva_backlight_levels[level-1] << 16; // level } par->riva.PCRTC0[0x081C/4] = tmp_pcrt; par->riva.PMC[0x10F0/4] = tmp_pmc; return 0;}static int riva_set_backlight_level(int level, void *data){ return riva_set_backlight_enable(1, level, data);}#endif /* CONFIG_PMAC_BACKLIGHT *//* ------------------------------------------------------------------------- * * * framebuffer operations * * ------------------------------------------------------------------------- */static int rivafb_open(struct fb_info *info, int user){ struct riva_par *par = (struct riva_par *) info->par; int cnt = atomic_read(&par->ref_count); NVTRACE_ENTER(); if (!cnt) {#ifdef CONFIG_X86 memset(&par->state, 0, sizeof(struct vgastate)); par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONTS; /* save the DAC for Riva128 */ if (par->riva.Architecture == NV_ARCH_03) par->state.flags |= VGA_SAVE_CMAP; save_vga(&par->state);#endif /* vgaHWunlock() + riva unlock (0x7F) */ CRTCout(par, 0x11, 0xFF); par->riva.LockUnlock(&par->riva, 0); riva_save_state(par, &par->initial_state); } atomic_inc(&par->ref_count); NVTRACE_LEAVE(); return 0;}static int rivafb_release(struct fb_info *info, int user){ struct riva_par *par = (struct riva_par *) info->par; int cnt = atomic_read(&par->ref_count); NVTRACE_ENTER(); if (!cnt) return -EINVAL; if (cnt == 1) { par->riva.LockUnlock(&par->riva, 0); par->riva.LoadStateExt(&par->riva, &par->initial_state.ext); riva_load_state(par, &par->initial_state);#ifdef CONFIG_X86 restore_vga(&par->state);#endif par->riva.LockUnlock(&par->riva, 1); } atomic_dec(&par->ref_count); NVTRACE_LEAVE(); return 0;}static int rivafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info){ struct fb_videomode *mode; struct riva_par *par = (struct riva_par *) info->par; int nom, den; /* translating from pixels->bytes */ int mode_valid = 0; NVTRACE_ENTER(); switch (var->bits_per_pixel) { case 1 ... 8: var->red.offset = var->green.offset = var->blue.offset = 0; var->red.length = var->green.length = var->blue.length = 8; var->bits_per_pixel = 8; nom = den = 1; break; case 9 ... 15: var->green.length = 5; /* fall through */ case 16: var->bits_per_pixel = 16; /* The Riva128 supports RGB555 only */ if (par->riva.Architecture == NV_ARCH_03) var->green.length = 5; if (var->green.length == 5) { /* 0rrrrrgg gggbbbbb */ var->red.offset = 10; var->green.offset = 5; var->blue.offset = 0; var->red.length = 5; var->green.length = 5; var->blue.length = 5; } else { /* rrrrrggg gggbbbbb */ var->red.offset = 11; var->green.offset = 5; var->blue.offset = 0; var->red.length = 5; var->green.length = 6; var->blue.length = 5; } nom = 2; den = 1; break; case 17 ... 32: var->red.length = var->green.length = var->blue.length = 8; var->bits_per_pixel = 32; var->red.offset = 16; var->green.offset = 8; var->blue.offset = 0; nom = 4; den = 1; break; default: printk(KERN_ERR PFX "mode %dx%dx%d rejected...color depth not supported.\n", var->xres, var->yres, var->bits_per_pixel);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -