/* * linux/drivers/video/atafb.c -- Atari builtin chipset frame buffer device * * Copyright (C) 1994 Martin Schaller & Roman Hodek * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive * for more details. * * History: * - 03 Jan 95: Original version by Martin Schaller: The TT driver and * all the device independent stuff * - 09 Jan 95: Roman: I've added the hardware abstraction (hw_switch) * and wrote the Falcon, ST(E), and External drivers * based on the original TT driver. * - 07 May 95: Martin: Added colormap operations for the external driver * - 21 May 95: Martin: Added support for overscan * Andreas: some bug fixes for this * - Jul 95: Guenther Kelleter <guenther@pool.informatik.rwth-aachen.de>: * Programmable Falcon video modes * (thanks to Christian Cartus for documentation * of VIDEL registers). * - 27 Dec 95: Guenther: Implemented user definable video modes "user[0-7]" * on minor 24...31. "user0" may be set on commandline by * "R<x>;<y>;<depth>". (Makes sense only on Falcon) * Video mode switch on Falcon now done at next VBL interrupt * to avoid the annoying right shift of the screen. * - 23 Sep 97: Juergen: added xres_virtual for cards like ProMST * The external-part is legacy, therefore hardware-specific * functions like panning/hardwarescrolling/blanking isn't * supported. * - 29 Sep 97: Juergen: added Romans suggestion for pan_display * (var->xoffset was changed even if no set_screen_base avail.) * - 05 Oct 97: Juergen: extfb (PACKED_PIXEL) is FB_PSEUDOCOLOR 'cause * we know how to set the colors * ext_*palette: read from ext_colors (former MV300_colors) * write to ext_colors and RAMDAC * * To do: * - For the Falcon it is not possible to set random video modes on * SM124 and SC/TV, only the bootup resolution is supported. *
*/
staticstruct atafb_par { void *screen_base; int yres_virtual;
u_long next_line; #ifdefined ATAFB_TT || defined ATAFB_STE union { struct { int mode; int sync;
} tt, st; #endif #ifdef ATAFB_FALCON struct falcon_hw { /* Here are fields for storing a video mode, as direct * parameters for the hardware.
*/ short sync; short line_width; short line_offset; short st_shift; short f_shift; short vid_control; short vid_mode; short xoffset; short hht, hbb, hbe, hdb, hde, hss; short vft, vbb, vbe, vdb, vde, vss; /* auxiliary information */ short mono; short ste_mode; short bpp;
u32 pseudo_palette[16];
} falcon; #endif /* Nothing needed for external mode */
} hw;
} current_par;
/* Don't calculate an own resolution, and thus don't change the one found when * booting (currently used for the Falcon to keep settings for internal video
* hardware extensions (e.g. ScreenBlaster) */ staticint DontCalcRes = 0;
/* * not needed - atafb will never support panning/hardwarescroll with external * static unsigned int external_yres_virtual;
*/ staticunsignedint external_depth; staticint external_pmode; staticvoid *external_screen_base; staticunsignedlong external_addr; staticunsignedlong external_len; staticunsignedlong external_vgaiobase; staticunsignedint external_bitspercol = 6;
/* * JOE <joe@amber.dinoco.de>: * added card type for external driver, is only needed for * colormap handling.
*/ enum cardtype { IS_VGA, IS_MV300 }; staticenum cardtype external_card_type = IS_VGA;
/* * struct fb_ops { * * open/release and usage marking * struct module *owner; * int (*fb_open)(struct fb_info *info, int user); * int (*fb_release)(struct fb_info *info, int user); * * * For framebuffers with strange non linear layouts or that do not * * work with normal memory mapped access * ssize_t (*fb_read)(struct file *file, char __user *buf, size_t count, loff_t *ppos); * ssize_t (*fb_write)(struct file *file, const char __user *buf, size_t count, loff_t *ppos); * * * checks var and eventually tweaks it to something supported, * * DOES NOT MODIFY PAR * * int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info); * * * set the video mode according to info->var * * int (*fb_set_par)(struct fb_info *info); * * * set color register * * int (*fb_setcolreg)(unsigned int regno, unsigned int red, unsigned int green, * unsigned int blue, unsigned int transp, struct fb_info *info); * * * set color registers in batch * * int (*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info); * * * blank display * * int (*fb_blank)(int blank, struct fb_info *info); * * * pan display * * int (*fb_pan_display)(struct fb_var_screeninfo *var, struct fb_info *info); * * *** The meat of the drawing engine *** * * Draws a rectangle * * void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect); * * Copy data from area to another * * void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region); * * Draws a image to the display * * void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image); * * * Draws cursor * * int (*fb_cursor) (struct fb_info *info, struct fb_cursor *cursor); * * * wait for blit idle, optional * * int (*fb_sync)(struct fb_info *info); * * * perform fb specific ioctl (optional) * * int (*fb_ioctl)(struct fb_info *info, unsigned int cmd, * unsigned long arg); * * * Handle 32bit compat ioctl (optional) * * int (*fb_compat_ioctl)(struct fb_info *info, unsigned int cmd, * unsigned long arg); * * * perform fb specific mmap * * int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma); * } ;
*/
/* ++roman: This structure abstracts from the underlying hardware (ST(e), * TT, or Falcon. * * int (*detect)(void) * This function should detect the current video mode settings and * store them in atafb_predefined[0] for later reference by the * user. Return the index+1 of an equivalent predefined mode or 0 * if there is no such. * * int (*encode_fix)(struct fb_fix_screeninfo *fix, * struct atafb_par *par) * This function should fill in the 'fix' structure based on the * values in the 'par' structure. * !!! Obsolete, perhaps !!! * * int (*decode_var)(struct fb_var_screeninfo *var, * struct atafb_par *par) * Get the video params out of 'var'. If a value doesn't fit, round * it up, if it's too big, return EINVAL. * Round up in the following order: bits_per_pixel, xres, yres, * xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields, * horizontal timing, vertical timing. * * int (*encode_var)(struct fb_var_screeninfo *var, * struct atafb_par *par); * Fill the 'var' structure based on the values in 'par' and maybe * other values read out of the hardware. * * void (*get_par)(struct atafb_par *par) * Fill the hardware's 'par' structure. * !!! Used only by detect() !!! * * void (*set_par)(struct atafb_par *par) * Set the hardware according to 'par'. * * void (*set_screen_base)(void *s_base) * Set the base address of the displayed frame buffer. Only called * if yres_virtual > yres or xres_virtual > xres. * * int (*blank)(int blank_mode) * Blank the screen if blank_mode != 0, else unblank. If blank == NULL then * the caller blanks by setting the CLUT 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, 3:suspend hsync, 4: powerdown.
*/
staticstruct fb_hwswitch { int (*detect)(void); int (*encode_fix)(struct fb_fix_screeninfo *fix, struct atafb_par *par); int (*decode_var)(struct fb_var_screeninfo *var, struct atafb_par *par); int (*encode_var)(struct fb_var_screeninfo *var, struct atafb_par *par); void (*get_par)(struct atafb_par *par); void (*set_par)(struct atafb_par *par); void (*set_screen_base)(void *s_base); int (*blank)(int blank_mode); int (*pan_display)(struct fb_var_screeninfo *var, struct fb_info *info);
} *fbhw;
#define DEFMODE_TT 5 /* "tt-high" for TT */ #define DEFMODE_F30 7 /* "vga70" for Falcon */ #define DEFMODE_STE 2 /* "st-high" for ST/E */ #define DEFMODE_EXT 6 /* "vga" for external */
staticint get_video_mode(char *vname)
{ char ***name_list; char **name; int i;
name_list = fb_var_names; for (i = 0; i < num_atafb_predefined; i++) {
name = *name_list++; if (!name || !*name) break; while (*name) { if (!strcmp(vname, *name)) return i + 1;
name++;
}
} return 0;
}
/* ------------------- TT specific functions ---------------------- */
#ifdef ATAFB_TT
staticint tt_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par)
{ int mode;
/* 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! * * Even on a TT, we should look if there is a DMA sound. It was * announced that the Eagle is TT compatible, but only the PCM is * missing...
*/ 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;
staticint falcon_encode_fix(struct fb_fix_screeninfo *fix, struct atafb_par *par)
{
strcpy(fix->id, "Atari Builtin");
fix->smem_start = phys_screen_base;
fix->smem_len = screen_len;
fix->type = FB_TYPE_INTERLEAVED_PLANES;
fix->type_aux = 2;
fix->visual = FB_VISUAL_PSEUDOCOLOR;
fix->xpanstep = 1;
fix->ypanstep = 1;
fix->ywrapstep = 0; if (par->hw.falcon.mono) {
fix->type = FB_TYPE_PACKED_PIXELS;
fix->type_aux = 0; /* no smooth scrolling with longword aligned video mem */
fix->xpanstep = 32;
} elseif (par->hw.falcon.f_shift & 0x100) {
fix->type = FB_TYPE_PACKED_PIXELS;
fix->type_aux = 0; /* Is this ok or should it be DIRECTCOLOR? */
fix->visual = FB_VISUAL_TRUECOLOR;
fix->xpanstep = 2;
}
fix->line_length = par->next_line;
fix->accel = FB_ACCEL_ATARIBLITT; return 0;
}
staticint falcon_decode_var(struct fb_var_screeninfo *var, struct atafb_par *par)
{ int bpp = var->bits_per_pixel; int xres = var->xres; int yres = var->yres; int xres_virtual = var->xres_virtual; int yres_virtual = var->yres_virtual; int left_margin, right_margin, hsync_len; int upper_margin, lower_margin, vsync_len; int linelen; int interlace = 0, doubleline = 0; struct pixel_clock *pclock; int plen; /* width of pixel in clock cycles */ int xstretch; int prescale; int longoffset = 0; int hfreq, vfreq; int hdb_off, hde_off, base_off; int gstart, gend1, gend2, align;
/* Get the video params out of 'var'. If a value doesn't fit, round it up, if it's too big, return EINVAL. Round up in the following order: bits_per_pixel, xres, yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale, bitfields, horizontal timing, vertical timing.
There is a maximum of screen resolution determined by pixelclock and minimum frame rate -- (X+hmarg.)*(Y+vmarg.)*vfmin <= pixelclock. In interlace mode this is " * " *vfmin <= pixelclock. Additional constraints: hfreq. Frequency range for multisync monitors is given via command line. For TV and SM124 both frequencies are fixed.
X % 16 == 0 to fit 8x?? font (except 1 bitplane modes must use X%32 == 0) Y % 16 == 0 to fit 8x16 font Y % 8 == 0 if Y<400
Currently interlace and doubleline mode in var are ignored. On SM124 and TV only the standard resolutions can be used.
*/
if (mon_type == F_MON_SM || DontCalcRes) { /* Skip all calculations. VGA/TV/SC1224 only supported. */ struct fb_var_screeninfo *myvar = &atafb_predefined[0];
if (bpp > myvar->bits_per_pixel ||
var->xres > myvar->xres ||
var->yres > myvar->yres) return -EINVAL;
fbhw->get_par(par); /* Current par will be new par */ goto set_screen_base; /* Don't forget this */
}
/* 2 planes must use STE compatibility mode */
par->hw.falcon.ste_mode = bpp == 2;
par->hw.falcon.mono = bpp == 1;
/* Total and visible scanline length must be a multiple of one longword, * this and the console fontwidth yields the alignment for xres and * xres_virtual. * TODO: this way "odd" fontheights are not supported * * Special case in STE mode: blank and graphic positions don't align, * avoid trash at right margin
*/ if (par->hw.falcon.ste_mode)
xres = (xres + 63) & ~63; elseif (bpp == 1)
xres = (xres + 31) & ~31; else
xres = (xres + 15) & ~15; if (yres >= 400)
yres = (yres + 15) & ~15; else
yres = (yres + 7) & ~7;
/* single or double pixel width */
xstretch = (xres < 640) ? 2 : 1;
#if 0 /* SM124 supports only 640x400, this is rejected above */ if (mon_type == F_MON_SM) { if (xres != 640 && yres != 400) return -EINVAL;
plen = 1;
pclock = &f32; /* SM124-mode is special */
par->hw.falcon.ste_mode = 1;
par->hw.falcon.f_shift = 0x000;
par->hw.falcon.st_shift = 0x200;
left_margin = hsync_len = 128 / plen;
right_margin = 0; /* TODO set all margins */
} else #endif if (mon_type == F_MON_SC || mon_type == F_MON_TV) {
plen = 2 * xstretch; if (var->pixclock > f32.t * plen) return -EINVAL;
pclock = &f32; if (yres > 240)
interlace = 1; if (var->pixclock == 0) { /* set some minimal margins which center the screen */
left_margin = 32;
right_margin = 18;
hsync_len = pclock->hsync / plen;
upper_margin = 31;
lower_margin = 14;
vsync_len = interlace ? 3 : 4;
} else {
left_margin = var->left_margin;
right_margin = var->right_margin;
hsync_len = var->hsync_len;
upper_margin = var->upper_margin;
lower_margin = var->lower_margin;
vsync_len = var->vsync_len; if (var->vmode & FB_VMODE_INTERLACED) {
upper_margin = (upper_margin + 1) / 2;
lower_margin = (lower_margin + 1) / 2;
vsync_len = (vsync_len + 1) / 2;
} elseif (var->vmode & FB_VMODE_DOUBLE) {
upper_margin *= 2;
lower_margin *= 2;
vsync_len *= 2;
}
}
} else { /* F_MON_VGA */ if (bpp == 16)
xstretch = 2; /* Double pixel width only for hicolor */ /* Default values are used for vert./hor. timing if no pixelclock given. */ if (var->pixclock == 0) { /* Choose master pixelclock depending on hor. timing */
plen = 1 * xstretch; if ((plen * xres + f25.right + f25.hsync + f25.left) *
fb_info.monspecs.hfmin < f25.f)
pclock = &f25; elseif ((plen * xres + f32.right + f32.hsync +
f32.left) * fb_info.monspecs.hfmin < f32.f)
pclock = &f32; elseif ((plen * xres + fext.right + fext.hsync +
fext.left) * fb_info.monspecs.hfmin < fext.f &&
fext.f)
pclock = &fext; else return -EINVAL;
left_margin = pclock->left / plen;
right_margin = pclock->right / plen;
hsync_len = pclock->hsync / plen;
upper_margin = 31;
lower_margin = 11;
vsync_len = 3;
} else { /* Choose largest pixelclock <= wanted clock */ int i; unsignedlong pcl = ULONG_MAX;
pclock = 0; for (i = 1; i <= 4; i *= 2) { if (f25.t * i >= var->pixclock &&
f25.t * i < pcl) {
pcl = f25.t * i;
pclock = &f25;
} if (f32.t * i >= var->pixclock &&
f32.t * i < pcl) {
pcl = f32.t * i;
pclock = &f32;
} if (fext.t && fext.t * i >= var->pixclock &&
fext.t * i < pcl) {
pcl = fext.t * i;
pclock = &fext;
}
} if (!pclock) return -EINVAL;
plen = pcl / pclock->t;
left_margin = var->left_margin;
right_margin = var->right_margin;
hsync_len = var->hsync_len;
upper_margin = var->upper_margin;
lower_margin = var->lower_margin;
vsync_len = var->vsync_len; /* Internal unit is [single lines per (half-)frame] */ if (var->vmode & FB_VMODE_INTERLACED) { /* # lines in half frame */ /* External unit is [lines per full frame] */
upper_margin = (upper_margin + 1) / 2;
lower_margin = (lower_margin + 1) / 2;
vsync_len = (vsync_len + 1) / 2;
} elseif (var->vmode & FB_VMODE_DOUBLE) { /* External unit is [double lines per frame] */
upper_margin *= 2;
lower_margin *= 2;
vsync_len *= 2;
}
} if (pclock == &fext)
longoffset = 1; /* VIDEL doesn't synchronize on short offset */
} /* Is video bus bandwidth (32MB/s) too low for this resolution? */ /* this is definitely wrong if bus clock != 32MHz */ if (pclock->f / plen / 8 * bpp > 32000000L) return -EINVAL;
if (vsync_len < 1)
vsync_len = 1;
/* include sync lengths in right/lower margin for all calculations */
right_margin += hsync_len;
lower_margin += vsync_len;
/* ! In all calculations of margins we use # of lines in half frame * (which is a full frame in non-interlace mode), so we can switch * between interlace and non-interlace without messing around * with these.
*/
again: /* Set base_offset 128 and video bus width */
par->hw.falcon.vid_control = mon_type | f030_bus_width; if (!longoffset)
par->hw.falcon.vid_control |= VCO_SHORTOFFS; /* base_offset 64 */ if (var->sync & FB_SYNC_HOR_HIGH_ACT)
par->hw.falcon.vid_control |= VCO_HSYPOS; if (var->sync & FB_SYNC_VERT_HIGH_ACT)
par->hw.falcon.vid_control |= VCO_VSYPOS; /* Pixelclock */
par->hw.falcon.vid_control |= pclock->control_mask; /* External or internal clock */
par->hw.falcon.sync = pclock->sync_mask | 0x2; /* Pixellength and prescale */
par->hw.falcon.vid_mode = (2 / plen) << 2; if (doubleline)
par->hw.falcon.vid_mode |= VMO_DOUBLE; if (interlace)
par->hw.falcon.vid_mode |= VMO_INTER;
/********************* * Horizontal timing: unit = [master clock cycles] * unit of hxx-registers: [master clock cycles * prescale] * Hxx-registers are 9 bit wide * * 1 line = ((hht + 2) * 2 * prescale) clock cycles * * graphic output = hdb & 0x200 ? * ((hht + 2) * 2 - hdb + hde) * prescale - hdboff + hdeoff: * (hht + 2 - hdb + hde) * prescale - hdboff + hdeoff * (this must be a multiple of plen*128/bpp, on VGA pixels * to the right may be cut off with a bigger right margin) * * start of graphics relative to start of 1st halfline = hdb & 0x200 ? * (hdb - hht - 2) * prescale + hdboff : * hdb * prescale + hdboff * * end of graphics relative to start of 1st halfline = * (hde + hht + 2) * prescale + hdeoff
*********************/ /* Calculate VIDEL registers */
{
prescale = hxx_prescale(&par->hw.falcon);
base_off = par->hw.falcon.vid_control & VCO_SHORTOFFS ? 64 : 128;
gstart = (prescale / 2 + plen * left_margin) / prescale; /* gend1 is for hde (gend-gstart multiple of align), shifter's xres */
gend1 = gstart + roundup(xres, align) * plen / prescale; /* gend2 is for hbb, visible xres (rest to gend1 is cut off by hblank) */
gend2 = gstart + xres * plen / prescale;
par->HHT = plen * (left_margin + xres + right_margin) /
(2 * prescale) - 2; /* par->HHT = (gend2 + plen * right_margin / prescale) / 2 - 2;*/
par->HDB = gstart - hdb_off / prescale;
par->HBE = gstart; if (par->HDB < 0)
par->HDB += par->HHT + 2 + 0x200;
par->HDE = gend1 - par->HHT - 2 - hde_off / prescale;
par->HBB = gend2 - par->HHT - 2; #if 0 /* One more Videl constraint: data fetch of two lines must not overlap */ if ((par->HDB & 0x200) && (par->HDB & ~0x200) - par->HDE <= 5) { /* if this happens increase margins, decrease hfreq. */
} #endif if (hde_off % prescale)
par->HBB++; /* compensate for non matching hde and hbb */
par->HSS = par->HHT + 2 - plen * hsync_len / prescale; if (par->HSS < par->HBB)
par->HSS = par->HBB;
}
/* check hor. frequency */
hfreq = pclock->f / ((par->HHT + 2) * prescale * 2); if (hfreq > fb_info.monspecs.hfmax && mon_type != F_MON_VGA) { /* ++guenther: ^^^^^^^^^^^^^^^^^^^ can't remember why I did this */ /* Too high -> enlarge margin */
left_margin += 1;
right_margin += 1; goto again;
} if (hfreq > fb_info.monspecs.hfmax || hfreq < fb_info.monspecs.hfmin) return -EINVAL;
/* Vxx-registers */ /* All Vxx must be odd in non-interlace, since frame starts in the middle * of the first displayed line! * One frame consists of VFT+1 half lines. VFT+1 must be even in * non-interlace, odd in interlace mode for synchronisation. * Vxx-registers are 11 bit wide
*/
par->VBE = (upper_margin * 2 + 1); /* must begin on odd halfline */
par->VDB = par->VBE;
par->VDE = yres; if (!interlace)
par->VDE <<= 1; if (doubleline)
par->VDE <<= 1; /* VDE now half lines per (half-)frame */
par->VDE += par->VDB;
par->VBB = par->VDE;
par->VFT = par->VBB + (lower_margin * 2 - 1) - 1;
par->VSS = par->VFT + 1 - (vsync_len * 2 - 1); /* vbb,vss,vft must be even in interlace mode */ if (interlace) {
par->VBB++;
par->VSS++;
par->VFT++;
}
/* V-frequency check, hope I didn't create any loop here. */ /* Interlace and doubleline are mutually exclusive. */
vfreq = (hfreq * 2) / (par->VFT + 1); if (vfreq > fb_info.monspecs.vfmax && !doubleline && !interlace) { /* Too high -> try again with doubleline */
doubleline = 1; goto again;
} elseif (vfreq < fb_info.monspecs.vfmin && !interlace && !doubleline) { /* Too low -> try again with interlace */
interlace = 1; goto again;
} elseif (vfreq < fb_info.monspecs.vfmin && doubleline) { /* Doubleline too low -> clear doubleline and enlarge margins */ int lines;
doubleline = 0; for (lines = 0;
(hfreq * 2) / (par->VFT + 1 + 4 * lines - 2 * yres) >
fb_info.monspecs.vfmax;
lines++)
;
upper_margin += lines;
lower_margin += lines; goto again;
} elseif (vfreq > fb_info.monspecs.vfmax && doubleline) { /* Doubleline too high -> enlarge margins */ int lines; for (lines = 0;
(hfreq * 2) / (par->VFT + 1 + 4 * lines) >
fb_info.monspecs.vfmax;
lines += 2)
;
upper_margin += lines;
lower_margin += lines; goto again;
} elseif (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;
} elseif (vfreq < fb_info.monspecs.vfmin ||
vfreq > fb_info.monspecs.vfmax) return -EINVAL;
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; elseif (hw->f_shift & 0x100) /* hicolor */
var->bits_per_pixel = 16; elseif (hw->f_shift & 0x010) /* 8 bitplanes */
var->bits_per_pixel = 8; elseif (hw->st_shift == 0)
var->bits_per_pixel = 4; elseif (hw->st_shift == 0x100)
var->bits_per_pixel = 2; else/* if (hw->st_shift == 0x200) */
var->bits_per_pixel = 1;
/* 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;
}
staticint 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;
/* 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;
/* 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
*/
/* SWITCH_ACIA may be used for Falcon (ScreenBlaster III internal!) */ staticvoid st_ovsc_switch(void)
{ unsignedlong flags; registerunsignedchar 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);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.