📄 intelfbdrv.c
字号:
DBG_MSG("intelfb_set_fbinfo\n"); info = &dinfo->info; strcpy(info->modename, dinfo->name); info->node = NODEV; info->flags = FBINFO_FLAG_DEFAULT; info->fbops = &intel_fb_ops; info->display_fg = NULL; info->changevar = NULL; info->switch_con = intelfb_switch; info->updatevar = intelfb_updatevar;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) info->blank = intelfbhw_do_blank;#endif if (intelfb_init_disp(dinfo)) return 1; return 0;}/* Update dinfo to match the active video mode. */static voidupdate_dinfo(struct intelfb_info *dinfo, struct fb_var_screeninfo *var, struct display *disp){ 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;#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) intelfb_get_fix(&dinfo->info.fix, dinfo->currcon, &dinfo->info);#endif switch (dinfo->bpp) {#ifdef FBCON_HAS_CFB8 case 8: dinfo->visual = FB_VISUAL_PSEUDOCOLOR; dinfo->pitch = disp->var.xres_virtual; break;#endif#ifdef FBCON_HAS_CFB16 case 16: dinfo->visual = FB_VISUAL_TRUECOLOR; dinfo->pitch = disp->var.xres_virtual * 2; break;#endif#ifdef FBCON_HAS_CFB32 case 32: dinfo->visual = FB_VISUAL_TRUECOLOR; dinfo->pitch = disp->var.xres_virtual * 4; break;#endif } /* Make sure the line length is a aligned correctly. */ dinfo->pitch = ROUND_UP_TO(dinfo->pitch, STRIDE_ALIGNMENT); if (dinfo->fixed_mode) dinfo->pitch = dinfo->initial_pitch;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) disp->screen_base = (char *)dinfo->fb_base; disp->visual = dinfo->visual; disp->line_length = dinfo->pitch; disp->type = FB_TYPE_PACKED_PIXELS; disp->type_aux = 0; disp->ypanstep = 1; disp->ywrapstep = 0;#else dinfo->info.screen_base = (char *)dinfo->fb_base; dinfo->info.fix.line_length = dinfo->pitch; dinfo->info.fix.visual = dinfo->visual;#endif disp->can_soft_blank = 1; disp->inverse = 0; DBG_MSG("disp->scrollmode is 0x%x\n", disp->scrollmode); if (disp->var.yres_virtual == disp->var.yres && !(disp->var.accel_flags & FB_ACCELF_TEXT)) { /* No space for panning. */ disp->scrollmode = SCROLL_YREDRAW; } else { disp->scrollmode = __SCROLL_YMOVE; }}/* fbops functions */static intintelfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info){ struct intelfb_info *dinfo = GET_DINFO(info); struct display *disp; DBG_MSG("intelfb_get_fix\n"); disp = GET_DISP(info, con); memset(fix, 0, sizeof(*fix)); strcpy(fix->id, dinfo->name); fix->smem_start = dinfo->fb_base_phys; fix->smem_len = dinfo->video_ram; fix->type = FB_TYPE_PACKED_PIXELS; fix->type_aux = 0; fix->visual = dinfo->visual; fix->xpanstep = 8; fix->ypanstep = 1; fix->ywrapstep = 0; fix->line_length = dinfo->pitch; fix->mmio_start = dinfo->mmio_base_phys; fix->mmio_len = INTEL_REG_SIZE; fix->accel = FB_ACCEL_NONE; return 0;}#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)static intintelfb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info){ struct intelfb_info *dinfo = GET_DINFO(info); DBG_MSG("intelfb_get_var\n"); if (con == -1) *var = dinfo->disp.var; else *var = fb_display[con].var; return 0;}#endifstatic intintelfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info){ struct display *disp; int change_var = 0; struct fb_var_screeninfo v; struct intelfb_info *dinfo; int ret; static int first = 1; DBG_MSG("intelfb_set_var: con is %d, accel_flags is %d\n", con, var->accel_flags); dinfo = GET_DINFO(info); disp = GET_DISP(info, con); if (intelfbhw_validate_mode(dinfo, con, var) != 0) return -EINVAL; memcpy(&v, var, sizeof(v)); /* Check for a supported bpp. */ if (v.bits_per_pixel <= 8) {#ifdef FBCON_HAS_CFB8 v.bits_per_pixel = 8;#else return -EINVAL;#endif } else if (v.bits_per_pixel <= 16) {#ifdef FBCON_HAS_CFB16 if (v.bits_per_pixel == 16) v.green.length = 6; v.bits_per_pixel = 16;#else return -EINVAL;#endif } else if (v.bits_per_pixel <= 32) {#ifdef FBCON_HAS_CFB32 v.bits_per_pixel = 32;#else return -EINVAL;#endif } else return -EINVAL; if (con < 0) {#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) info->var = *var;#endif return 0; } change_var = ((disp->var.xres != var->xres) || (disp->var.yres != var->yres) || (disp->var.xres_virtual != var->xres_virtual) || (disp->var.yres_virtual != var->yres_virtual) || (disp->var.bits_per_pixel != var->bits_per_pixel) || memcmp(&disp->var.red, &var->red, sizeof(var->red)) || memcmp(&disp->var.green, &var->green, sizeof(var->green)) || memcmp(&disp->var.blue, &var->blue, sizeof(var->blue))); if (dinfo->fixed_mode && (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; } if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) return 0; switch (intelfb_var_to_depth(&v)) {#ifdef FBCON_HAS_CFB8 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;#endif#ifdef FBCON_HAS_CFB16 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;#endif#ifdef FBCON_HAS_CFB32 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;#endif } 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;#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) info->var = v;#endif memcpy(&disp->var, &v, sizeof(v)); update_dinfo(dinfo, &v, disp); intelfb_set_dispsw(dinfo, disp); if (change_var) { if (info && info->changevar) info->changevar(con); } intelfb_blank(1, info);#if 0 if (dinfo->hwcursor) intelfbhw_cursor_hide(dinfo);#endif intelfbhw_2d_stop(dinfo); if (!dinfo->fixed_mode) { mdelay(100); if ((ret = intelfb_set_mode(dinfo, &v, disp, 1))) return ret; mdelay(100); } if (dinfo->vc_mode == KD_TEXT) { intelfb_do_install_cmap(con, info); if (dinfo->hwcursor) { del_timer(&dinfo->cursor.timer); dinfo->cursor.state = CM_ERASE; if (disp->conp) { intelfbhw_cursor_init(dinfo); intelfbhw_cursor_load(dinfo, disp); dinfo->cursor.redraw = 1; } } mdelay(100); intelfbhw_2d_start(dinfo);#if 0 if (dinfo->hwcursor) intelfbhw_cursor_show(dinfo);#endif if (v.yoffset != 0) intelfbhw_pan_display(&v, con, info); } else { dinfo->cursor.enabled = 0; } intelfb_blank(0, info); return 0;}static intintelfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info){ struct intelfb_info *dinfo = GET_DINFO(info); struct display *disp = GET_DISP(info, con); DBG_MSG("intelfb_get_cmap: con = %d, bpp = %d\n", con, disp->var.bits_per_pixel); if (con == dinfo->currcon) return fb_get_cmap(cmap, kspc, intelfb_getcolreg, info); else if (disp->cmap.len) fb_copy_cmap(&disp->cmap, cmap, kspc ? 0 : 2); else { int cmap_len = (disp->var.bits_per_pixel > 8) ? 16 : 256; fb_copy_cmap(fb_default_cmap(cmap_len), cmap, kspc ? 0 : 2); } return 0;}static intintelfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info){ struct intelfb_info *dinfo = GET_DINFO(info); struct display *disp = GET_DISP(info, con); unsigned int cmap_len; int err; DBG_MSG("intelfb_set_cmap: con = %d, bpp = %d\n", con, disp->var.bits_per_pixel); cmap_len = (disp->var.bits_per_pixel > 8) ? 16 : 256; if (!disp->cmap.len) { err = fb_alloc_cmap(&disp->cmap, cmap_len, 0); if (err) return err; } if (con == dinfo->currcon) return FB_SET_CMAP(cmap, kspc, intelfb_setcolreg, info); else fb_copy_cmap(cmap, &disp->cmap, kspc ? 0 : 1); return 0;}/* When/if we have our own ioctls. */static intintelfb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg, int con, struct fb_info *info){ DBG_MSG("intelfb_ioctl\n"); return -EINVAL;}static intintelfb_switch(int con, struct fb_info *info){ struct intelfb_info *dinfo = GET_DINFO(info); struct display *disp; struct fb_cmap *cmap; int switchmode = 0; DBG_MSG("intelfb_switch: con = %d, currcon = %d\n", con, dinfo->currcon); disp = GET_DISP(info, con); if (dinfo->currcon >= 0) { cmap = &dinfo->currcon_display->cmap; if (cmap->len) fb_get_cmap(cmap, 1, intelfb_getcolreg, info); } switchmode = (con != dinfo->currcon); dinfo->currcon = con; dinfo->vc_mode = con >= 0 ? vt_cons[con]->vc_mode : KD_TEXT; dinfo->currcon_display = disp; disp->var.activate = FB_ACTIVATE_NOW; if (switchmode) { intelfb_set_var(&disp->var, con, info); intelfb_do_install_cmap(con, info); } return 0;}/* Called whenever there's panning. */static intintelfb_updatevar(int con, struct fb_info *info){ struct display *disp = GET_DISP(info, con); DBG_MSG("intelfb_updatevar\n"); if (con < 0) return -EINVAL; else return intelfbhw_pan_display(&disp->var, con, info);}static intintelfb_blank(int blank, struct fb_info *info){ intelfbhw_do_blank(blank, info); return 0;}static intintelfb_getcolreg(unsigned regno, unsigned *red, unsigned *green, unsigned *blue, unsigned *transp, struct fb_info *info){ struct intelfb_info *dinfo = GET_DINFO(info);#if 0 DBG_MSG("intelfb_getcolreg\n");#endif if (regno > 255) return 1; *red = (dinfo->palette[regno].red<<8) | dinfo->palette[regno].red; *green = (dinfo->palette[regno].green<<8) | dinfo->palette[regno].green; *blue = (dinfo->palette[regno].blue<<8) | dinfo->palette[regno].blue; *transp = 0; return 0;}static intintelfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info){ struct intelfb_info *dinfo = GET_DINFO(info);#if 1 DBG_MSG("intelfb_setcolreg: regno %d, depth %d\n", regno, dinfo->depth);#endif if ((dinfo->depth > 8 && regno > 16) || regno > 255) return 1; switch (dinfo->depth) {#ifdef FBCON_HAS_CFB8 case 8: { red >>= 8; green >>= 8; blue >>= 8; dinfo->palette[regno].red = red; dinfo->palette[regno].green = green; dinfo->palette[regno].blue = blue; intelfbhw_setcolreg(dinfo, regno, red, green, blue, transp); } break;#endif#ifdef FBCON_HAS_CFB16 case 15: dinfo->con_cmap.cfb16[regno] = ((red & 0xf800) >> 1) | ((green & 0xf800) >> 6) | ((blue & 0xf800) >> 11); break; case 16: dinfo->con_cmap.cfb16[regno] = (red & 0xf800) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11); break;#endif#ifdef FBCON_HAS_CFB32 case 24: dinfo->con_cmap.cfb32[regno] = ((red & 0xff00) << 8) | (green & 0xff00) | ((blue & 0xff00) >> 8); break;#endif } return 0;}/* Convert a mode to a var, also making the bpp a supported value. */static voidmode_to_var(const struct fb_videomode *mode, struct fb_var_screeninfo *var, u32 bpp){ if (!mode || !var) return; var->xres = mode->xres; var->yres = mode->yres; var->xres_virtual = mode->xres; var->yres_virtual = mode->yres; var->xoffset = 0; var->yoffset = 0; if (bpp <= 8) var->bits_per_pixel = 8; else if (bpp <= 16) { if (bpp == 16) var->green.length = 6; var->bits_per_pixel = 16; } else if (bpp <= 32) var->bits_per_pixel = 32; else { WRN_MSG("var_to_mode: bad bpp: %d\n", bpp); var->bits_per_pixel = bpp; } var->pixclock = mode->pixclock; var->left_margin = mode->left_margin; var->right_margin = mode->right_margin; var->upper_margin = mode->upper_margin; var->lower_margin = mode->lower_margin; var->hsync_len = mode->hsync_len; var->vsync_len = mode->vsync_len; var->sync = mode->sync; var->vmode = mode->vmode; var->width = -1; var->height = -1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -