📄 intelfbdrv.c
字号:
info->pixmap.scan_align = 1; strcpy(info->fix.id, dinfo->name); info->fix.smem_start = dinfo->fb.physical; info->fix.smem_len = dinfo->fb.size; info->fix.type = FB_TYPE_PACKED_PIXELS; info->fix.type_aux = 0; info->fix.xpanstep = 8; info->fix.ypanstep = 1; info->fix.ywrapstep = 0; info->fix.mmio_start = dinfo->mmio_base_phys; info->fix.mmio_len = INTEL_REG_SIZE; info->fix.accel = FB_ACCEL_I830; update_dinfo(dinfo, &info->var); return 0;}/* Update dinfo to match the active video mode. */static void update_dinfo(struct intelfb_info *dinfo, struct fb_var_screeninfo *var){ DBG_MSG("update_dinfo\n"); dinfo->bpp = var->bits_per_pixel; dinfo->depth = intelfb_var_to_depth(var); dinfo->xres = var->xres; dinfo->yres = var->xres; dinfo->pixclock = var->pixclock; dinfo->info->fix.visual = dinfo->visual; dinfo->info->fix.line_length = dinfo->pitch; switch (dinfo->bpp) { case 8: dinfo->visual = FB_VISUAL_PSEUDOCOLOR; dinfo->pitch = var->xres_virtual; break; case 16: dinfo->visual = FB_VISUAL_TRUECOLOR; dinfo->pitch = var->xres_virtual * 2; break; case 32: dinfo->visual = FB_VISUAL_TRUECOLOR; dinfo->pitch = var->xres_virtual * 4; break; } /* Make sure the line length is a aligned correctly. */ if (IS_I9XX(dinfo)) dinfo->pitch = ROUND_UP_TO(dinfo->pitch, STRIDE_ALIGNMENT_I9XX); else dinfo->pitch = ROUND_UP_TO(dinfo->pitch, STRIDE_ALIGNMENT); if (FIXED_MODE(dinfo)) dinfo->pitch = dinfo->initial_pitch; dinfo->info->screen_base = (char __iomem *)dinfo->fb.virtual; dinfo->info->fix.line_length = dinfo->pitch; dinfo->info->fix.visual = dinfo->visual;}/* fbops functions *//*************************************************************** * fbdev interface * ***************************************************************/static int intelfb_open(struct fb_info *info, int user){ struct intelfb_info *dinfo = GET_DINFO(info); if (user) dinfo->open++; return 0;}static int intelfb_release(struct fb_info *info, int user){ struct intelfb_info *dinfo = GET_DINFO(info); if (user) { dinfo->open--; msleep(1); if (!dinfo->open) intelfbhw_disable_irq(dinfo); } return 0;}static int intelfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info){ int change_var = 0; struct fb_var_screeninfo v; struct intelfb_info *dinfo; static int first = 1; int i; /* Good pitches to allow tiling. Don't care about pitches < 1024. */ static const int pitches[] = { 128 * 8, 128 * 16, 128 * 32, 128 * 64, 0 }; DBG_MSG("intelfb_check_var: accel_flags is %d\n", var->accel_flags); dinfo = GET_DINFO(info); /* update the pitch */ if (intelfbhw_validate_mode(dinfo, var) != 0) return -EINVAL; v = *var; for (i = 0; pitches[i] != 0; i++) { if (pitches[i] >= v.xres_virtual) { v.xres_virtual = pitches[i]; break; } } /* Check for a supported bpp. */ if (v.bits_per_pixel <= 8) v.bits_per_pixel = 8; else if (v.bits_per_pixel <= 16) { if (v.bits_per_pixel == 16) v.green.length = 6; v.bits_per_pixel = 16; } else if (v.bits_per_pixel <= 32) v.bits_per_pixel = 32; else return -EINVAL; change_var = ((info->var.xres != var->xres) || (info->var.yres != var->yres) || (info->var.xres_virtual != var->xres_virtual) || (info->var.yres_virtual != var->yres_virtual) || (info->var.bits_per_pixel != var->bits_per_pixel) || memcmp(&info->var.red, &var->red, sizeof(var->red)) || memcmp(&info->var.green, &var->green, sizeof(var->green)) || memcmp(&info->var.blue, &var->blue, sizeof(var->blue))); if (FIXED_MODE(dinfo) && (change_var || var->yres_virtual > dinfo->initial_var.yres_virtual || var->yres_virtual < dinfo->initial_var.yres || var->xoffset || var->nonstd)) { if (first) { ERR_MSG("Changing the video mode is not supported.\n"); first = 0; } return -EINVAL; } switch (intelfb_var_to_depth(&v)) { case 8: v.red.offset = v.green.offset = v.blue.offset = 0; v.red.length = v.green.length = v.blue.length = 8; v.transp.offset = v.transp.length = 0; break; case 15: v.red.offset = 10; v.green.offset = 5; v.blue.offset = 0; v.red.length = v.green.length = v.blue.length = 5; v.transp.offset = v.transp.length = 0; break; case 16: v.red.offset = 11; v.green.offset = 5; v.blue.offset = 0; v.red.length = 5; v.green.length = 6; v.blue.length = 5; v.transp.offset = v.transp.length = 0; break; case 24: v.red.offset = 16; v.green.offset = 8; v.blue.offset = 0; v.red.length = v.green.length = v.blue.length = 8; v.transp.offset = v.transp.length = 0; break; case 32: v.red.offset = 16; v.green.offset = 8; v.blue.offset = 0; v.red.length = v.green.length = v.blue.length = 8; v.transp.offset = 24; v.transp.length = 8; break; } if (v.xoffset < 0) v.xoffset = 0; if (v.yoffset < 0) v.yoffset = 0; if (v.xoffset > v.xres_virtual - v.xres) v.xoffset = v.xres_virtual - v.xres; if (v.yoffset > v.yres_virtual - v.yres) v.yoffset = v.yres_virtual - v.yres; v.red.msb_right = v.green.msb_right = v.blue.msb_right = v.transp.msb_right = 0; *var = v; return 0;}static int intelfb_set_par(struct fb_info *info){ struct intelfb_hwstate *hw; struct intelfb_info *dinfo = GET_DINFO(info); if (FIXED_MODE(dinfo)) { ERR_MSG("Changing the video mode is not supported.\n"); return -EINVAL; } hw = kmalloc(sizeof(*hw), GFP_ATOMIC); if (!hw) return -ENOMEM; DBG_MSG("intelfb_set_par (%dx%d-%d)\n", info->var.xres, info->var.yres, info->var.bits_per_pixel); intelfb_blank(FB_BLANK_POWERDOWN, info); if (ACCEL(dinfo, info)) intelfbhw_2d_stop(dinfo); memcpy(hw, &dinfo->save_state, sizeof(*hw)); if (intelfbhw_mode_to_hw(dinfo, hw, &info->var)) goto invalid_mode; if (intelfbhw_program_mode(dinfo, hw, 0)) goto invalid_mode;#if REGDUMP > 0 intelfbhw_read_hw_state(dinfo, hw, 0); intelfbhw_print_hw_state(dinfo, hw);#endif update_dinfo(dinfo, &info->var); if (ACCEL(dinfo, info)) intelfbhw_2d_start(dinfo); intelfb_pan_display(&info->var, info); intelfb_blank(FB_BLANK_UNBLANK, info); if (ACCEL(dinfo, info)) { info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN | FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_IMAGEBLIT; } else info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; kfree(hw); return 0;invalid_mode: kfree(hw); return -EINVAL;}static int intelfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info){ struct intelfb_info *dinfo = GET_DINFO(info);#if VERBOSE > 0 DBG_MSG("intelfb_setcolreg: regno %d, depth %d\n", regno, dinfo->depth);#endif if (regno > 255) return 1; if (dinfo->depth == 8) { red >>= 8; green >>= 8; blue >>= 8; intelfbhw_setcolreg(dinfo, regno, red, green, blue, transp); } if (regno < 16) { switch (dinfo->depth) { case 15: dinfo->pseudo_palette[regno] = ((red & 0xf800) >> 1) | ((green & 0xf800) >> 6) | ((blue & 0xf800) >> 11); break; case 16: dinfo->pseudo_palette[regno] = (red & 0xf800) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11); break; case 24: dinfo->pseudo_palette[regno] = ((red & 0xff00) << 8) | (green & 0xff00) | ((blue & 0xff00) >> 8); break; } } return 0;}static int intelfb_blank(int blank, struct fb_info *info){ intelfbhw_do_blank(blank, info); return 0;}static int intelfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info){ intelfbhw_pan_display(var, info); return 0;}/* When/if we have our own ioctls. */static int intelfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg){ int retval = 0; struct intelfb_info *dinfo = GET_DINFO(info); u32 pipe = 0; switch (cmd) { case FBIO_WAITFORVSYNC: if (get_user(pipe, (__u32 __user *)arg)) return -EFAULT; retval = intelfbhw_wait_for_vsync(dinfo, pipe); break; default: break; } return retval;}static void intelfb_fillrect (struct fb_info *info, const struct fb_fillrect *rect){ struct intelfb_info *dinfo = GET_DINFO(info); u32 rop, color;#if VERBOSE > 0 DBG_MSG("intelfb_fillrect\n");#endif if (!ACCEL(dinfo, info) || dinfo->depth == 4) { cfb_fillrect(info, rect); return; } if (rect->rop == ROP_COPY) rop = PAT_ROP_GXCOPY; else /* ROP_XOR */ rop = PAT_ROP_GXXOR; if (dinfo->depth != 8) color = dinfo->pseudo_palette[rect->color]; else color = rect->color; intelfbhw_do_fillrect(dinfo, rect->dx, rect->dy, rect->width, rect->height, color, dinfo->pitch, info->var.bits_per_pixel, rop);}static void intelfb_copyarea(struct fb_info *info, const struct fb_copyarea *region){ struct intelfb_info *dinfo = GET_DINFO(info);#if VERBOSE > 0 DBG_MSG("intelfb_copyarea\n");#endif if (!ACCEL(dinfo, info) || dinfo->depth == 4) { cfb_copyarea(info, region); return; } intelfbhw_do_bitblt(dinfo, region->sx, region->sy, region->dx, region->dy, region->width, region->height, dinfo->pitch, info->var.bits_per_pixel);}static void intelfb_imageblit(struct fb_info *info, const struct fb_image *image){ struct intelfb_info *dinfo = GET_DINFO(info); u32 fgcolor, bgcolor;#if VERBOSE > 0 DBG_MSG("intelfb_imageblit\n");#endif if (!ACCEL(dinfo, info) || dinfo->depth == 4 || image->depth != 1) { cfb_imageblit(info, image); return; } if (dinfo->depth != 8) { fgcolor = dinfo->pseudo_palette[image->fg_color]; bgcolor = dinfo->pseudo_palette[image->bg_color]; } else { fgcolor = image->fg_color; bgcolor = image->bg_color; } if (!intelfbhw_do_drawglyph(dinfo, fgcolor, bgcolor, image->width, image->height, image->data, image->dx, image->dy, dinfo->pitch, info->var.bits_per_pixel)) { cfb_imageblit(info, image); return; }}static int intelfb_cursor(struct fb_info *info, struct fb_cursor *cursor){ struct intelfb_info *dinfo = GET_DINFO(info); u32 physical;#if VERBOSE > 0 DBG_MSG("intelfb_cursor\n");#endif if (!dinfo->hwcursor) return -ENODEV; intelfbhw_cursor_hide(dinfo); /* If XFree killed the cursor - restore it */ physical = (dinfo->mobile || IS_I9XX(dinfo)) ? dinfo->cursor.physical : (dinfo->cursor.offset << 12); if (INREG(CURSOR_A_BASEADDR) != physical) { u32 fg, bg; DBG_MSG("the cursor was killed - restore it !!\n"); DBG_MSG("size %d, %d pos %d, %d\n", cursor->image.width, cursor->image.height, cursor->image.dx, cursor->image.dy); intelfbhw_cursor_init(dinfo); intelfbhw_cursor_reset(dinfo); intelfbhw_cursor_setpos(dinfo, cursor->image.dx, cursor->image.dy); if (dinfo->depth != 8) { fg =dinfo->pseudo_palette[cursor->image.fg_color]; bg =dinfo->pseudo_palette[cursor->image.bg_color]; } else { fg = cursor->image.fg_color; bg = cursor->image.bg_color; } intelfbhw_cursor_setcolor(dinfo, bg, fg); intelfbhw_cursor_load(dinfo, cursor->image.width, cursor->image.height, dinfo->cursor_src); if (cursor->enable) intelfbhw_cursor_show(dinfo); return 0; } if (cursor->set & FB_CUR_SETPOS) { u32 dx, dy; dx = cursor->image.dx - info->var.xoffset; dy = cursor->image.dy - info->var.yoffset; intelfbhw_cursor_setpos(dinfo, dx, dy); } if (cursor->set & FB_CUR_SETSIZE) { if (cursor->image.width > 64 || cursor->image.height > 64) return -ENXIO; intelfbhw_cursor_reset(dinfo); } if (cursor->set & FB_CUR_SETCMAP) { u32 fg, bg; if (dinfo->depth != 8) { fg = dinfo->pseudo_palette[cursor->image.fg_color]; bg = dinfo->pseudo_palette[cursor->image.bg_color]; } else { fg = cursor->image.fg_color; bg = cursor->image.bg_color; } intelfbhw_cursor_setcolor(dinfo, bg, fg); } if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETIMAGE)) { u32 s_pitch = (ROUND_UP_TO(cursor->image.width, 8) / 8); u32 size = s_pitch * cursor->image.height; u8 *dat = (u8 *) cursor->image.data; u8 *msk = (u8 *) cursor->mask; u8 src[64]; u32 i; if (cursor->image.depth != 1) return -ENXIO; switch (cursor->rop) { case ROP_XOR: for (i = 0; i < size; i++) src[i] = dat[i] ^ msk[i]; break; case ROP_COPY: default: for (i = 0; i < size; i++) src[i] = dat[i] & msk[i]; break; } /* save the bitmap to restore it when XFree will make the cursor dirty */ memcpy(dinfo->cursor_src, src, size); intelfbhw_cursor_load(dinfo, cursor->image.width, cursor->image.height, src); } if (cursor->enable) intelfbhw_cursor_show(dinfo); return 0;}static int intelfb_sync(struct fb_info *info){ struct intelfb_info *dinfo = GET_DINFO(info);#if VERBOSE > 0 DBG_MSG("intelfb_sync\n");#endif if (dinfo->ring_lockup) return 0; intelfbhw_do_sync(dinfo); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -