fbdev.c
来自「优龙2410linux2.6.8内核源代码」· C语言 代码 · 共 2,214 行 · 第 1/4 页
C
2,214 行
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); restore_vga(&par->state); 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_monspecs *specs = &info->monspecs; 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; 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); NVTRACE("EXIT, returning -EINVAL\n"); return -EINVAL; } if (!strictmode) { if (!fb_validate_mode(var, info)) mode_valid = 1; } /* find best mode from modedb */ if (!mode_valid && specs->modedb_len) { int i, best, best_refresh, best_x, best_y, diff_x, diff_y; best_refresh = best = best_x = best_y = 0; diff_x = diff_y = -1; for (i = 0; i < specs->modedb_len; i++) { if (var->xres <= specs->modedb[i].xres && !(specs->modedb[i].flag & FB_MODE_IS_CALCULATED) && specs->modedb[i].xres - var->xres < diff_x) { best_x = specs->modedb[i].xres; diff_x = best_x - var->xres; } if (!diff_x) break; } if (diff_x != -1) { for (i = 0; i < specs->modedb_len; i++) { if (best_x == specs->modedb[i].xres && var->yres <= specs->modedb[i].yres && !(specs->modedb[i].flag & FB_MODE_IS_CALCULATED) && specs->modedb[i].yres-var->yres < diff_y) { best_y = specs->modedb[i].yres; diff_y = best_y - var->yres; } if (!diff_y) break; } } if (diff_y != -1) { for (i = 0; i < specs->modedb_len; i++) { if (best_x == specs->modedb[i].xres && best_y == specs->modedb[i].yres && !(specs->modedb[i].flag & FB_MODE_IS_CALCULATED) && specs->modedb[i].refresh > best_refresh) { best_refresh=specs->modedb[i].refresh; best = i; } } } if (best_refresh) { riva_update_var(var, &specs->modedb[best]); 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 && 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(); riva_common_setup(par); RivaGetConfig(&par->riva, par->Chipset); /* vgaHWunlock() + riva unlock (0x7F) */ CRTCout(par, 0x11, 0xFF); par->riva.LockUnlock(&par->riva, 0); riva_load_video_mode(info); riva_setup_accel(info); memset_io(par->riva.CURSOR, 0, MAX_CURS * MAX_CURS * 2); 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; 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 - 1) { case VESA_NO_BLANKING: break; case VESA_VSYNC_SUSPEND: vesa |= 0x80; break; case VESA_HSYNC_SUSPEND: vesa |= 0x40; break; case VESA_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; } 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) { if (regno < 16) { /* 0rrrrrgg gggbbbbb */ ((u32 *)info->pseudo_palette)[regno] = ((red & 0xf800) >> 1) | ((green & 0xf800) >> 6) | ((blue & 0xf800) >> 11); } 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 < 16) { /* rrrrrggg gggbbbbb */ ((u32 *)info->pseudo_palette)[regno] = ((red & 0xf800) >> 0) | ((green & 0xf800) >> 5) | ((blue & 0xf800) >> 11); } if (regno < 32) { for (i = 0; i < 8; i++) { riva_wclut(chip, regno*8+i, red >> 8, green >> 8, blue >> 8); } } for (i = 0; i < 4; i++) { riva_rclut(chip, regno*2+i, &r, &g, &b); riva_wclut(chip, regno*4+i, r, green >> 8, b); } } break; case 32: if (regno < 16) { ((u32 *)info->pseudo_palette)[regno] = ((red & 0xff00) << 8) | ((green & 0xff00)) | ((blue & 0xff00) >> 8); } 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->var.bits_per_pixel == 8) color = rect->color; else color = ((u32 *)info->pseudo_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); par->riva.Bitmap->Color1A = color; RIVA_FIFO_FREE(par->riva, Bitmap, 2); par->riva.Bitmap->UnclippedRectangle[0].TopLeft = (rect->dx << 16) | rect->dy; mb(); par->riva.Bitmap->UnclippedRectangle[0].WidthHeight = (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; RIVA_FIFO_FREE(par->riva, Blt, 3); par->riva.Blt->TopLeftSrc = (region->sy << 16) | region->sx; par->riva.Blt->TopLeftDst = (region->dy << 16) | region->dx; mb(); par->riva.Blt->WidthHeight = (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 *d; int i, size; if (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: fgx = ((u32 *)info->pseudo_palette)[image->fg_color]; bgx = ((u32 *)info->pseudo_palette)[image->bg_color]; if (info->var.green.length == 6) convert_bgcolor_16(&bgx); break; case 32: fgx = ((u32 *)info->pseudo_palette)[image->fg_color]; bgx = ((u32 *)info->pseudo_palette)[image->bg_color]; break; } RIVA_FIFO_FREE(par->riva, Bitmap, 7); par->riva.Bitmap->ClipE.TopLeft = (image->dy << 16) | (image->dx & 0xFFFF); par->riva.Bitmap->ClipE.BottomRight = (((image->dy + image->height) << 16) | ((image->dx + image->width) & 0xffff)); par->riva.Bitmap->Color0E = bgx; par->riva.Bitmap->Color1E = fgx; par->riva.Bitmap->WidthHeightInE = (image->height << 16) | ((image->width + 31) & ~31); par->riva.Bitmap->WidthHeightOutE = (image->height << 16) | ((image->width + 31) & ~31); par->riva.Bitmap->PointE = (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); d[i] = 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); d[i] = 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];
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?