📄 neofb.c
字号:
default: break; } par->ExtCRTDispAddr = 0x10; /* Vertical Extension */ par->VerticalExt = (((timings.VTotal -2) & 0x400) >> 10 ) | (((timings.VDisplay -1) & 0x400) >> 9 ) | (((timings.VSyncStart) & 0x400) >> 8 ) | (((timings.VSyncStart) & 0x400) >> 7 ); /* Fast write bursts on unless disabled. */ if (info->pci_burst) par->SysIfaceCntl1 = 0x30; else par->SysIfaceCntl1 = 0x00; par->SysIfaceCntl2 = 0xc0; /* VESA Bios sets this to 0x80! */ /* Enable any user specified display devices. */ par->PanelDispCntlReg1 = 0x00; if (info->internal_display) par->PanelDispCntlReg1 |= 0x02; if (info->external_display) par->PanelDispCntlReg1 |= 0x01; /* If the user did not specify any display devices, then... */ if (par->PanelDispCntlReg1 == 0x00) { /* Default to internal (i.e., LCD) only. */ par->PanelDispCntlReg1 |= 0x02; } /* If we are using a fixed mode, then tell the chip we are. */ switch (var->xres) { case 1280: par->PanelDispCntlReg1 |= 0x60; break; case 1024: par->PanelDispCntlReg1 |= 0x40; break; case 800: par->PanelDispCntlReg1 |= 0x20; break; case 640: default: break; } /* Setup shadow register locking. */ switch (par->PanelDispCntlReg1 & 0x03) { case 0x01: /* External CRT only mode: */ par->GeneralLockReg = 0x00; /* We need to program the VCLK for external display only mode. */ par->ProgramVCLK = 1; break; case 0x02: /* Internal LCD only mode: */ case 0x03: /* Simultaneous internal/external (LCD/CRT) mode: */ par->GeneralLockReg = 0x01; /* Don't program the VCLK when using the LCD. */ par->ProgramVCLK = 0; break; } /* * If the screen is to be stretched, turn on stretching for the * various modes. * * OPTION_LCD_STRETCH means stretching should be turned off! */ par->PanelDispCntlReg2 = 0x00; par->PanelDispCntlReg3 = 0x00; if (info->lcd_stretch && (par->PanelDispCntlReg1 == 0x02) && /* LCD only */ (var->xres != info->NeoPanelWidth)) { switch (var->xres) { case 320: /* Needs testing. KEM -- 24 May 98 */ case 400: /* Needs testing. KEM -- 24 May 98 */ case 640: case 800: case 1024: lcd_stretch = 1; par->PanelDispCntlReg2 |= 0xC6; break; default: lcd_stretch = 0; /* No stretching in these modes. */ } } else lcd_stretch = 0; /* * If the screen is to be centerd, turn on the centering for the * various modes. */ par->PanelVertCenterReg1 = 0x00; par->PanelVertCenterReg2 = 0x00; par->PanelVertCenterReg3 = 0x00; par->PanelVertCenterReg4 = 0x00; par->PanelVertCenterReg5 = 0x00; par->PanelHorizCenterReg1 = 0x00; par->PanelHorizCenterReg2 = 0x00; par->PanelHorizCenterReg3 = 0x00; par->PanelHorizCenterReg4 = 0x00; par->PanelHorizCenterReg5 = 0x00; if (par->PanelDispCntlReg1 & 0x02) { if (var->xres == info->NeoPanelWidth) { /* * No centering required when the requested display width * equals the panel width. */ } else { par->PanelDispCntlReg2 |= 0x01; par->PanelDispCntlReg3 |= 0x10; /* Calculate the horizontal and vertical offsets. */ if (!lcd_stretch) { hoffset = ((info->NeoPanelWidth - var->xres) >> 4) - 1; voffset = ((info->NeoPanelHeight - var->yres) >> 1) - 2; } else { /* Stretched modes cannot be centered. */ hoffset = 0; voffset = 0; } switch (var->xres) { case 320: /* Needs testing. KEM -- 24 May 98 */ par->PanelHorizCenterReg3 = hoffset; par->PanelVertCenterReg2 = voffset; break; case 400: /* Needs testing. KEM -- 24 May 98 */ par->PanelHorizCenterReg4 = hoffset; par->PanelVertCenterReg1 = voffset; break; case 640: par->PanelHorizCenterReg1 = hoffset; par->PanelVertCenterReg3 = voffset; break; case 800: par->PanelHorizCenterReg2 = hoffset; par->PanelVertCenterReg4 = voffset; break; case 1024: par->PanelHorizCenterReg5 = hoffset; par->PanelVertCenterReg5 = voffset; break; case 1280: default: /* No centering in these modes. */ break; } } } par->biosMode = neoFindMode (var->xres, var->yres, var->bits_per_pixel); /* * Calculate the VCLK that most closely matches the requested dot * clock. */ neoCalcVCLK (info, par, timings.pixclock); /* Since we program the clocks ourselves, always use VCLK3. */ par->MiscOutReg |= 0x0C; return 0;}static int neofb_set_var (struct fb_var_screeninfo *var, int con, struct fb_info *fb){ struct neofb_info *info = (struct neofb_info *)fb; struct display *display; struct neofb_par par; int err, chgvar = 0; DBG("neofb_set_var"); err = neofb_decode_var (var, info, &par); if (err) return err; if (var->activate & FB_ACTIVATE_TEST) return 0; if (con < 0) { display = fb->disp; chgvar = 0; } else { display = fb_display + con; if (fb->var.xres != var->xres) chgvar = 1; if (fb->var.yres != var->yres) chgvar = 1; if (fb->var.xres_virtual != var->xres_virtual) chgvar = 1; if (fb->var.yres_virtual != var->yres_virtual) chgvar = 1; if (fb->var.bits_per_pixel != var->bits_per_pixel) chgvar = 1; } if (!info->neo2200) var->accel_flags &= ~FB_ACCELF_TEXT; var->red.msb_right = 0; var->green.msb_right = 0; var->blue.msb_right = 0; switch (var->bits_per_pixel) {#ifdef FBCON_HAS_CFB8 case 8: /* PSEUDOCOLOUR, 256 */ var->transp.offset = 0; var->transp.length = 0; var->red.offset = 0; var->red.length = 8; var->green.offset = 0; var->green.length = 8; var->blue.offset = 0; var->blue.length = 8; fb->fix.visual = FB_VISUAL_PSEUDOCOLOR; info->dispsw = &fbcon_cfb8; display->dispsw_data = NULL; display->next_line = var->xres_virtual; break;#endif#ifdef FBCON_HAS_CFB16 case 16: /* DIRECTCOLOUR, 64k */ var->transp.offset = 0; var->transp.length = 0; var->red.offset = 11; var->red.length = 5; var->green.offset = 5; var->green.length = 6; var->blue.offset = 0; var->blue.length = 5; fb->fix.visual = FB_VISUAL_DIRECTCOLOR; info->dispsw = &fbcon_cfb16; display->dispsw_data = fb->pseudo_palette; display->next_line = var->xres_virtual * 2; break;#endif#ifdef FBCON_HAS_CFB24 case 24: /* TRUECOLOUR, 16m */ var->transp.offset = 0; var->transp.length = 0; var->red.offset = 16; var->red.length = 8; var->green.offset = 8; var->green.length = 8; var->blue.offset = 0; var->blue.length = 8; fb->fix.visual = FB_VISUAL_TRUECOLOR; info->dispsw = &fbcon_cfb24; display->dispsw_data = fb->pseudo_palette; display->next_line = var->xres_virtual * 3; var->accel_flags &= ~FB_ACCELF_TEXT; break;#endif#ifdef NO_32BIT_SUPPORT_YET# ifdef FBCON_HAS_CFB32 case 32: /* TRUECOLOUR, 16m */ var->transp.offset = 24; var->transp.length = 8; var->red.offset = 16; var->red.length = 8; var->green.offset = 8; var->green.length = 8; var->blue.offset = 0; var->blue.length = 8; fb->fix.visual = FB_VISUAL_TRUECOLOR; info->dispsw = &fbcon_cfb32; display->dispsw_data = fb->pseudo_palette; display->next_line = var->xres_virtual * 4; var->accel_flags &= ~FB_ACCELF_TEXT; break;# endif#endif default: printk (KERN_WARNING "neofb: no support for %dbpp\n", var->bits_per_pixel); info->dispsw = &fbcon_dummy; var->accel_flags &= ~FB_ACCELF_TEXT; break; } if (var->accel_flags & FB_ACCELF_TEXT) display->dispsw = &fbcon_neo2200_accel; else display->dispsw = info->dispsw; fb->fix.line_length = display->next_line; display->screen_base = fb->screen_base; display->line_length = fb->fix.line_length; display->visual = fb->fix.visual; display->type = fb->fix.type; display->type_aux = fb->fix.type_aux; display->ypanstep = fb->fix.ypanstep; display->ywrapstep = fb->fix.ywrapstep; display->can_soft_blank = 1; display->inverse = 0; fb->var = *var; fb->var.activate &= ~FB_ACTIVATE_ALL; /* * Update the old var. The fbcon drivers still use this. * Once they are using cfb->fb.var, this can be dropped. * --rmk */ display->var = fb->var; /* * If we are setting all the virtual consoles, also set the * defaults used to create new consoles. */ if (var->activate & FB_ACTIVATE_ALL) fb->disp->var = fb->var; if (chgvar && fb && fb->changevar) fb->changevar (con); if (con == info->currcon) { if (chgvar || con < 0) neofb_set_par (info, &par); neofb_update_start (info, var); fb_set_cmap (&fb->cmap, 1, neo_setcolreg, fb); if (var->accel_flags & FB_ACCELF_TEXT) neo2200_accel_init (info, var); } return 0;}/* * Pan or Wrap the Display */static int neofb_pan_display (struct fb_var_screeninfo *var, int con, struct fb_info *fb){ struct neofb_info *info = (struct neofb_info *)fb; u_int y_bottom; y_bottom = var->yoffset; if (!(var->vmode & FB_VMODE_YWRAP)) y_bottom += var->yres; if (var->xoffset > (var->xres_virtual - var->xres)) return -EINVAL; if (y_bottom > fb->var.yres_virtual) return -EINVAL; neofb_update_start (info, var); fb->var.xoffset = var->xoffset; fb->var.yoffset = var->yoffset; if (var->vmode & FB_VMODE_YWRAP) fb->var.vmode |= FB_VMODE_YWRAP; else fb->var.vmode &= ~FB_VMODE_YWRAP; return 0;}/* * Update the `var' structure (called by fbcon.c) * * This call looks only at yoffset and the FB_VMODE_YWRAP flag in `var'. * Since it's called by a kernel driver, no range checking is done. */static int neofb_updatevar (int con, struct fb_info *fb){ struct neofb_info *info = (struct neofb_info *)fb; neofb_update_start (info, &fb_display[con].var); return 0;}static int neofb_switch (int con, struct fb_info *fb){ struct neofb_info *info = (struct neofb_info *)fb; struct display *disp; struct fb_cmap *cmap; if (info->currcon >= 0) { disp = fb_display + info->currcon; /* * Save the old colormap and video mode. */ disp->var = fb->var; if (disp->cmap.len) fb_copy_cmap(&fb->cmap, &disp->cmap, 0); } info->currcon = con; disp = fb_display + con; /* * Install the new colormap and change the video mode. By default, * fbcon sets all the colormaps and video modes to the default * values at bootup. * * Really, we want to set the colourmap size depending on the * depth of the new video mode. For now, we leave it at its * default 256 entry. */ if (disp->cmap.len) cmap = &disp->cmap; else cmap = fb_default_cmap(1 << disp->var.bits_per_pixel); fb_copy_cmap(cmap, &fb->cmap, 0); disp->var.activate = FB_ACTIVATE_NOW; neofb_set_var(&disp->var, con, fb); return 0;}/* * (Un)Blank the display. */static void neofb_blank (int blank, struct fb_info *fb){ // struct neofb_info *info = (struct neofb_info *)fb; /* * Blank the screen if blank_mode != 0, else unblank. If * blank == NULL then the caller blanks by setting the CLUT * (Color Look Up Table) to all black. Return 0 if blanking * succeeded, != 0 if un-/blanking failed due to e.g. a * video mode which doesn't support it. Implements VESA * suspend and powerdown modes on hardware that supports * disabling hsync/vsync: * blank_mode == 2: suspend vsync * blank_mode == 3: suspend hsync * blank_mode == 4: powerdown * * wms...Enable VESA DMPS compatible powerdown mode * run "setterm -powersave powerdown" to take advantage */ switch (blank) { case 4: /* powerdown - both sync lines down */ break; case 3: /* hsync off */ break; case 2: /* vsync off */ break; case 1: /* just software blanking of screen */ break; default: /* case 0, or anything else: unblank */ break; }}/* * Get the currently displayed virtual consoles colormap. */static int gen_get_cmap (struct fb_cmap *cmap, int kspc, int con, struct fb_info *fb){ fb_copy_cmap (&fb->cmap, cmap, kspc ? 0 : 2); return 0;}/* * Get the currently displayed virtual consoles fixed part of the display. */static int gen_get_fix (struct fb_fix_screeninfo *fix, int con, struct fb_info *fb){ *fix = fb->fix; return 0;}/* * Get the current user defined part of the display. */static int gen_get_var (struct fb_var_screeninfo *var, int con, struct fb_info *fb){ *var = fb->var; return 0;}static struct fb_ops neofb_ops = { owner: THIS_MODULE, fb_set_var: neofb_set_var, fb_set_cmap: neofb_set_cmap, fb_pan_display: neofb_pan_display, fb_get_fix: gen_get_fix, fb_get_var: gen_get_var, fb_get_cmap: gen_get_cmap,};/* --------------------------------------------------------------------- */static struct fb_var_screeninfo __devinitdata neofb_var640x480x8 = { accel_flags: FB_ACCELF_TEXT, xres: 640, yres: 480, xres_virtual: 640, yres_virtual: 30000, bits_per_pixel: 8, pixclock: 39722, left_margin: 48, right_margin: 16, upper_margin: 33, lower_margin: 10, hsync_len: 96, vsync_len: 2, sync: 0, vmode: FB_VMODE_NONINTERLACED};static struct fb_var_screeninfo __devinitdata neofb_var800x600x8 = { accel_flags: FB_ACCELF_TEXT, xres: 800, yres: 600, xres_virtual: 800, yres_virtual: 30000, bits_per_pixel: 8, pixclock: 25000, left_margin: 88, right_margin: 40, upper_margin: 23, lower_margin: 1, hsync_len: 128, vsync_len: 4, sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, vmode: FB_VMODE_NONINTERLACED};static struct fb_var_screeninfo __devinitdata neofb_var1024x768x8 = { accel_flags: FB_ACCELF_TEXT, xres: 1024, yres: 768, xres_virtual: 1024, yres_virtual: 30000, bits_per_pixel: 8, pixclock: 15385, left_margin: 160, right_margin: 24, upper_margin: 29, lower_margin: 3, hsync_len: 136, vsync_len: 6, sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, vmode: FB_VMODE_NONINTERLACED};#ifdef NOT_DONEstatic struct fb_var_screeninfo __devinitdata neofb_var1280x1024x8 = { accel_flags: FB_ACCELF_TEXT, xres: 1280, yres: 1024, xres_virtual: 1280, yres_virtual: 30000, bits_per_pixel: 8, pixclock: 9260, left_margin: 248, right_margin: 48, upper_margin: 38, lower_margin: 1, hsync_len: 112, vsync_len: 3, sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -