📄 fbdev.c
字号:
NVTRACE("EXIT, returning -EINVAL\n"); return -EINVAL; } if (!strictmode) { if (!info->monspecs.vfmax || !info->monspecs.hfmax || !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) { mode = fb_find_best_mode(var, &info->modelist); if (mode) { riva_update_var(var, mode); mode_valid = 1; } } if (!mode_valid && info->monspecs.modedb_len) return -EINVAL; if (var->xres_virtual < var->xres) var->xres_virtual = var->xres; if (var->yres_virtual <= var->yres) var->yres_virtual = -1; if (rivafb_do_maximize(info, var, nom, den) < 0) return -EINVAL; if (var->xoffset < 0) var->xoffset = 0; if (var->yoffset < 0) var->yoffset = 0; /* truncate xoffset and yoffset to maximum if too high */ if (var->xoffset > var->xres_virtual - var->xres) var->xoffset = var->xres_virtual - var->xres - 1; if (var->yoffset > var->yres_virtual - var->yres) var->yoffset = var->yres_virtual - var->yres - 1; var->red.msb_right = var->green.msb_right = var->blue.msb_right = var->transp.offset = var->transp.length = var->transp.msb_right = 0; NVTRACE_LEAVE(); return 0;}static int rivafb_set_par(struct fb_info *info){ struct riva_par *par = (struct riva_par *) info->par; NVTRACE_ENTER(); /* vgaHWunlock() + riva unlock (0x7F) */ CRTCout(par, 0x11, 0xFF); par->riva.LockUnlock(&par->riva, 0); riva_load_video_mode(info); if(!(info->flags & FBINFO_HWACCEL_DISABLED)) riva_setup_accel(info); par->cursor_reset = 1; info->fix.line_length = (info->var.xres_virtual * (info->var.bits_per_pixel >> 3)); info->fix.visual = (info->var.bits_per_pixel == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; if (info->flags & FBINFO_HWACCEL_DISABLED) info->pixmap.scan_align = 1; else info->pixmap.scan_align = 4; NVTRACE_LEAVE(); return 0;}/** * rivafb_pan_display * @var: standard kernel fb changeable data * @con: TODO * @info: pointer to fb_info object containing info for current riva board * * DESCRIPTION: * Pan (or wrap, depending on the `vmode' field) the display using the * `xoffset' and `yoffset' fields of the `var' structure. * If the values don't fit, return -EINVAL. * * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag */static int rivafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info){ struct riva_par *par = (struct riva_par *)info->par; unsigned int base; NVTRACE_ENTER(); if (var->xoffset > (var->xres_virtual - var->xres)) return -EINVAL; if (var->yoffset > (var->yres_virtual - var->yres)) return -EINVAL; if (var->vmode & FB_VMODE_YWRAP) { if (var->yoffset < 0 || var->yoffset >= info->var.yres_virtual || var->xoffset) return -EINVAL; } else { if (var->xoffset + info->var.xres > info->var.xres_virtual || var->yoffset + info->var.yres > info->var.yres_virtual) return -EINVAL; } base = var->yoffset * info->fix.line_length + var->xoffset; par->riva.SetStartAddress(&par->riva, base); info->var.xoffset = var->xoffset; info->var.yoffset = var->yoffset; if (var->vmode & FB_VMODE_YWRAP) info->var.vmode |= FB_VMODE_YWRAP; else info->var.vmode &= ~FB_VMODE_YWRAP; NVTRACE_LEAVE(); return 0;}static int rivafb_blank(int blank, struct fb_info *info){ struct riva_par *par= (struct riva_par *)info->par; unsigned char tmp, vesa; tmp = SEQin(par, 0x01) & ~0x20; /* screen on/off */ vesa = CRTCin(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; } SEQout(par, 0x01, tmp); CRTCout(par, 0x1a, vesa);#ifdef CONFIG_PMAC_BACKLIGHT if ( par->FlatPanel && _machine == _MACH_Pmac) { set_backlight_enable(!blank); }#endif NVTRACE_LEAVE(); return 0;}/** * rivafb_setcolreg * @regno: register index * @red: red component * @green: green component * @blue: blue component * @transp: transparency * @info: pointer to fb_info object containing info for current riva board * * DESCRIPTION: * Set a single color register. The values supplied have a 16 bit * magnitude. * * RETURNS: * Return != 0 for invalid regno. * * CALLED FROM: * fbcmap.c:fb_set_cmap() */static int rivafb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info){ struct riva_par *par = (struct riva_par *)info->par; RIVA_HW_INST *chip = &par->riva; int i; if (regno >= riva_get_cmap_len(&info->var)) 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); /* * The Riva128 2D engine requires color information in * TrueColor format even if framebuffer is in DirectColor */ if (par->riva.Architecture == NV_ARCH_03) { switch (info->var.bits_per_pixel) { case 16: par->palette[regno] = ((red & 0xf800) >> 1) | ((green & 0xf800) >> 6) | ((blue & 0xf800) >> 11); break; case 32: par->palette[regno] = ((red & 0xff00) << 8) | ((green & 0xff00)) | ((blue & 0xff00) >> 8); break; } } } switch (info->var.bits_per_pixel) { case 8: /* "transparent" stuff is completely ignored. */ riva_wclut(chip, regno, red >> 8, green >> 8, blue >> 8); break; case 16: if (info->var.green.length == 5) { for (i = 0; i < 8; i++) { riva_wclut(chip, regno*8+i, red >> 8, green >> 8, blue >> 8); } } else { u8 r, g, b; if (regno < 32) { for (i = 0; i < 8; i++) { riva_wclut(chip, regno*8+i, red >> 8, green >> 8, blue >> 8); } } riva_rclut(chip, regno*4, &r, &g, &b); for (i = 0; i < 4; i++) riva_wclut(chip, regno*4+i, r, green >> 8, b); } break; case 32: riva_wclut(chip, regno, red >> 8, green >> 8, blue >> 8); break; default: /* do nothing */ break; } return 0;}/** * rivafb_fillrect - hardware accelerated color fill function * @info: pointer to fb_info structure * @rect: pointer to fb_fillrect structure * * DESCRIPTION: * This function fills up a region of framebuffer memory with a solid * color with a choice of two different ROP's, copy or invert. * * CALLED FROM: * framebuffer hook */static void rivafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect){ struct riva_par *par = (struct riva_par *) info->par; u_int color, rop = 0; if ((info->flags & FBINFO_HWACCEL_DISABLED)) { cfb_fillrect(info, rect); return; } if (info->var.bits_per_pixel == 8) color = rect->color; else { if (par->riva.Architecture != NV_ARCH_03) color = ((u32 *)info->pseudo_palette)[rect->color]; else color = par->palette[rect->color]; } switch (rect->rop) { case ROP_XOR: rop = 0x66; break; case ROP_COPY: default: rop = 0xCC; break; } riva_set_rop_solid(par, rop); RIVA_FIFO_FREE(par->riva, Bitmap, 1); NV_WR32(&par->riva.Bitmap->Color1A, 0, color); RIVA_FIFO_FREE(par->riva, Bitmap, 2); NV_WR32(&par->riva.Bitmap->UnclippedRectangle[0].TopLeft, 0, (rect->dx << 16) | rect->dy); mb(); NV_WR32(&par->riva.Bitmap->UnclippedRectangle[0].WidthHeight, 0, (rect->width << 16) | rect->height); mb(); riva_set_rop_solid(par, 0xcc);}/** * rivafb_copyarea - hardware accelerated blit function * @info: pointer to fb_info structure * @region: pointer to fb_copyarea structure * * DESCRIPTION: * This copies an area of pixels from one location to another * * CALLED FROM: * framebuffer hook */static void rivafb_copyarea(struct fb_info *info, const struct fb_copyarea *region){ struct riva_par *par = (struct riva_par *) info->par; if ((info->flags & FBINFO_HWACCEL_DISABLED)) { cfb_copyarea(info, region); return; } RIVA_FIFO_FREE(par->riva, Blt, 3); NV_WR32(&par->riva.Blt->TopLeftSrc, 0, (region->sy << 16) | region->sx); NV_WR32(&par->riva.Blt->TopLeftDst, 0, (region->dy << 16) | region->dx); mb(); NV_WR32(&par->riva.Blt->WidthHeight, 0, (region->height << 16) | region->width); mb();}static inline void convert_bgcolor_16(u32 *col){ *col = ((*col & 0x0000F800) << 8) | ((*col & 0x00007E0) << 5) | ((*col & 0x0000001F) << 3) | 0xFF000000; mb();}/** * rivafb_imageblit: hardware accelerated color expand function * @info: pointer to fb_info structure * @image: pointer to fb_image structure * * DESCRIPTION: * If the source is a monochrome bitmap, the function fills up a a region * of framebuffer memory with pixels whose color is determined by the bit * setting of the bitmap, 1 - foreground, 0 - background. * * If the source is not a monochrome bitmap, color expansion is not done. * In this case, it is channeled to a software function. * * CALLED FROM: * framebuffer hook */static void rivafb_imageblit(struct fb_info *info, const struct fb_image *image){ struct riva_par *par = (struct riva_par *) info->par; u32 fgx = 0, bgx = 0, width, tmp; u8 *cdat = (u8 *) image->data; volatile u32 __iomem *d; int i, size; if ((info->flags & FBINFO_HWACCEL_DISABLED) || image->depth != 1) { cfb_imageblit(info, image); return; } switch (info->var.bits_per_pixel) { case 8: fgx = image->fg_color; bgx = image->bg_color; break; case 16: case 32: if (par->riva.Architecture != NV_ARCH_03) { fgx = ((u32 *)info->pseudo_palette)[image->fg_color]; bgx = ((u32 *)info->pseudo_palette)[image->bg_color]; } else { fgx = par->palette[image->fg_color]; bgx = par->palette[image->bg_color]; } if (info->var.green.length == 6) convert_bgcolor_16(&bgx); break; } RIVA_FIFO_FREE(par->riva, Bitmap, 7); NV_WR32(&par->riva.Bitmap->ClipE.TopLeft, 0, (image->dy << 16) | (image->dx & 0xFFFF)); NV_WR32(&par->riva.Bitmap->ClipE.BottomRight, 0, (((image->dy + image->height) << 16) | ((image->dx + image->width) & 0xffff))); NV_WR32(&par->riva.Bitmap->Color0E, 0, bgx); NV_WR32(&par->riva.Bitmap->Color1E, 0, fgx); NV_WR32(&par->riva.Bitmap->WidthHeightInE, 0, (image->height << 16) | ((image->width + 31) & ~31)); NV_WR32(&par->riva.Bitmap->WidthHeightOutE, 0, (image->height << 16) | ((image->width + 31) & ~31)); NV_WR32(&par->riva.Bitmap->PointE, 0, (image->dy << 16) | (image->dx & 0xFFFF)); d = &par->riva.Bitmap->MonochromeData01E; width = (image->width + 31)/32; size = width * image->height; while (size >= 16) { RIVA_FIFO_FREE(par->riva, Bitmap, 16); for (i = 0; i < 16; i++) { tmp = *((u32 *)cdat); cdat = (u8 *)((u32 *)cdat + 1); reverse_order(&tmp); NV_WR32(d, i*4, tmp); } size -= 16; } if (size) { RIVA_FIFO_FREE(par->riva, Bitmap, size); for (i = 0; i < size; i++) { tmp = *((u32 *) cdat); cdat = (u8 *)((u32 *)cdat + 1); reverse_order(&tmp); NV_WR32(d, i*4, tmp); } }}/** * rivafb_cursor - hardware cursor function * @info: pointer to info structure * @cursor: pointer to fbcursor structure * * DESCRIPTION: * A cursor function that supports displaying a cursor image via hardware. * Within the kernel, copy and invert rops are supported. If exported * to user space, only the copy rop will be supported. * * CALLED FROM * framebuffer hook */static int rivafb_cursor(struct fb_info *info, struct fb_cursor *cursor){ struct riva_par *par = (struct riva_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; par->riva.ShowHideCursor(&par->riva, 0); if (par->cursor_reset) { set = FB_CUR_SETALL; par->cursor_reset = 0; } if (set & FB_CUR_SETSIZE) memset_io(par->riva.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->riva.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; par->riva.LockUnlock(&par->riva, 0); rivafb_load_cursor_image(par, data, bg, fg, cursor->image.width, cursor->image.height); kfree(src); } } if (cursor->enable) par->riva.ShowHideCursor(&par->riva, 1); return 0;}static int rivafb_sync(struct fb_info *info){ struct riva_par *par = (struct riva_par *)info->par;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -