📄 nvidia.c
字号:
state->gra[0x05] = 0x40; state->gra[0x06] = 0x05; state->gra[0x07] = 0x0f; state->gra[0x08] = 0xff; state->seq[0x00] = 0x03; state->seq[0x01] = 0x01; state->seq[0x02] = 0x0f; state->seq[0x03] = 0x00; state->seq[0x04] = 0x0e; state->misc_output = 0xeb;}static int nvidiafb_cursor(struct fb_info *info, struct fb_cursor *cursor){ struct nvidia_par *par = info->par; u8 data[MAX_CURS * MAX_CURS / 8]; int i, set = cursor->set; u16 fg, bg; if (cursor->image.width > MAX_CURS || cursor->image.height > MAX_CURS) return -ENXIO; NVShowHideCursor(par, 0); if (par->cursor_reset) { set = FB_CUR_SETALL; par->cursor_reset = 0; } if (set & FB_CUR_SETSIZE) memset_io(par->CURSOR, 0, MAX_CURS * MAX_CURS * 2); if (set & FB_CUR_SETPOS) { u32 xx, yy, temp; yy = cursor->image.dy - info->var.yoffset; xx = cursor->image.dx - info->var.xoffset; temp = xx & 0xFFFF; temp |= yy << 16; NV_WR32(par->PRAMDAC, 0x0000300, temp); } if (set & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP | FB_CUR_SETIMAGE)) { u32 bg_idx = cursor->image.bg_color; u32 fg_idx = cursor->image.fg_color; u32 s_pitch = (cursor->image.width + 7) >> 3; u32 d_pitch = MAX_CURS / 8; u8 *dat = (u8 *) cursor->image.data; u8 *msk = (u8 *) cursor->mask; u8 *src; src = kmalloc(s_pitch * cursor->image.height, GFP_ATOMIC); if (src) { switch (cursor->rop) { case ROP_XOR: for (i = 0; i < s_pitch * cursor->image.height; i++) src[i] = dat[i] ^ msk[i]; break; case ROP_COPY: default: for (i = 0; i < s_pitch * cursor->image.height; i++) src[i] = dat[i] & msk[i]; break; } fb_pad_aligned_buffer(data, d_pitch, src, s_pitch, cursor->image.height); bg = ((info->cmap.red[bg_idx] & 0xf8) << 7) | ((info->cmap.green[bg_idx] & 0xf8) << 2) | ((info->cmap.blue[bg_idx] & 0xf8) >> 3) | 1 << 15; fg = ((info->cmap.red[fg_idx] & 0xf8) << 7) | ((info->cmap.green[fg_idx] & 0xf8) << 2) | ((info->cmap.blue[fg_idx] & 0xf8) >> 3) | 1 << 15; NVLockUnlock(par, 0); nvidiafb_load_cursor_image(par, data, bg, fg, cursor->image.width, cursor->image.height); kfree(src); } } if (cursor->enable) NVShowHideCursor(par, 1); return 0;}static int nvidiafb_set_par(struct fb_info *info){ struct nvidia_par *par = info->par; NVTRACE_ENTER(); NVLockUnlock(par, 1); if (!par->FlatPanel || (info->var.bits_per_pixel != 24) || !par->twoHeads) par->FPDither = 0; info->fix.visual = (info->var.bits_per_pixel == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; nvidia_init_vga(info); nvidia_calc_regs(info); nvidia_write_regs(par); NVLockUnlock(par, 0); if (par->twoHeads) { VGA_WR08(par->PCIO, 0x03D4, 0x44); VGA_WR08(par->PCIO, 0x03D5, par->ModeReg.crtcOwner); NVLockUnlock(par, 0); } NVWriteCrtc(par, 0x11, 0x00); info->fix.line_length = (info->var.xres_virtual * info->var.bits_per_pixel) >> 3; if (info->var.accel_flags) { info->fbops->fb_imageblit = nvidiafb_imageblit; info->fbops->fb_fillrect = nvidiafb_fillrect; info->fbops->fb_copyarea = nvidiafb_copyarea; info->fbops->fb_sync = nvidiafb_sync; info->pixmap.scan_align = 4; info->flags &= ~FBINFO_HWACCEL_DISABLED; NVResetGraphics(info); } else { info->fbops->fb_imageblit = cfb_imageblit; info->fbops->fb_fillrect = cfb_fillrect; info->fbops->fb_copyarea = cfb_copyarea; info->fbops->fb_sync = NULL; info->pixmap.scan_align = 1; info->flags |= FBINFO_HWACCEL_DISABLED; } par->cursor_reset = 1; NVWriteCrtc(par, 0x11, 0xff); NVTRACE_LEAVE(); return 0;}static int nvidiafb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info){ struct nvidia_par *par = info->par; int i; NVTRACE_ENTER(); if (regno >= (1 << info->var.green.length)) return -EINVAL; if (info->var.grayscale) { /* gray = 0.30*R + 0.59*G + 0.11*B */ red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8; } if (regno < 16 && info->fix.visual == FB_VISUAL_DIRECTCOLOR) { ((u32 *) info->pseudo_palette)[regno] = (regno << info->var.red.offset) | (regno << info->var.green.offset) | (regno << info->var.blue.offset); } switch (info->var.bits_per_pixel) { case 8: /* "transparent" stuff is completely ignored. */ nvidia_write_clut(par, regno, red >> 8, green >> 8, blue >> 8); break; case 16: if (info->var.green.length == 5) { for (i = 0; i < 8; i++) { nvidia_write_clut(par, regno * 8 + i, red >> 8, green >> 8, blue >> 8); } } else { u8 r, g, b; if (regno < 32) { for (i = 0; i < 8; i++) { nvidia_write_clut(par, regno * 8 + i, red >> 8, green >> 8, blue >> 8); } } nvidia_read_clut(par, regno * 4, &r, &g, &b); for (i = 0; i < 4; i++) nvidia_write_clut(par, regno * 4 + i, r, green >> 8, b); } break; case 32: nvidia_write_clut(par, regno, red >> 8, green >> 8, blue >> 8); break; default: /* do nothing */ break; } NVTRACE_LEAVE(); return 0;}static int nvidiafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info){ struct nvidia_par *par = info->par; int memlen, vramlen, mode_valid = 0; int pitch, err = 0; NVTRACE_ENTER(); var->transp.offset = 0; var->transp.length = 0; var->xres &= ~7; if (var->bits_per_pixel <= 8) var->bits_per_pixel = 8; else if (var->bits_per_pixel <= 16) var->bits_per_pixel = 16; else var->bits_per_pixel = 32; switch (var->bits_per_pixel) { case 8: var->red.offset = 0; var->red.length = 8; var->green.offset = 0; var->green.length = 8; var->blue.offset = 0; var->blue.length = 8; var->transp.offset = 0; var->transp.length = 0; break; case 16: var->green.length = (var->green.length < 6) ? 5 : 6; var->red.length = 5; var->blue.length = 5; var->transp.length = 6 - var->green.length; var->blue.offset = 0; var->green.offset = 5; var->red.offset = 5 + var->green.length; var->transp.offset = (5 + var->red.offset) & 15; break; case 32: /* RGBA 8888 */ var->red.offset = 16; var->red.length = 8; var->green.offset = 8; var->green.length = 8; var->blue.offset = 0; var->blue.length = 8; var->transp.length = 8; var->transp.offset = 24; break; } var->red.msb_right = 0; var->green.msb_right = 0; var->blue.msb_right = 0; var->transp.msb_right = 0; if (!info->monspecs.hfmax || !info->monspecs.vfmax || !info->monspecs.dclkmax || !fb_validate_mode(var, info)) mode_valid = 1; /* calculate modeline if supported by monitor */ if (!mode_valid && info->monspecs.gtf) { if (!fb_get_mode(FB_MAXTIMINGS, 0, var, info)) mode_valid = 1; } if (!mode_valid) { struct fb_videomode *mode; mode = fb_find_best_mode(var, &info->modelist); if (mode) { fb_videomode_to_var(var, mode); mode_valid = 1; } } if (!mode_valid && info->monspecs.modedb_len) return -EINVAL; if (par->fpWidth && par->fpHeight && (par->fpWidth < var->xres || par->fpHeight < var->yres)) return -EINVAL; if (var->yres_virtual < var->yres) var->yres_virtual = var->yres; if (var->xres_virtual < var->xres) var->xres_virtual = var->xres; var->xres_virtual = (var->xres_virtual + 63) & ~63; vramlen = info->screen_size; pitch = ((var->xres_virtual * var->bits_per_pixel) + 7) / 8; memlen = pitch * var->yres_virtual; if (memlen > vramlen) { var->yres_virtual = vramlen / pitch; if (var->yres_virtual < var->yres) { var->yres_virtual = var->yres; var->xres_virtual = vramlen / var->yres_virtual; var->xres_virtual /= var->bits_per_pixel / 8; var->xres_virtual &= ~63; pitch = (var->xres_virtual * var->bits_per_pixel + 7) / 8; memlen = pitch * var->yres; if (var->xres_virtual < var->xres) { printk("nvidiafb: required video memory, " "%d bytes, for %dx%d-%d (virtual) " "is out of range\n", memlen, var->xres_virtual, var->yres_virtual, var->bits_per_pixel); err = -ENOMEM; } } } if (var->accel_flags) { if (var->yres_virtual > 0x7fff) var->yres_virtual = 0x7fff; if (var->xres_virtual > 0x7fff) var->xres_virtual = 0x7fff; } var->xres_virtual &= ~63; NVTRACE_LEAVE(); return err;}static int nvidiafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info){ struct nvidia_par *par = info->par; u32 total; total = info->var.yoffset * info->fix.line_length + info->var.xoffset; NVSetStartAddress(par, total); return 0;}static int nvidiafb_blank(int blank, struct fb_info *info){ struct nvidia_par *par = info->par; unsigned char tmp, vesa; tmp = NVReadSeq(par, 0x01) & ~0x20; /* screen on/off */ vesa = NVReadCrtc(par, 0x1a) & ~0xc0; /* sync on/off */ NVTRACE_ENTER(); if (blank) tmp |= 0x20; switch (blank) { case FB_BLANK_UNBLANK: case FB_BLANK_NORMAL: break; case FB_BLANK_VSYNC_SUSPEND: vesa |= 0x80; break; case FB_BLANK_HSYNC_SUSPEND: vesa |= 0x40; break; case FB_BLANK_POWERDOWN: vesa |= 0xc0; break; } NVWriteSeq(par, 0x01, tmp); NVWriteCrtc(par, 0x1a, vesa);#ifdef CONFIG_PMAC_BACKLIGHT if (par->FlatPanel && _machine == _MACH_Pmac) { set_backlight_enable(!blank); }#endif NVTRACE_LEAVE(); return 0;}static struct fb_ops nvidia_fb_ops = { .owner = THIS_MODULE, .fb_check_var = nvidiafb_check_var, .fb_set_par = nvidiafb_set_par, .fb_setcolreg = nvidiafb_setcolreg, .fb_pan_display = nvidiafb_pan_display, .fb_blank = nvidiafb_blank, .fb_fillrect = nvidiafb_fillrect, .fb_copyarea = nvidiafb_copyarea, .fb_imageblit = nvidiafb_imageblit, .fb_cursor = nvidiafb_cursor, .fb_sync = nvidiafb_sync,};static int __devinit nvidia_set_fbinfo(struct fb_info *info){ struct fb_monspecs *specs = &info->monspecs; struct fb_videomode modedb; struct nvidia_par *par = info->par; int lpitch; NVTRACE_ENTER(); info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_IMAGEBLIT | FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_YPAN; fb_videomode_to_modelist(info->monspecs.modedb, info->monspecs.modedb_len, &info->modelist); fb_var_to_videomode(&modedb, &nvidiafb_default_var); if (specs->modedb != NULL) { /* get preferred timing */ if (specs->misc & FB_MISC_1ST_DETAIL) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -