📄 atafb.c
字号:
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 = 0;static struct falcon_hw f_new_mode;static int f_pan_display = 0;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 void falcon_vbl_switcher( int irq, void *dummy, struct pt_regs *fp ){ 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; }}static int falcon_pan_display( struct fb_var_screeninfo *var, struct atafb_par *par ){ int xoffset; int bpp = fb_display[currcon].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 * (fb_display[currcon].var.xres_virtual - fb_display[currcon].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 * fb_display[currcon].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_getcolreg( unsigned regno, unsigned *red, unsigned *green, unsigned *blue, unsigned *transp, struct fb_info *info ){ unsigned long col; if (regno > 255) return 1; /* This works in STE-mode (with 4bit/color) since f030_col-registers * hold up to 6bit/color. * Even with hicolor r/g/b=5/6/5 bit! */ col = f030_col[regno]; *red = (col >> 16) & 0xff00; *green = (col >> 8) & 0xff00; *blue = (col << 8) & 0xff00; *transp = 0; return 0;}static int falcon_setcolreg( unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned 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 FBCON_HAS_CFB16 fbcon_cfb16_cmap[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;}#endif /* ATAFB_FALCON *//* ------------------- ST(E) specific functions ---------------------- */#ifdef ATAFB_STEstatic int stste_encode_fix( struct fb_fix_screeninfo *fix, struct atafb_par *par ){ int mode; strcpy(fix->id,"Atari Builtin"); fix->smem_start = (unsigned long)real_screen_base; fix->smem_len = screen_len; fix->type = FB_TYPE_INTERLEAVED_PLANES; fix->type_aux = 2; fix->visual = FB_VISUAL_PSEUDOCOLOR; mode = par->hw.st.mode & 3; if (mode == ST_HIGH) { fix->type = FB_TYPE_PACKED_PIXELS; fix->type_aux = 0; fix->visual = FB_VISUAL_MONO10; } if (ATARIHW_PRESENT(EXTD_SHIFTER)) { fix->xpanstep = 16; fix->ypanstep = 1; } else { fix->xpanstep = 0; fix->ypanstep = 0; } fix->ywrapstep = 0; fix->line_length = 0; fix->accel = FB_ACCEL_ATARIBLITT; return 0;}static int stste_decode_var( struct fb_var_screeninfo *var, struct atafb_par *par ){ int xres=var->xres; int yres=var->yres; int bpp=var->bits_per_pixel; int linelen; int yres_virtual = var->yres_virtual; if (mono_moni) { if (bpp > 1 || xres > sttt_xres || yres > st_yres) return -EINVAL; par->hw.st.mode=ST_HIGH; xres=sttt_xres; yres=st_yres; bpp=1; } else { if (bpp > 4 || xres > sttt_xres || yres > st_yres) return -EINVAL; if (bpp > 2) { if (xres > sttt_xres/2 || yres > st_yres/2) return -EINVAL; par->hw.st.mode=ST_LOW; xres=sttt_xres/2; yres=st_yres/2; bpp=4; } else if (bpp > 1) { if (xres > sttt_xres || yres > st_yres/2) return -EINVAL; par->hw.st.mode=ST_MID; xres=sttt_xres; yres=st_yres/2; bpp=2; } else return -EINVAL; } if (yres_virtual <= 0) yres_virtual = 0; else if (yres_virtual < yres) yres_virtual = yres; if (var->sync & FB_SYNC_EXT) par->hw.st.sync=(par->hw.st.sync & ~1) | 1; else par->hw.st.sync=(par->hw.st.sync & ~1); linelen=xres*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; return 0;}static int stste_encode_var( struct fb_var_screeninfo *var, struct atafb_par *par ){ int linelen; memset(var, 0, sizeof(struct fb_var_screeninfo)); var->red.offset=0; var->red.length = ATARIHW_PRESENT(EXTD_SHIFTER) ? 4 : 3; var->red.msb_right=0; var->grayscale=0; var->pixclock=31041; var->left_margin=120; /* these are incorrect */ var->right_margin=100; var->upper_margin=8; var->lower_margin=16; var->hsync_len=140; var->vsync_len=30; var->height=-1; var->width=-1; if (!(par->hw.st.sync & 1)) var->sync=0; else var->sync=FB_SYNC_EXT; switch (par->hw.st.mode & 3) { case ST_LOW: var->xres=sttt_xres/2; var->yres=st_yres/2; var->bits_per_pixel=4; break; case ST_MID: var->xres=sttt_xres; var->yres=st_yres/2; var->bits_per_pixel=2; break; case ST_HIGH: var->xres=sttt_xres; var->yres=st_yres; var->bits_per_pixel=1; break; } var->blue=var->green=var->red;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -