/* * drivers/video/cirrusfb.c - driver for Cirrus Logic chipsets * * Copyright 1999-2001 Jeff Garzik <jgarzik@pobox.com> * * Contributors (thanks, all!) * * David Eger: * Overhaul for Linux 2.6 * * Jeff Rugen: * Major contributions; Motorola PowerStack (PPC and PCI) support, * GD54xx, 1280x1024 mode support, change MCLK based on VCLK. * * Geert Uytterhoeven: * Excellent code review. * * Lars Hecking: * Amiga updates and testing. * * Original cirrusfb author: Frank Neumann * * Based on retz3fb.c and cirrusfb.c: * Copyright (C) 1997 Jes Sorensen * Copyright (C) 1996 Frank Neumann * *************************************************************** * * Format this code with GNU indent '-kr -i8 -pcs' options. * * 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. *
*/
/* * per-board-type information, used for enumerating and abstracting * chip-specific information * NOTE: MUST be in the same order as enum cirrus_board in order to * use direct indexing on this array * NOTE: '__initdata' cannot be used as some of this info * is required at runtime. Maybe separate into an init-only and * a run-time table?
*/ staticconststruct cirrusfb_board_info_rec { char *name; /* ASCII name of chipset */ long maxclock[5]; /* maximum video clock */ /* for 1/4bpp, 8bpp 15/16bpp, 24bpp, 32bpp - numbers from xorg code */ bool init_sr07 : 1; /* init SR07 during init_vgachip() */ bool init_sr1f : 1; /* write SR1F during init_vgachip() */ /* construct bit 19 of screen start address */ bool scrn_start_bit19 : 1;
/* initial SR07 value, then for each mode */ unsignedchar sr07; unsignedchar sr07_1bpp; unsignedchar sr07_1bpp_mux; unsignedchar sr07_8bpp; unsignedchar sr07_8bpp_mux;
#ifdef CONFIG_ZORRO struct zorrocl { enum cirrus_board type; /* Board type */
u32 regoffset; /* Offset of registers in first Zorro device */
u32 ramsize; /* Size of video RAM in first Zorro device */ /* If zero, use autoprobe on RAM device */
u32 ramoffset; /* Offset of video RAM in first Zorro device */
zorro_id ramid; /* Zorro ID of RAM device */
zorro_id ramid2; /* Zorro ID of optional second RAM device */
};
/****************************************************************************/ /**** BEGIN PROTOTYPES ******************************************************/
/*--- Interface used by the world ------------------------------------------*/ staticint cirrusfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info);
/*** END PROTOTYPES ********************************************************/ /*****************************************************************************/ /*** BEGIN Interface Used by the World ***************************************/
/*--- Open /dev/fbx ---------------------------------------------------------*/ staticint cirrusfb_open(struct fb_info *info, int user)
{ if (opencount++ == 0)
switch_monitor(info->par, 1); return 0;
}
/*--- Close /dev/fbx --------------------------------------------------------*/ staticint cirrusfb_release(struct fb_info *info, int user)
{ if (--opencount == 0)
switch_monitor(info->par, 0); return 0;
}
/**** END Interface used by the World *************************************/ /****************************************************************************/ /**** BEGIN Hardware specific Routines **************************************/
/* Check if the MCLK is not a better clock source */ staticint cirrusfb_check_mclk(struct fb_info *info, long freq)
{ struct cirrusfb_info *cinfo = info->par; long mclk = vga_rseq(cinfo->regbase, CL_SEQR1F) & 0x3f;
/* Read MCLK value */
mclk = (14318 * mclk) >> 3;
dev_dbg(info->device, "Read MCLK of %ld kHz\n", mclk);
/* Determine if we should use MCLK instead of VCLK, and if so, what we * should divide it by to get VCLK
*/
/* If the frequency is greater than we can support, we might be able
* to use multiplexing for the video mode */ if (freq > maxclock) {
var->pixclock = KHZ2PICOS(maxclock);
/* * Additional constraint: 8bpp uses DAC clock doubling to allow maximum * pixel clock
*/ if (var->bits_per_pixel == 8) { switch (cinfo->btype) { case BT_ALPINE: case BT_SD64: case BT_PICASSO4: if (freq > 85500)
cinfo->multiplexing = 1; break; case BT_GD5480: if (freq > 135100)
cinfo->multiplexing = 1; break;
default: break;
}
}
/* If we have a 1MB 5434, we need to put ourselves in a mode where
* the VCLK is double the pixel clock. */
cinfo->doubleVCLK = 0; if (cinfo->btype == BT_SD64 && info->fix.smem_len <= MB_ &&
var->bits_per_pixel == 16) {
cinfo->doubleVCLK = 1;
}
pixels = info->screen_size * 8 / var->bits_per_pixel; if (var->xres_virtual < var->xres)
var->xres_virtual = var->xres; /* use highest possible virtual resolution */ if (var->yres_virtual == -1) {
var->yres_virtual = pixels / var->xres_virtual;
dev_info(info->device, "virtual resolution set to maximum of %dx%d\n",
var->xres_virtual, var->yres_virtual);
} if (var->yres_virtual < var->yres)
var->yres_virtual = var->yres;
if (var->xres_virtual * var->yres_virtual > pixels) {
dev_err(info->device, "mode %dx%dx%d rejected... " "virtual resolution too high to fit into video memory!\n",
var->xres_virtual, var->yres_virtual,
var->bits_per_pixel); return -EINVAL;
}
/* truncate xoffset and yoffset to maximum if too high */ if (var->xoffset > var->xres_virtual - var->xres)
var->xoffset = var->xres_virtual - var->xres - 1; if (var->yoffset > var->yres_virtual - var->yres)
var->yoffset = var->yres_virtual - var->yres - 1;
actually writes the values for a new video mode into the hardware,
**************************************************************************/ staticint cirrusfb_set_par_foo(struct fb_info *info)
{ struct cirrusfb_info *cinfo = info->par; struct fb_var_screeninfo *var = &info->var;
u8 __iomem *regbase = cinfo->regbase; unsignedchar tmp; int pitch; conststruct cirrusfb_board_info_rec *bi; int hdispend, hsyncstart, hsyncend, htotal; int yres, vdispend, vsyncstart, vsyncend, vtotal; long freq; int nom, den, div; unsignedint control = 0, format = 0, threshold = 0;
/* if debugging is enabled, all parameters get output before writing */
dev_dbg(info->device, "CRT0: %d\n", htotal);
vga_wcrt(regbase, VGA_CRTC_H_TOTAL, htotal);
if (cinfo->btype == BT_ALPINE || cinfo->btype == BT_PICASSO4 ||
cinfo->btype == BT_SD64) { /* if freq is close to mclk or mclk/2 select mclk * as clock source
*/ int divMCLK = cirrusfb_check_mclk(info, freq); if (divMCLK)
nom = 0;
cirrusfb_set_mclk_as_source(info, divMCLK);
} if (is_laguna(cinfo)) { long pcifc = fb_readl(cinfo->laguna_mmio + 0x3fc); unsignedchar tile = fb_readb(cinfo->laguna_mmio + 0x407); unsignedshort tile_control;
/* don't know if it would hurt to also program this if no interlaced */ /* mode is used, but I feel better this way.. :-) */ if (var->vmode & FB_VMODE_INTERLACED)
vga_wcrt(regbase, VGA_CRTC_REGS, htotal / 2); else
vga_wcrt(regbase, VGA_CRTC_REGS, 0x00); /* interlace control */
/* adjust horizontal/vertical sync type (low/high), use VCLK3 */ /* enable display memory & CRTC I/O address for color mode */
tmp = 0x03 | 0xc; if (var->sync & FB_SYNC_HOR_HIGH_ACT)
tmp |= 0x40; if (var->sync & FB_SYNC_VERT_HIGH_ACT)
tmp |= 0x80;
WGen(cinfo, VGA_MIS_W, tmp);
/* text cursor on and start line */
vga_wcrt(regbase, VGA_CRTC_CURSOR_START, 0); /* text cursor end line */
vga_wcrt(regbase, VGA_CRTC_CURSOR_END, 31);
/* programming for different color depths */ if (var->bits_per_pixel == 1) {
dev_dbg(info->device, "preparing for 1 bit deep display\n");
vga_wgfx(regbase, VGA_GFX_MODE, 0); /* mode register */
/* SR07 */ switch (cinfo->btype) { case BT_SD64: case BT_PICCOLO: case BT_PICASSO: case BT_SPECTRUM: case BT_PICASSO4: case BT_ALPINE: case BT_GD5480:
vga_wseq(regbase, CL_SEQR7,
cinfo->multiplexing ?
bi->sr07_1bpp_mux : bi->sr07_1bpp); break;
case BT_LAGUNA: case BT_LAGUNAB:
vga_wseq(regbase, CL_SEQR7,
vga_rseq(regbase, CL_SEQR7) & ~0x01); break;
elseif (var->bits_per_pixel == 8) {
dev_dbg(info->device, "preparing for 8 bit deep display\n"); switch (cinfo->btype) { case BT_SD64: case BT_PICCOLO: case BT_PICASSO: case BT_SPECTRUM: case BT_PICASSO4: case BT_ALPINE: case BT_GD5480:
vga_wseq(regbase, CL_SEQR7,
cinfo->multiplexing ?
bi->sr07_8bpp_mux : bi->sr07_8bpp); break;
case BT_LAGUNA: case BT_LAGUNAB:
vga_wseq(regbase, CL_SEQR7,
vga_rseq(regbase, CL_SEQR7) | 0x01);
threshold |= 0x10; break;
switch (cinfo->btype) { case BT_PICCOLO: case BT_PICASSO: case BT_SPECTRUM: /* Fast Page-Mode writes */
vga_wseq(regbase, CL_SEQRF, 0xb0); break;
case BT_PICASSO4: #ifdef CONFIG_ZORRO /* ### INCOMPLETE!! */
vga_wseq(regbase, CL_SEQRF, 0xb8); #endif case BT_ALPINE: case BT_SD64: case BT_GD5480: case BT_LAGUNA: case BT_LAGUNAB: /* do nothing */ break;
elseif (var->bits_per_pixel == 16) {
dev_dbg(info->device, "preparing for 16 bit deep display\n"); switch (cinfo->btype) { case BT_PICCOLO: case BT_SPECTRUM:
vga_wseq(regbase, CL_SEQR7, 0x87); /* Fast Page-Mode writes */
vga_wseq(regbase, CL_SEQRF, 0xb0); break;
case BT_PICASSO:
vga_wseq(regbase, CL_SEQR7, 0x27); /* Fast Page-Mode writes */
vga_wseq(regbase, CL_SEQRF, 0xb0); break;
case BT_SD64: case BT_PICASSO4: case BT_ALPINE: /* Extended Sequencer Mode: 256c col. mode */
vga_wseq(regbase, CL_SEQR7,
cinfo->doubleVCLK ? 0xa3 : 0xa7); break;
case BT_GD5480:
vga_wseq(regbase, CL_SEQR7, 0x17); /* We already set SRF and SR1F */ break;
case BT_LAGUNA: case BT_LAGUNAB:
vga_wseq(regbase, CL_SEQR7,
vga_rseq(regbase, CL_SEQR7) & ~0x01);
control |= 0x2000;
format |= 0x1400;
threshold |= 0x10; break;
elseif (var->bits_per_pixel == 24) {
dev_dbg(info->device, "preparing for 24 bit deep display\n"); switch (cinfo->btype) { case BT_PICCOLO: case BT_SPECTRUM:
vga_wseq(regbase, CL_SEQR7, 0x85); /* Fast Page-Mode writes */
vga_wseq(regbase, CL_SEQRF, 0xb0); break;
case BT_PICASSO:
vga_wseq(regbase, CL_SEQR7, 0x25); /* Fast Page-Mode writes */
vga_wseq(regbase, CL_SEQRF, 0xb0); break;
case BT_SD64: case BT_PICASSO4: case BT_ALPINE: /* Extended Sequencer Mode: 256c col. mode */
vga_wseq(regbase, CL_SEQR7, 0xa5); break;
case BT_GD5480:
vga_wseq(regbase, CL_SEQR7, 0x15); /* We already set SRF and SR1F */ break;
case BT_LAGUNA: case BT_LAGUNAB:
vga_wseq(regbase, CL_SEQR7,
vga_rseq(regbase, CL_SEQR7) & ~0x01);
control |= 0x4000;
format |= 0x2400;
threshold |= 0x20; break;
/* for some reason incomprehensible to me, cirrusfb requires that you write
* the registers twice for the settings to take..grr. -dte */ staticint cirrusfb_set_par(struct fb_info *info)
{
cirrusfb_set_par_foo(info); return cirrusfb_set_par_foo(info);
}
/* write pixel panning value to AR33; this does not quite work in 8bpp * * ### Piccolo..? Will this work?
*/ if (info->var.bits_per_pixel == 1)
vga_wattr(cinfo->regbase, CL_AR33, xpix);
return 0;
}
staticint cirrusfb_blank(int blank_mode, struct fb_info *info)
{ /* * Blank the screen if blank_mode != 0, else unblank. If blank == NULL * then the caller blanks by setting the CLUT (Color Look Up Table) * 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 * blank_mode == 3: suspend hsync * blank_mode == 4: powerdown
*/ unsignedchar val; struct cirrusfb_info *cinfo = info->par; int current_mode = cinfo->blank_mode;
/* Undo current */ if (current_mode == FB_BLANK_NORMAL ||
current_mode == FB_BLANK_UNBLANK) /* clear "FullBandwidth" bit */
val = 0; else /* set "FullBandwidth" bit */
val = 0x20;
val |= vga_rseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE) & 0xdf;
vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, val);
switch (blank_mode) { case FB_BLANK_UNBLANK: case FB_BLANK_NORMAL:
val = 0x00; break; case FB_BLANK_VSYNC_SUSPEND:
val = 0x04; break; case FB_BLANK_HSYNC_SUSPEND:
val = 0x02; break; case FB_BLANK_POWERDOWN:
val = 0x06; break; default:
dev_dbg(info->device, "EXIT, returning 1\n"); return 1;
}
/* Let fbcon do a soft blank for us */ return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0;
}
/**** END Hardware specific Routines **************************************/ /****************************************************************************/ /**** BEGIN Internal Routines ***********************************************/
/* make sure RAM size set by this point */
assert(info->screen_size > 0);
/* the P4 is not fully initialized here; I rely on it having been */ /* inited under AmigaOS already, which seems to work just fine */ /* (Klaus advised to do it this way) */
/* "magic cookie" - doesn't make any sense to me.. */ /* vga_wgfx(cinfo->regbase, CL_GRA, 0xce); */ /* unlock all extension registers */
vga_wseq(cinfo->regbase, CL_SEQR6, 0x12);
switch (cinfo->btype) { case BT_GD5480:
vga_wseq(cinfo->regbase, CL_SEQRF, 0x98); break; case BT_ALPINE: case BT_LAGUNA: case BT_LAGUNAB: break; case BT_SD64: #ifdef CONFIG_ZORRO
vga_wseq(cinfo->regbase, CL_SEQRF, 0xb8); #endif break; default:
vga_wseq(cinfo->regbase, CL_SEQR16, 0x0f);
vga_wseq(cinfo->regbase, CL_SEQRF, 0xb0); break;
}
} /* plane mask: nothing */
vga_wseq(cinfo->regbase, VGA_SEQ_PLANE_WRITE, 0xff); /* character map select: doesn't even matter in gx mode */
vga_wseq(cinfo->regbase, VGA_SEQ_CHARACTER_MAP, 0x00); /* memory mode: chain4, ext. memory */
vga_wseq(cinfo->regbase, VGA_SEQ_MEMORY_MODE, 0x0a);
/* controller-internal base address of video memory */ if (bi->init_sr07)
vga_wseq(cinfo->regbase, CL_SEQR7, bi->sr07);
/* vga_wseq(cinfo->regbase, CL_SEQR8, 0x00); */ /* EEPROM control: shouldn't be necessary to write to this at all.. */
/* graphics cursor X position (incomplete; position gives rem. 3 bits */
vga_wseq(cinfo->regbase, CL_SEQR10, 0x00); /* graphics cursor Y position (..."... ) */
vga_wseq(cinfo->regbase, CL_SEQR11, 0x00); /* graphics cursor attributes */
vga_wseq(cinfo->regbase, CL_SEQR12, 0x00); /* graphics cursor pattern address */
vga_wseq(cinfo->regbase, CL_SEQR13, 0x00);
/* writing these on a P4 might give problems.. */ if (cinfo->btype != BT_PICASSO4) { /* configuration readback and ext. color */
vga_wseq(cinfo->regbase, CL_SEQR17, 0x00); /* signature generator */
vga_wseq(cinfo->regbase, CL_SEQR18, 0x02);
}
/* Screen A preset row scan: none */
vga_wcrt(cinfo->regbase, VGA_CRTC_PRESET_ROW, 0x00); /* Text cursor start: disable text cursor */
vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_START, 0x20); /* Text cursor end: - */
vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_END, 0x00); /* text cursor location high: 0 */
vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_HI, 0x00); /* text cursor location low: 0 */
vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_LO, 0x00);
staticvoid switch_monitor(struct cirrusfb_info *cinfo, int on)
{ #ifdef CONFIG_ZORRO /* only works on Zorro boards */ staticint IsOn = 0; /* XXX not ok for multiple boards */
if (cinfo->btype == BT_PICASSO4) return; /* nothing to switch */ if (cinfo->btype == BT_ALPINE) return; /* nothing to switch */ if (cinfo->btype == BT_GD5480) return; /* nothing to switch */ if (cinfo->btype == BT_PICASSO) { if ((on && !IsOn) || (!on && IsOn))
WSFR(cinfo, 0xff); return;
} if (on) { switch (cinfo->btype) { case BT_SD64:
WSFR(cinfo, cinfo->SFR | 0x21); break; case BT_PICCOLO:
WSFR(cinfo, cinfo->SFR | 0x28); break; case BT_SPECTRUM:
WSFR(cinfo, 0x6f); break; default: /* do nothing */ break;
}
} else { switch (cinfo->btype) { case BT_SD64:
WSFR(cinfo, cinfo->SFR & 0xde); break; case BT_PICCOLO:
WSFR(cinfo, cinfo->SFR & 0xd7); break; case BT_SPECTRUM:
WSFR(cinfo, 0x4f); break; default: /* do nothing */ break;
}
} #endif/* CONFIG_ZORRO */
}
/******************************************/ /* Linux 2.6-style accelerated functions */ /******************************************/
/* Pulled the logic from XFree86 Cirrus driver to get the memory size, * based on the DRAM bandwidth bit and DRAM bank switching bit. This * works with 1MB, 2MB and 4MB configurations (which the Motorola boards
* seem to have. */ staticunsignedint cirrusfb_get_memsize(struct fb_info *info,
u8 __iomem *regbase)
{ unsignedlong mem; struct cirrusfb_info *cinfo = info->par;
if (is_laguna(cinfo)) { unsignedchar SR14 = vga_rseq(regbase, CL_SEQR14);
mem = ((SR14 & 7) + 1) << 20;
} else { unsignedchar SRF = vga_rseq(regbase, CL_SEQRF); switch ((SRF & 0x18)) { case 0x08:
mem = 512 * 1024; break; case 0x10:
mem = 1024 * 1024; break; /* 64-bit DRAM data bus width; assume 2MB. * Also indicates 2MB memory on the 5430.
*/ case 0x18:
mem = 2048 * 1024; break; default:
dev_warn(info->device, "Unknown memory size!\n");
mem = 1024 * 1024;
} /* If DRAM bank switching is enabled, there must be * twice as much memory installed. (4MB on the 5434)
*/ if (cinfo->btype != BT_ALPINE && (SRF & 0x80) != 0)
mem *= 2;
}
/* TODO: Handling of GD5446/5480 (see XF86 sources ...) */ return mem;
}
if (cinfo->laguna_mmio == NULL)
iounmap(cinfo->laguna_mmio);
iounmap(info->screen_base); #if 0 /* if system didn't claim this region, we would... */
release_mem_region(0xA0000, 65535); #endif if (release_io_ports)
release_region(0x3C0, 32);
pci_release_regions(pdev);
} #endif/* CONFIG_PCI */
err = cirrusfb_check_var(&info->var, info); if (err < 0) { /* should never happen */
dev_dbg(info->device, "choking on default var... umm, no good.\n"); goto err_dealloc_cmap;
}
dev_dbg(info->device, " Found PCI device, base address 0 is 0x%Lx, btype set to %d\n",
(unsignedlonglong)pdev->resource[0].start, cinfo->btype);
dev_dbg(info->device, " base address 1 is 0x%Lx\n",
(unsignedlonglong)pdev->resource[1].start);
dev_dbg(info->device, "Attempt to get PCI info for Cirrus Graphics Card\n");
get_pci_addrs(pdev, &board_addr, &info->fix.mmio_start); /* FIXME: this forces VGA. alternatives? */
cinfo->regbase = NULL;
cinfo->laguna_mmio = ioremap(info->fix.mmio_start, 0x1000);
ret = pci_request_regions(pdev, "cirrusfb"); if (ret < 0) {
dev_err(info->device, "cannot reserve region 0x%lx, abort\n",
board_addr); goto err_release_fb;
} #if 0 /* if the system didn't claim this region, we would... */ if (!request_mem_region(0xA0000, 65535, "cirrusfb")) {
dev_err(info->device, "cannot reserve region 0x%lx, abort\n",
0xA0000L);
ret = -EBUSY; goto err_release_regions;
} #endif if (request_region(0x3C0, 32, "cirrusfb"))
release_io_ports = 1;
info->screen_base = ioremap(board_addr, board_size); if (!info->screen_base) {
ret = -EIO; goto err_release_legacy;
}
module_param(mode_option, charp, 0);
MODULE_PARM_DESC(mode_option, "Initial video mode e.g. '648x480-8@60'");
module_param(noaccel, bool, 0);
MODULE_PARM_DESC(noaccel, "Disable acceleration");
#ifdef MODULE
module_exit(cirrusfb_exit); #endif
/**********************************************************************/ /* about the following functions - I have used the same names for the */ /* functions as Markus Wild did in his Retina driver for NetBSD as */ /* they just made sense for this purpose. Apart from that, I wrote */ /* these functions myself. */ /**********************************************************************/
/*** WGen() - write into one of the external/general registers ***/ staticvoid WGen(conststruct cirrusfb_info *cinfo, int regnum, unsignedchar val)
{ unsignedlong regofs = 0;
if (cinfo->btype == BT_PICASSO) { /* Picasso II specific hack */ /* if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D ||
regnum == CL_VSSM2) */ if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
regofs = 0xfff;
}
vga_w(cinfo->regbase, regofs + regnum, val);
}
/*** RGen() - read out one of the external/general registers ***/ staticunsignedchar RGen(conststruct cirrusfb_info *cinfo, int regnum)
{ unsignedlong regofs = 0;
if (cinfo->btype == BT_PICASSO) { /* Picasso II specific hack */ /* if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D ||
regnum == CL_VSSM2) */ if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
regofs = 0xfff;
}
return vga_r(cinfo->regbase, regofs + regnum);
}
/*** AttrOn() - turn on VideoEnable for Attribute controller ***/ staticvoid AttrOn(conststruct cirrusfb_info *cinfo)
{
assert(cinfo != NULL);
if (vga_rcrt(cinfo->regbase, CL_CRT24) & 0x80) { /* if we're just in "write value" mode, write back the */ /* same value as before to not modify anything */
vga_w(cinfo->regbase, VGA_ATT_IW,
vga_r(cinfo->regbase, VGA_ATT_R));
} /* turn on video bit */ /* vga_w(cinfo->regbase, VGA_ATT_IW, 0x20); */
vga_w(cinfo->regbase, VGA_ATT_IW, 0x33);
/* dummy write on Reg0 to be on "write index" mode next time */
vga_w(cinfo->regbase, VGA_ATT_IW, 0x00);
}
/*** WHDR() - write into the Hidden DAC register ***/ /* as the HDR is the only extension register that requires special treatment * (the other extension registers are accessible just like the "ordinary" * registers of their functional group) here is a specialized routine for * accessing the HDR
*/ staticvoid WHDR(conststruct cirrusfb_info *cinfo, unsignedchar val)
{ if (is_laguna(cinfo)) return; if (cinfo->btype == BT_PICASSO) { /* Klaus' hint for correct access to HDR on some boards */ /* first write 0 to pixel mask (3c6) */
WGen(cinfo, VGA_PEL_MSK, 0x00);
udelay(200); /* next read dummy from pixel address (3c8) */
RGen(cinfo, VGA_PEL_IW);
udelay(200);
} /* now do the usual stuff to access the HDR */
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.