📄 atyfb_base.c
字号:
else par->accel_flags = 0;#if 0 /* fbmon is not done. uncomment for 2.5.x -brad */ if (!fbmon_valid_timings(pixclock, htotal, vtotal, info)) return -EINVAL;#endif return 0;}static int atyfb_encode_var(struct fb_var_screeninfo *var, const struct atyfb_par *par, const struct fb_info_aty *info){ int err; memset(var, 0, sizeof(struct fb_var_screeninfo)); if ((err = aty_crtc_to_var(&par->crtc, var))) return err; var->pixclock = info->pll_ops->pll_to_var(info, &par->pll); var->height = -1; var->width = -1; var->accel_flags = par->accel_flags; return 0;}static void set_off_pitch(struct atyfb_par *par, const struct fb_info_aty *info){ u32 xoffset = par->crtc.xoffset; u32 yoffset = par->crtc.yoffset; u32 vxres = par->crtc.vxres; u32 bpp = par->crtc.bpp; par->crtc.off_pitch = ((yoffset*vxres+xoffset)*bpp/64) | (vxres<<19); aty_st_le32(CRTC_OFF_PITCH, par->crtc.off_pitch, info);} /* * Open/Release the frame buffer device */static int atyfb_open(struct fb_info *info, int user){#ifdef __sparc__ struct fb_info_aty *fb = (struct fb_info_aty *)info; if (user) { fb->open++; fb->mmaped = 0; fb->vtconsole = -1; } else { fb->consolecnt++; }#endif return(0);}struct fb_var_screeninfo default_var = { /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */ 640, 480, 640, 480, 0, 0, 8, 0, {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, 0, 0, -1, -1, 0, 39722, 48, 16, 33, 10, 96, 2, 0, FB_VMODE_NONINTERLACED};static int atyfb_release(struct fb_info *info, int user){#ifdef __sparc__ struct fb_info_aty *fb = (struct fb_info_aty *)info; if (user) { fb->open--; mdelay(1); wait_for_idle(fb); if (!fb->open) { int was_mmaped = fb->mmaped; fb->mmaped = 0; if (fb->vtconsole != -1) vt_cons[fb->vtconsole]->vc_mode = KD_TEXT; fb->vtconsole = -1; if (was_mmaped) { struct fb_var_screeninfo var; /* Now reset the default display config, we have no * idea what the program(s) which mmap'd the chip did * to the configuration, nor whether it restored it * correctly. */ var = default_var; if (noaccel) var.accel_flags &= ~FB_ACCELF_TEXT; else var.accel_flags |= FB_ACCELF_TEXT; if (var.yres == var.yres_virtual) { u32 vram = (fb->total_vram - (PAGE_SIZE << 2)); var.yres_virtual = ((vram * 8) / var.bits_per_pixel) / var.xres_virtual; if (var.yres_virtual < var.yres) var.yres_virtual = var.yres; } atyfb_set_var(&var, -1, &fb->fb_info); } } } else { fb->consolecnt--; }#endif return(0);}static int encode_fix(struct fb_fix_screeninfo *fix, const struct atyfb_par *par, const struct fb_info_aty *info){ memset(fix, 0, sizeof(struct fb_fix_screeninfo)); strcpy(fix->id, atyfb_name); fix->smem_start = info->frame_buffer_phys; fix->smem_len = (u32)info->total_vram; /* * Reg Block 0 (CT-compatible block) is at ati_regbase_phys * Reg Block 1 (multimedia extensions) is at ati_regbase_phys-0x400 */ if (M64_HAS(GX)) { fix->mmio_start = info->ati_regbase_phys; fix->mmio_len = 0x400; fix->accel = FB_ACCEL_ATI_MACH64GX; } else if (M64_HAS(CT)) { fix->mmio_start = info->ati_regbase_phys; fix->mmio_len = 0x400; fix->accel = FB_ACCEL_ATI_MACH64CT; } else if (M64_HAS(VT)) { fix->mmio_start = info->ati_regbase_phys-0x400; fix->mmio_len = 0x800; fix->accel = FB_ACCEL_ATI_MACH64VT; } else /* if (M64_HAS(GT)) */ { fix->mmio_start = info->ati_regbase_phys-0x400; fix->mmio_len = 0x800; fix->accel = FB_ACCEL_ATI_MACH64GT; } fix->type = FB_TYPE_PACKED_PIXELS; fix->type_aux = 0; fix->line_length = par->crtc.vxres*par->crtc.bpp/8; fix->visual = par->crtc.bpp <= 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR; fix->ywrapstep = 0; fix->xpanstep = 8; fix->ypanstep = 1; return 0;} /* * Get the Fixed Part of the Display */static int atyfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *fb){ const struct fb_info_aty *info = (struct fb_info_aty *)fb; struct atyfb_par par; if (con == -1) par = info->default_par; else /* The monitors_enabled information is not important for the calculation of the information in par that encode_fix needs, so we pass a 0. */ atyfb_decode_var(&fb_display[con].var, &par, info, 0); encode_fix(fix, &par, info); return 0;} /* * Get the User Defined Part of the Display */static int atyfb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *fb){ const struct fb_info_aty *info = (struct fb_info_aty *)fb; if (con == -1) atyfb_encode_var(var, &info->default_par, info); else *var = fb_display[con].var; return 0;}static void atyfb_set_dispsw(struct display *disp, struct fb_info_aty *info, int bpp, int accel){ switch (bpp) {#ifdef FBCON_HAS_CFB8 case 8: info->dispsw = accel ? fbcon_aty8 : fbcon_cfb8; disp->dispsw = &info->dispsw; break;#endif#ifdef FBCON_HAS_CFB16 case 16: info->dispsw = accel ? fbcon_aty16 : fbcon_cfb16; disp->dispsw = &info->dispsw; disp->dispsw_data = info->fbcon_cmap.cfb16; break;#endif#ifdef FBCON_HAS_CFB24 case 24: info->dispsw = accel ? fbcon_aty24 : fbcon_cfb24; disp->dispsw = &info->dispsw; disp->dispsw_data = info->fbcon_cmap.cfb24; break;#endif#ifdef FBCON_HAS_CFB32 case 32: info->dispsw = accel ? fbcon_aty32 : fbcon_cfb32; disp->dispsw = &info->dispsw; disp->dispsw_data = info->fbcon_cmap.cfb32; break;#endif default: disp->dispsw = &fbcon_dummy; }#ifdef CONFIG_FB_ATY_CT if (info->cursor) { info->dispsw.cursor = atyfb_cursor; info->dispsw.set_font = atyfb_set_font; }#endif /* CONFIG_FB_ATY_CT */} /* * In the display mode set code we need to make desisions depending on * wether the LCD or CRT monitor is enabled. * This is going to give problems in the unlikely case that someone * for example turns on the LCD monitor just after we tested what * monitors are enabled. Since the consequences are very serious * (the graphic card crashes and sends the wrong signals to the lcd * monitor which gets brighter and brighter; to prevent it from * damage the computer must be switched off as soon as possible) * we need to prevent this. * * As far as I know there is no way to prevent people switching on the * LCD monitor while we are programming the video card. So the best way * to do it, is detect what monitors are enabled before programming the * video chip. After programming the video chip, we write this information * back to the video chip, switching the LCD off again if someone enabled * it. But isn't the card already crashed before we have the chance to * turn the display back off? I don't think so because the CRTC is disabled * while we program it. */#ifdef CONFIG_FB_ATY_GENERIC_LCDstatic u32 atyfb_monitors_enabled(struct fb_info_aty *info) { if (info->lcd_table != 0) { return aty_ld_lcd(LCD_GEN_CTRL, info) & 3; }; return 0;};#else#define atyfb_monitors_enabled(info) 0#endif /* * Set the User Defined Part of the Display */static int atyfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *fb){ struct fb_info_aty *info = (struct fb_info_aty *)fb; struct atyfb_par par; struct display *display; int oldxres, oldyres, oldvxres, oldvyres, oldbpp, oldaccel, accel, err; int activate = var->activate; u32 monitors_enabled; if (con >= 0) display = &fb_display[con]; else display = fb->disp; /* used during initialization */ monitors_enabled = atyfb_monitors_enabled(info); /* * We have to be very carefull with encode_var for LCD_panels. Fbdev * applications do not know about LCD monitors. We have to make them * think they are using a CRT. That means that alltough the video * chip is programmed for the resolution of the LCD monitor (say 800x600), * the applications expect the mode they asked for, say 640x480 * * So when a program asks for 640x480, atyfb_decode_var sets the crtc * registers for 800x600. Then atyfb_encode_var calculates the crtc * registers back into the var variable, but now the var variable * will contain wrong values for 800x600! Result: wrong information is * returned to the program! * * To counter this, we call atyfb_decode_var first like if there is no * lcd monitor switched on. Then we call atyfb_decode_var. Now * the correct information is returned to the program, but the values * for the crtc registers are not suited for the LCD monitor. We call * atyfb_decode_var again to calculate the registers again, this time * with the right monitors_enabled. */ if ((err = atyfb_decode_var(var, &par, info, CRT_ON))) return err; atyfb_encode_var(var, &par, (struct fb_info_aty *)info);#ifdef CONFIG_FB_ATY_GENERIC_LCD if ((err = atyfb_decode_var(var, &par, info, monitors_enabled))) return err;#endif if ((activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) { oldxres = display->var.xres; oldyres = display->var.yres; oldvxres = display->var.xres_virtual; oldvyres = display->var.yres_virtual; oldbpp = display->var.bits_per_pixel; oldaccel = display->var.accel_flags; display->var = *var; accel = var->accel_flags & FB_ACCELF_TEXT; if (oldxres != var->xres || oldyres != var->yres || oldvxres != var->xres_virtual || oldvyres != var->yres_virtual || oldbpp != var->bits_per_pixel || oldaccel != var->accel_flags) { struct fb_fix_screeninfo fix; encode_fix(&fix, &par, info); display->screen_base = (char *)info->frame_buffer; display->visual = fix.visual; display->type = fix.type; display->type_aux = fix.type_aux; display->ypanstep = fix.ypanstep; display->ywrapstep = fix.ywrapstep; display->line_length = fix.line_length; display->can_soft_blank = 1; display->inverse = 0; if (accel) display->scrollmode = (info->bus_type == PCI) ? SCROLL_YNOMOVE : 0; else display->scrollmode = SCROLL_YREDRAW; if (info->fb_info.changevar) (*info->fb_info.changevar)(con);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -