📄 atafb.c
字号:
#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 = par->next_line; 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; par->next_line = 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; var->transp.offset = 0; var->transp.length = 0; var->transp.msb_right = 0; var->xres_virtual = sttt_xres_virtual; linelen = var->xres_virtual * var->bits_per_pixel / 8; ovsc_addlen = linelen * (sttt_yres_virtual - st_yres); if (!use_hwscroll) var->yres_virtual = var->yres; else 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; if (screen_base) var->yoffset = (par->screen_base - screen_base) / linelen; else var->yoffset = 0; var->nonstd = 0; var->activate = 0; var->vmode = FB_VMODE_NONINTERLACED; return 0;}static void stste_get_par(struct atafb_par *par){ unsigned long addr; par->hw.st.mode = shifter_tt.st_shiftmode; par->hw.st.sync = shifter.syncmode; addr = ((shifter.bas_hi & 0xff) << 16) | ((shifter.bas_md & 0xff) << 8); if (ATARIHW_PRESENT(EXTD_SHIFTER)) addr |= (shifter.bas_lo & 0xff); par->screen_base = phys_to_virt(addr);}static void stste_set_par(struct atafb_par *par){ shifter_tt.st_shiftmode = par->hw.st.mode; shifter.syncmode = par->hw.st.sync; /* only set screen_base if really necessary */ if (current_par.screen_base != par->screen_base) fbhw->set_screen_base(par->screen_base);}static int stste_setcolreg(unsigned int regno, unsigned int red, unsigned int green, unsigned int blue, unsigned int transp, struct fb_info *info){ if (regno > 15) return 1; red >>= 12; blue >>= 12; green >>= 12; if (ATARIHW_PRESENT(EXTD_SHIFTER)) shifter_tt.color_reg[regno] = (((red & 0xe) >> 1) | ((red & 1) << 3) << 8) | (((green & 0xe) >> 1) | ((green & 1) << 3) << 4) | ((blue & 0xe) >> 1) | ((blue & 1) << 3); else shifter_tt.color_reg[regno] = ((red & 0xe) << 7) | ((green & 0xe) << 3) | ((blue & 0xe) >> 1); return 0;}static int stste_detect(void){ struct atafb_par par; /* Determine the connected monitor: The DMA sound must be * disabled before reading the MFP GPIP, because the Sound * Done Signal and the Monochrome Detect are XORed together! */ if (ATARIHW_PRESENT(PCM_8BIT)) { tt_dmasnd.ctrl = DMASND_CTRL_OFF; udelay(20); /* wait a while for things to settle down */ } mono_moni = (st_mfp.par_dt_reg & 0x80) == 0; stste_get_par(&par); stste_encode_var(&atafb_predefined[0], &par); if (!ATARIHW_PRESENT(EXTD_SHIFTER)) use_hwscroll = 0; return 1;}static void stste_set_screen_base(void *s_base){ unsigned long addr; addr = virt_to_phys(s_base); /* Setup Screen Memory */ shifter.bas_hi = (unsigned char)((addr & 0xff0000) >> 16); shifter.bas_md = (unsigned char)((addr & 0x00ff00) >> 8); if (ATARIHW_PRESENT(EXTD_SHIFTER)) shifter.bas_lo = (unsigned char)(addr & 0x0000ff);}#endif /* ATAFB_STE *//* Switching the screen size should be done during vsync, otherwise * the margins may get messed up. This is a well known problem of * the ST's video system. * * Unfortunately there is hardly any way to find the vsync, as the * vertical blank interrupt is no longer in time on machines with * overscan type modifications. * * We can, however, use Timer B to safely detect the black shoulder, * but then we've got to guess an appropriate delay to find the vsync. * This might not work on every machine. * * martin_rogge @ ki.maus.de, 8th Aug 1995 */#define LINE_DELAY (mono_moni ? 30 : 70)#define SYNC_DELAY (mono_moni ? 1500 : 2000)/* SWITCH_ACIA may be used for Falcon (ScreenBlaster III internal!) */static void st_ovsc_switch(void){ unsigned long flags; register unsigned char old, new; if (!(atari_switches & ATARI_SWITCH_OVSC_MASK)) return; local_irq_save(flags); st_mfp.tim_ct_b = 0x10; st_mfp.active_edge |= 8; st_mfp.tim_ct_b = 0; st_mfp.tim_dt_b = 0xf0; st_mfp.tim_ct_b = 8; while (st_mfp.tim_dt_b > 1) /* TOS does it this way, don't ask why */ ; new = st_mfp.tim_dt_b; do { udelay(LINE_DELAY); old = new; new = st_mfp.tim_dt_b; } while (old != new); st_mfp.tim_ct_b = 0x10; udelay(SYNC_DELAY); if (atari_switches & ATARI_SWITCH_OVSC_IKBD) acia.key_ctrl = ACIA_DIV64 | ACIA_D8N1S | ACIA_RHTID | ACIA_RIE; if (atari_switches & ATARI_SWITCH_OVSC_MIDI) acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S | ACIA_RHTID; if (atari_switches & (ATARI_SWITCH_OVSC_SND6|ATARI_SWITCH_OVSC_SND7)) { sound_ym.rd_data_reg_sel = 14; sound_ym.wd_data = sound_ym.rd_data_reg_sel | ((atari_switches & ATARI_SWITCH_OVSC_SND6) ? 0x40:0) | ((atari_switches & ATARI_SWITCH_OVSC_SND7) ? 0x80:0); } local_irq_restore(flags);}/* ------------------- External Video ---------------------- */#ifdef ATAFB_EXTstatic int ext_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par){ strcpy(fix->id, "Unknown Extern"); fix->smem_start = (unsigned long)external_addr; fix->smem_len = PAGE_ALIGN(external_len); if (external_depth == 1) { fix->type = FB_TYPE_PACKED_PIXELS; /* The letters 'n' and 'i' in the "atavideo=external:" stand * for "normal" and "inverted", rsp., in the monochrome case */ fix->visual = (external_pmode == FB_TYPE_INTERLEAVED_PLANES || external_pmode == FB_TYPE_PACKED_PIXELS) ? FB_VISUAL_MONO10 : FB_VISUAL_MONO01; } else { /* Use STATIC if we don't know how to access color registers */ int visual = external_vgaiobase ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_STATIC_PSEUDOCOLOR; switch (external_pmode) { case -1: /* truecolor */ fix->type = FB_TYPE_PACKED_PIXELS; fix->visual = FB_VISUAL_TRUECOLOR; break; case FB_TYPE_PACKED_PIXELS: fix->type = FB_TYPE_PACKED_PIXELS; fix->visual = visual; break; case FB_TYPE_PLANES: fix->type = FB_TYPE_PLANES; fix->visual = visual; break; case FB_TYPE_INTERLEAVED_PLANES: fix->type = FB_TYPE_INTERLEAVED_PLANES; fix->type_aux = 2; fix->visual = visual; break; } } fix->xpanstep = 0; fix->ypanstep = 0; fix->ywrapstep = 0; fix->line_length = par->next_line; return 0;}static int ext_decode_var(struct fb_var_screeninfo *var, struct atafb_par *par){ struct fb_var_screeninfo *myvar = &atafb_predefined[0]; if (var->bits_per_pixel > myvar->bits_per_pixel || var->xres > myvar->xres || var->xres_virtual > myvar->xres_virtual || var->yres > myvar->yres || var->xoffset > 0 || var->yoffset > 0) return -EINVAL; par->next_line = external_xres_virtual * external_depth / 8; return 0;}static int ext_encode_var(struct fb_var_screeninfo *var, struct atafb_par *par){ memset(var, 0, sizeof(struct fb_var_screeninfo)); var->red.offset = 0; var->red.length = (external_pmode == -1) ? external_depth / 3 : (external_vgaiobase ? external_bitspercol : 0); var->red.msb_right = 0; var->grayscale = 0; var->pixclock = 31041; var->left_margin = 120; /* these are surely 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; var->sync = 0; var->xres = external_xres; var->yres = external_yres; var->xres_virtual = external_xres_virtual; var->bits_per_pixel = external_depth; var->blue = var->green = var->red; var->transp.offset = 0; var->transp.length = 0; var->transp.msb_right = 0; var->yres_virtual = var->yres; var->xoffset = 0; var->yoffset = 0; var->nonstd = 0; var->activate = 0; var->vmode = FB_VMODE_NONINTERLACED; return 0;}static void ext_get_par(struct atafb_par *par){ par->screen_base = external_addr;}static void ext_set_par(struct atafb_par *par){}#define OUTB(port,val) \ *((unsigned volatile char *) ((port)+external_vgaiobase)) = (val)#define INB(port) \ (*((unsigned volatile char *) ((port)+external_vgaiobase)))#define DACDelay \ do { \ unsigned char tmp = INB(0x3da); \ tmp = INB(0x3da); \ } while (0)static int ext_setcolreg(unsigned int regno, unsigned int red, unsigned int green, unsigned int blue, unsigned int transp, struct fb_info *info){ unsigned char colmask = (1 << external_bitspercol) - 1; if (!external_vgaiobase) return 1; switch (external_card_type) { case IS_VGA: OUTB(0x3c8, regno); DACDelay; OUTB(0x3c9, red & colmask); DACDelay; OUTB(0x3c9, green & colmask); DACDelay; OUTB(0x3c9, blue & colmask); DACDelay; return 0; case IS_MV300: OUTB((MV300_reg[regno] << 2) + 1, red);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -