📄 atafb.c
字号:
(hfreq * 2) / (par->VFT + 1 + 4 * lines) > fb_info.monspecs.vfmax; lines += 2) ; upper_margin += lines; lower_margin += lines; goto again; } else if (vfreq > fb_info.monspecs.vfmax && interlace) { /* Interlace, too high -> enlarge margins */ int lines; for (lines = 0; (hfreq * 2) / (par->VFT + 1 + 4 * lines) > fb_info.monspecs.vfmax; lines++) ; upper_margin += lines; lower_margin += lines; goto again; } else if (vfreq < fb_info.monspecs.vfmin || vfreq > fb_info.monspecs.vfmax) return -EINVAL;set_screen_base: linelen = xres_virtual * bpp / 8; if (yres_virtual * linelen > screen_len && screen_len) return -EINVAL; if (yres * linelen > screen_len && screen_len) return -EINVAL; if (var->yoffset + yres > yres_virtual && yres_virtual) return -EINVAL; par->yres_virtual = yres_virtual; par->screen_base = screen_base + var->yoffset * linelen; par->hw.falcon.xoffset = 0; par->next_line = linelen; return 0;}static int falcon_encode_var(struct fb_var_screeninfo *var, struct atafb_par *par){/* !!! only for VGA !!! */ int linelen; int prescale, plen; int hdb_off, hde_off, base_off; struct falcon_hw *hw = &par->hw.falcon; memset(var, 0, sizeof(struct fb_var_screeninfo)); /* possible frequencies: 25.175 or 32MHz */ var->pixclock = hw->sync & 0x1 ? fext.t : hw->vid_control & VCO_CLOCK25 ? f25.t : f32.t; var->height = -1; var->width = -1; var->sync = 0; if (hw->vid_control & VCO_HSYPOS) var->sync |= FB_SYNC_HOR_HIGH_ACT; if (hw->vid_control & VCO_VSYPOS) var->sync |= FB_SYNC_VERT_HIGH_ACT; var->vmode = FB_VMODE_NONINTERLACED; if (hw->vid_mode & VMO_INTER) var->vmode |= FB_VMODE_INTERLACED; if (hw->vid_mode & VMO_DOUBLE) var->vmode |= FB_VMODE_DOUBLE; /* visible y resolution: * Graphics display starts at line VDB and ends at line * VDE. If interlace mode off unit of VC-registers is * half lines, else lines. */ var->yres = hw->vde - hw->vdb; if (!(var->vmode & FB_VMODE_INTERLACED)) var->yres >>= 1; if (var->vmode & FB_VMODE_DOUBLE) var->yres >>= 1; /* * to get bpp, we must examine f_shift and st_shift. * f_shift is valid if any of bits no. 10, 8 or 4 * is set. Priority in f_shift is: 10 ">" 8 ">" 4, i.e. * if bit 10 set then bit 8 and bit 4 don't care... * If all these bits are 0 get display depth from st_shift * (as for ST and STE) */ if (hw->f_shift & 0x400) /* 2 colors */ var->bits_per_pixel = 1; else if (hw->f_shift & 0x100) /* hicolor */ var->bits_per_pixel = 16; else if (hw->f_shift & 0x010) /* 8 bitplanes */ var->bits_per_pixel = 8; else if (hw->st_shift == 0) var->bits_per_pixel = 4; else if (hw->st_shift == 0x100) var->bits_per_pixel = 2; else /* if (hw->st_shift == 0x200) */ var->bits_per_pixel = 1; var->xres = hw->line_width * 16 / var->bits_per_pixel; var->xres_virtual = var->xres + hw->line_offset * 16 / var->bits_per_pixel; if (hw->xoffset) var->xres_virtual += 16; if (var->bits_per_pixel == 16) { var->red.offset = 11; var->red.length = 5; var->red.msb_right = 0; var->green.offset = 5; var->green.length = 6; var->green.msb_right = 0; var->blue.offset = 0; var->blue.length = 5; var->blue.msb_right = 0; } else { var->red.offset = 0; var->red.length = hw->ste_mode ? 4 : 6; if (var->red.length > var->bits_per_pixel) var->red.length = var->bits_per_pixel; var->red.msb_right = 0; var->grayscale = 0; var->blue = var->green = var->red; } var->transp.offset = 0; var->transp.length = 0; var->transp.msb_right = 0; linelen = var->xres_virtual * var->bits_per_pixel / 8; if (screen_len) { if (par->yres_virtual) var->yres_virtual = par->yres_virtual; else /* yres_virtual == 0 means use maximum */ var->yres_virtual = screen_len / linelen; } else { if (hwscroll < 0) var->yres_virtual = 2 * var->yres; else var->yres_virtual = var->yres + hwscroll * 16; } var->xoffset = 0; /* TODO change this */ /* hdX-offsets */ prescale = hxx_prescale(hw); plen = 4 >> (hw->vid_mode >> 2 & 0x3); base_off = hw->vid_control & VCO_SHORTOFFS ? 64 : 128; if (hw->f_shift & 0x100) { hde_off = 0; hdb_off = (base_off + 16 * plen) + prescale; } else { hde_off = ((128 / var->bits_per_pixel + 2) * plen); if (hw->ste_mode) hdb_off = (64 + base_off + (128 / var->bits_per_pixel + 2) * plen) + prescale; else hdb_off = (base_off + (128 / var->bits_per_pixel + 18) * plen) + prescale; } /* Right margin includes hsync */ var->left_margin = hdb_off + prescale * ((hw->hdb & 0x1ff) - (hw->hdb & 0x200 ? 2 + hw->hht : 0)); if (hw->ste_mode || mon_type != F_MON_VGA) var->right_margin = prescale * (hw->hht + 2 - hw->hde) - hde_off; else /* can't use this in ste_mode, because hbb is +1 off */ var->right_margin = prescale * (hw->hht + 2 - hw->hbb); var->hsync_len = prescale * (hw->hht + 2 - hw->hss); /* Lower margin includes vsync */ var->upper_margin = hw->vdb / 2; /* round down to full lines */ var->lower_margin = (hw->vft + 1 - hw->vde + 1) / 2; /* round up */ var->vsync_len = (hw->vft + 1 - hw->vss + 1) / 2; /* round up */ if (var->vmode & FB_VMODE_INTERLACED) { var->upper_margin *= 2; var->lower_margin *= 2; var->vsync_len *= 2; } else if (var->vmode & FB_VMODE_DOUBLE) { var->upper_margin = (var->upper_margin + 1) / 2; var->lower_margin = (var->lower_margin + 1) / 2; var->vsync_len = (var->vsync_len + 1) / 2; } var->pixclock *= plen; var->left_margin /= plen; var->right_margin /= plen; var->hsync_len /= plen; var->right_margin -= var->hsync_len; var->lower_margin -= var->vsync_len; if (screen_base) var->yoffset = (par->screen_base - screen_base) / linelen; else var->yoffset = 0; var->nonstd = 0; /* what is this for? */ var->activate = 0; return 0;}static int f_change_mode;static struct falcon_hw f_new_mode;static int f_pan_display;static void falcon_get_par(struct atafb_par *par){ unsigned long addr; struct falcon_hw *hw = &par->hw.falcon; hw->line_width = shifter_f030.scn_width; hw->line_offset = shifter_f030.off_next; hw->st_shift = videl.st_shift & 0x300; hw->f_shift = videl.f_shift; hw->vid_control = videl.control; hw->vid_mode = videl.mode; hw->sync = shifter.syncmode & 0x1; hw->xoffset = videl.xoffset & 0xf; hw->hht = videl.hht; hw->hbb = videl.hbb; hw->hbe = videl.hbe; hw->hdb = videl.hdb; hw->hde = videl.hde; hw->hss = videl.hss; hw->vft = videl.vft; hw->vbb = videl.vbb; hw->vbe = videl.vbe; hw->vdb = videl.vdb; hw->vde = videl.vde; hw->vss = videl.vss; addr = (shifter.bas_hi & 0xff) << 16 | (shifter.bas_md & 0xff) << 8 | (shifter.bas_lo & 0xff); par->screen_base = phys_to_virt(addr); /* derived parameters */ hw->ste_mode = (hw->f_shift & 0x510) == 0 && hw->st_shift == 0x100; hw->mono = (hw->f_shift & 0x400) || ((hw->f_shift & 0x510) == 0 && hw->st_shift == 0x200);}static void falcon_set_par(struct atafb_par *par){ f_change_mode = 0; /* only set screen_base if really necessary */ if (current_par.screen_base != par->screen_base) fbhw->set_screen_base(par->screen_base); /* Don't touch any other registers if we keep the default resolution */ if (DontCalcRes) return; /* Tell vbl-handler to change video mode. * We change modes only on next VBL, to avoid desynchronisation * (a shift to the right and wrap around by a random number of pixels * in all monochrome modes). * This seems to work on my Falcon. */ f_new_mode = par->hw.falcon; f_change_mode = 1;}static irqreturn_t falcon_vbl_switcher(int irq, void *dummy){ struct falcon_hw *hw = &f_new_mode; if (f_change_mode) { f_change_mode = 0; if (hw->sync & 0x1) { /* Enable external pixelclock. This code only for ScreenWonder */ *(volatile unsigned short *)0xffff9202 = 0xffbf; } else { /* Turn off external clocks. Read sets all output bits to 1. */ *(volatile unsigned short *)0xffff9202; } shifter.syncmode = hw->sync; videl.hht = hw->hht; videl.hbb = hw->hbb; videl.hbe = hw->hbe; videl.hdb = hw->hdb; videl.hde = hw->hde; videl.hss = hw->hss; videl.vft = hw->vft; videl.vbb = hw->vbb; videl.vbe = hw->vbe; videl.vdb = hw->vdb; videl.vde = hw->vde; videl.vss = hw->vss; videl.f_shift = 0; /* write enables Falcon palette, 0: 4 planes */ if (hw->ste_mode) { videl.st_shift = hw->st_shift; /* write enables STE palette */ } else { /* IMPORTANT: * set st_shift 0, so we can tell the screen-depth if f_shift == 0. * Writing 0 to f_shift enables 4 plane Falcon mode but * doesn't set st_shift. st_shift != 0 (!= 4planes) is impossible * with Falcon palette. */ videl.st_shift = 0; /* now back to Falcon palette mode */ videl.f_shift = hw->f_shift; } /* writing to st_shift changed scn_width and vid_mode */ videl.xoffset = hw->xoffset; shifter_f030.scn_width = hw->line_width; shifter_f030.off_next = hw->line_offset; videl.control = hw->vid_control; videl.mode = hw->vid_mode; } if (f_pan_display) { f_pan_display = 0; videl.xoffset = current_par.hw.falcon.xoffset; shifter_f030.off_next = current_par.hw.falcon.line_offset; } return IRQ_HANDLED;}static int falcon_pan_display(struct fb_var_screeninfo *var, struct fb_info *info){ struct atafb_par *par = (struct atafb_par *)info->par; int xoffset; int bpp = info->var.bits_per_pixel; if (bpp == 1) var->xoffset = up(var->xoffset, 32); if (bpp != 16) par->hw.falcon.xoffset = var->xoffset & 15; else { par->hw.falcon.xoffset = 0; var->xoffset = up(var->xoffset, 2); } par->hw.falcon.line_offset = bpp * (info->var.xres_virtual - info->var.xres) / 16; if (par->hw.falcon.xoffset) par->hw.falcon.line_offset -= bpp; xoffset = var->xoffset - par->hw.falcon.xoffset; par->screen_base = screen_base + (var->yoffset * info->var.xres_virtual + xoffset) * bpp / 8; if (fbhw->set_screen_base) fbhw->set_screen_base(par->screen_base); else return -EINVAL; /* shouldn't happen */ f_pan_display = 1; return 0;}static int falcon_setcolreg(unsigned int regno, unsigned int red, unsigned int green, unsigned int blue, unsigned int transp, struct fb_info *info){ if (regno > 255) return 1; f030_col[regno] = (((red & 0xfc00) << 16) | ((green & 0xfc00) << 8) | ((blue & 0xfc00) >> 8)); if (regno < 16) { shifter_tt.color_reg[regno] = (((red & 0xe000) >> 13) | ((red & 0x1000) >> 12) << 8) | (((green & 0xe000) >> 13) | ((green & 0x1000) >> 12) << 4) | ((blue & 0xe000) >> 13) | ((blue & 0x1000) >> 12);#ifdef ATAFB_FALCON ((u32 *)info->pseudo_palette)[regno] = ((red & 0xf800) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11));#endif } return 0;}static int falcon_blank(int blank_mode){ /* ++guenther: we can switch off graphics by changing VDB and VDE, * so VIDEL doesn't hog the bus while saving. * (this may affect usleep()). */ int vdb, vss, hbe, hss; if (mon_type == F_MON_SM) /* this doesn't work on SM124 */ return 1; vdb = current_par.VDB; vss = current_par.VSS; hbe = current_par.HBE; hss = current_par.HSS; if (blank_mode >= 1) { /* disable graphics output (this speeds up the CPU) ... */ vdb = current_par.VFT + 1; /* ... and blank all lines */ hbe = current_par.HHT + 2; } /* use VESA suspend modes on VGA monitors */ if (mon_type == F_MON_VGA) { if (blank_mode == 2 || blank_mode == 4) vss = current_par.VFT + 1; if (blank_mode == 3 || blank_mode == 4) hss = current_par.HHT + 2; } videl.vdb = vdb; videl.vss = vss; videl.hbe = hbe; videl.hss = hss; return 0;}static int falcon_detect(void){ struct atafb_par par; unsigned char fhw; /* Determine connected monitor and set monitor parameters */ fhw = *(unsigned char *)0xffff8006; mon_type = fhw >> 6 & 0x3; /* bit 1 of fhw: 1=32 bit ram bus, 0=16 bit */ f030_bus_width = fhw << 6 & 0x80; switch (mon_type) { case F_MON_SM: fb_info.monspecs.vfmin = 70; fb_info.monspecs.vfmax = 72; fb_info.monspecs.hfmin = 35713; fb_info.monspecs.hfmax = 35715; break; case F_MON_SC: case F_MON_TV: /* PAL...NTSC */ fb_info.monspecs.vfmin = 49; /* not 50, since TOS defaults to 49.9x Hz */ fb_info.monspecs.vfmax = 60; fb_info.monspecs.hfmin = 15620; fb_info.monspecs.hfmax = 15755; break; } /* initialize hsync-len */ f25.hsync = h_syncs[mon_type] / f25.t; f32.hsync = h_syncs[mon_type] / f32.t; if (fext.t) fext.hsync = h_syncs[mon_type] / fext.t; falcon_get_par(&par); falcon_encode_var(&atafb_predefined[0], &par); /* Detected mode is always the "autodetect" slot */ return 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -