diff options
-rw-r--r-- | man/chips.man | 218 | ||||
-rw-r--r-- | src/ct_BlitMM.h | 140 | ||||
-rw-r--r-- | src/ct_Blitter.h | 168 | ||||
-rw-r--r-- | src/ct_BltHiQV.h | 178 | ||||
-rw-r--r-- | src/ct_accel.c | 1737 | ||||
-rw-r--r-- | src/ct_bank.c | 626 | ||||
-rw-r--r-- | src/ct_cursor.c | 481 | ||||
-rw-r--r-- | src/ct_ddc.c | 282 | ||||
-rw-r--r-- | src/ct_dga.c | 316 | ||||
-rw-r--r-- | src/ct_driver.c | 7487 | ||||
-rw-r--r-- | src/ct_driver.h | 553 | ||||
-rw-r--r-- | src/ct_regs.c | 535 | ||||
-rw-r--r-- | src/ct_shadow.c | 243 | ||||
-rw-r--r-- | src/ct_video.c | 1163 | ||||
-rw-r--r-- | util/AsmMacros.h | 450 | ||||
-rw-r--r-- | util/dRegs.c | 305 | ||||
-rw-r--r-- | util/mRegs.c | 186 | ||||
-rw-r--r-- | util/modClock.c | 412 |
18 files changed, 15480 insertions, 0 deletions
diff --git a/man/chips.man b/man/chips.man new file mode 100644 index 0000000..ad05ba6 --- /dev/null +++ b/man/chips.man @@ -0,0 +1,218 @@ +.\" $XFree86: xc/programs/Xserver/hw/xfree86/drivers/chips/chips.man,v 1.5 2002/01/04 21:22:27 tsi Exp $ +.\" shorthand for double quote that works everywhere. +.ds q \N'34' +.TH CHIPS __drivermansuffix__ __vendorversion__ +.SH NAME +chips \- Chips and Technologies video driver +.SH SYNOPSIS +.nf +.B "Section \*qDevice\*q" +.BI " Identifier \*q" devname \*q +.B " Driver \*qchips\*q" +\ \ ... +.B EndSection +.fi +.SH DESCRIPTION +.B chips +is an XFree86 driver for Chips and Technologies video processors. The majority +of the Chips and Technologies chipsets are supported by this driver. In general +the limitation on the capabilities of this driver are determined by the +chipset on which it is run. Where possible, this driver provides full +acceleration and supports the following depths: 1, 4, 8, 15, 16, 24 and on +the latest chipsets an 8+16 overlay mode. All visual types are supported for +depth 1, 4 and 8 and both TrueColor and DirectColor visuals are supported +where possible. Multi-head configurations are supported on PCI or AGP buses. +.SH SUPPORTED HARDWARE +The +.B chips +driver supports video processors on most of the bus types currently available. +The chipsets supported fall into one of three architectural classes. A +.B basic +architecture, the +.B WinGine +architecture and the newer +.B HiQV +architecture. +.PP +.B Basic Architecture +.PP +The supported chipsets are +.B ct65520, ct65525, ct65530, ct65535, ct65540, ct65545, ct65546 +and +.B ct65548 +.PP +Color depths 1, 4 and 8 are supported on all chipsets, while depths 15, 16 +and 24 are supported only on the +.B 65540, 65545, 65546 +and +.B 65548 +chipsets. The driver is accelerated when used with the +.B 65545, 65546 +or +.B 65548 +chipsets, however the DirectColor visual is not available. +.PP +.B Wingine Architecture +.PP +The supported chipsets are +.B ct64200 +and +.B ct64300 +.PP +Color depths 1, 4 and 8 are supported on both chipsets, while depths 15, 16 +and 24 are supported only on the +.B 64300 +chipsets. The driver is accelerated when used with the +.B 64300 +chipsets, however the DirectColor visual is not available. +.PP +.B HiQV Architecture +.PP +The supported chipsets are +.B ct65550, ct65554, ct65555, ct68554, ct69000 +and +.B ct69030 +.PP +Color depths 1, 4, 8, 15, 16, 24 and 8+16 are supported on all chipsets. +The DirectColor visual is supported on all color depths except the 8+16 +overlay mode. Full acceleration is supplied for all chipsets. +.SH CONFIGURATION DETAILS +Please refer to XF86Config(__filemansuffix__) for general configuration +details. This section only covers configuration details specific to this +driver. +.PP +The driver auto-detects the chipset type, but the following +.B ChipSet +names may optionally be specified in the config file +.B \*qDevice\*q +section, and will override the auto-detection: +.PP +.RS 4 +"ct65520", "ct65525", "ct65530", "ct65535", "ct65540", "ct65545", "ct65546", +"ct65548", "ct65550", "ct65554", "ct65555", "ct68554", "ct69000", "ct69030", +"ct64200", "ct64300". +.RE +.PP +The driver will auto-detect the amount of video memory present for all +chipsets. But maybe overridden with the +.B VideoRam +entry in the config file +.B \*qDevice\*q +section. +.PP +The following driver +.B Options +are supported, on one or more of the supported chipsets: +.TP +.BI "Option \*qNoAccel\*q \*q" boolean \*q +Disable or enable acceleration. Default: acceleration is enabled. +.TP +.BI "Option \*qNoLinear\*q \*q" boolean \*q +Disables linear addressing in cases where it is enabled by default. +Default: off +.TP +.BI "Option \*qLinear\*q \*q" boolean \*q +Enables linear addressing in cases where it is disabled by default. +Default: off +.TP +.BI "Option \*qHWCursor\*q \*q" boolean \*q +Enable or disable the HW cursor. Default: on. +.TP +.BI "Option \*qSWCursor\*q \*q" boolean \*q +Enable or disable the HW cursor. Default: off. +.TP +.BI "Option \*qSTN\*q \*q" boolean \*q +Force detection of STN screen type. Default: off. +.TP +.BI "Option \*qUseModeline\*q \*q" boolean \*q +Reprogram flat panel timings with values from the modeline. Default: off +.TP +.BI "Option \*qFixPanelSize\*q \*q" boolean \*q +Reprogram flat panel size with values from the modeline. Default: off +.TP +.BI "Option \*qNoStretch\*q \*q" boolean \*q +This option disables the stretching on a mode on a flat panel to fill the +screen. Default: off +.TP +.BI "Option \*qLcdCenter\*q \*q" boolean \*q +Center the mode displayed on the flat panel on the screen. Default: off +.TP +.BI "Option \*qHWclocks\*q \*q" boolean \*q +Force the use of fixed hardware clocks on chips that support both fixed +and programmable clocks. Default: off +.TP +.BI "Option \*qUseVclk1\*q \*q" boolean \*q +Use the Vclk1 programmable clock on +.B HiQV +chipsets instead of Vclk2. Default: off +.TP +.BI "Option \*qFPClock8\*q \*q" float \*q +.TP +.BI "Option \*qFPClock16\*q \*q" float \*q +.TP +.BI "Option \*qFPClock24\*q \*q" float \*q +.TP +.BI "Option \*qFPClock32\*q \*q" float \*q +Force the use of a particular video clock speed for use with the +flat panel at a specified depth +.TP +.BI "Option \*qMMIO\*q \*q" boolean \*q +Force the use of memory mapped IO for acceleration registers. Default: off +.TP +.BI "Option \*qFullMMIO\*q \*q" boolean \*q +Force the use of memory mapped IO where it can be used. Default: off +.TP +.BI "Option \*qSuspendHack\*q \*q" boolean \*q +Force driver to leave centering and stretching registers alone. This +can fix some laptop suspend/resume problems. Default: off +.TP +.BI "Option \*qOverlay\*q" +Enable 8+24 overlay mode. Only appropriate for depth 24. Default: off. +.TP +.BI "Option \*qColorKey\*q \*q" integer \*q +Set the colormap index used for the transparency key for the depth 8 plane +when operating in 8+16 overlay mode. The value must be in the range +2\-255. Default: 255. +.TP +.BI "Option \*qVideoKey\*q \*q" integer \*q +This sets the default pixel value for the YUV video overlay key. +Default: undefined. +.TP +.BI "Option \*qShadowFB\*q \*q" boolean \*q +Enable or disable use of the shadow framebuffer layer. Default: off. +.TP +.BI "Option \*qSyncOnGreen\*q \*q" boolean \*q +Enable or disable combining the sync signals with the green signal. +Default: off. +.TP +.BI "Option \*qShowCache\*q \*q" boolean \*q +Enable or disable viewing offscreen memory. Used for debugging only +Default: off. +.TP +.BI "Option \*q18bitBus\*q \*q" boolean \*q +Force the driver to assume that the flat panel has an 18bit data bus. +Default: off. +.TP +.BI "Option \*qCrt2Memory\*q \*q" integer \*q +In a dual-head mode (69030 only) this option selects the amount of memory +to set aside for the second head. If not specified, half the memory is used. +Default: off. +.TP +.BI "Option \*qDualRefresh\*q \*q" integer \*q +The 69030 supports independent refresh rates on its two display channels. +This mode of operations uses additional memory bandwidth and thus limits +the maximum colour depth and refresh rate that can be achieved, and so is +off by default. Using this option forces the use of an independent refresh +rate on the two screens. +Default: off. +.SH "SEE ALSO" +XFree86(1), XF86Config(__filemansuffix__), xf86config(1), Xserver(1), X(__miscmansuffix__) +.PP +You are also recommended to read the README.chips file that comes with all +XFree86 distributions, which discusses the +.B chips +driver in more detail. +.SH AUTHORS +Authors include: Jon Block, Mike Hollick, Regis Cridlig, Nozomi Ytow, +Egbert Eich, David Bateman and Xavier Ducoin + diff --git a/src/ct_BlitMM.h b/src/ct_BlitMM.h new file mode 100644 index 0000000..7660241 --- /dev/null +++ b/src/ct_BlitMM.h @@ -0,0 +1,140 @@ +/* $XConsortium: ct_BlitMM.h /main/2 1996/10/25 10:28:31 kaleb $ */ + + + + + +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/chips/ct_BlitMM.h,v 1.5 2002/11/25 14:04:58 eich Exp $ */ + +/* Definitions for the Chips and Technology BitBLT engine communication. */ +/* These are done using Memory Mapped IO, of the registers */ +/* BitBLT modes for register 93D0. */ + +#define ctPATCOPY 0xF0 +#define ctTOP2BOTTOM 0x100 +#define ctBOTTOM2TOP 0x000 +#define ctLEFT2RIGHT 0x200 +#define ctRIGHT2LEFT 0x000 +#define ctSRCFG 0x400 +#define ctSRCMONO 0x800 +#define ctPATMONO 0x1000 +#define ctBGTRANSPARENT 0x2000 +#define ctSRCSYSTEM 0x4000 +#define ctPATSOLID 0x80000L +#define ctPATSTART0 0x00000L +#define ctPATSTART1 0x10000L +#define ctPATSTART2 0x20000L +#define ctPATSTART3 0x30000L +#define ctPATSTART4 0x40000L +#define ctPATSTART5 0x50000L +#define ctPATSTART6 0x60000L +#define ctPATSTART7 0x70000L + +/* Macros to do useful things with the C&T BitBLT engine */ +#define ctBLTWAIT \ + {HW_DEBUG(0x4); \ + while(MMIO_IN32(cPtr->MMIOBase, MR(0x4)) & 0x00100000){};} + +#define ctSETROP(op) \ + {HW_DEBUG(0x4); MMIO_OUT32(cPtr->MMIOBase, MR(0x4), op);} + +#define ctSETSRCADDR(srcAddr) \ + {HW_DEBUG(0x5); \ + MMIO_OUT32(cPtr->MMIOBase, MR(0x5),(srcAddr)&0x7FFFFFL);} + +#define ctSETDSTADDR(dstAddr) \ +{HW_DEBUG(0x6); \ + MMIO_OUT32(cPtr->MMIOBase, MR(0x6), (dstAddr)&0x7FFFFFL);} + +#define ctSETPITCH(srcPitch,dstPitch) \ +{HW_DEBUG(0x0); \ + MMIO_OUT32(cPtr->MMIOBase, MR(0x0),(((dstPitch)&0xFFFF)<<16)| \ + ((srcPitch)&0xFFFF));} + +#define ctSETHEIGHTWIDTHGO(Height,Width)\ +{HW_DEBUG(0x7); \ + MMIO_OUT32(cPtr->MMIOBase, MR(0x7), (((Height)&0xFFFF)<<16)| \ + ((Width)&0xFFFF));} + +#define ctSETPATSRCADDR(srcAddr)\ +{HW_DEBUG(0x1); \ + MMIO_OUT32(cPtr->MMIOBase, MR(0x1),(srcAddr)&0x1FFFFFL);} + +#define ctSETBGCOLOR8(c) {\ + HW_DEBUG(0x2); \ + if ((cAcl->bgColor != (c)) || (cAcl->bgColor == -1)) { \ + cAcl->bgColor = (c); \ + MMIO_OUT32(cPtr->MMIOBase, MR(0x2),\ + ((((((c)&0xFF)<<8)|((c)&0xFF))<<16) | \ + ((((c)&0xFF)<<8)|((c)&0xFF)))); \ + } \ +} + +#define ctSETBGCOLOR16(c) {\ + HW_DEBUG(0x2); \ + if ((cAcl->bgColor != (c)) || (cAcl->bgColor == -1)) { \ + cAcl->bgColor = (c); \ + MMIO_OUT32(cPtr->MMIOBase, MR(0x2), \ + ((((c)&0xFFFF)<<16)|((c)&0xFFFF))); \ + } \ +} + +/* As the 6554x doesn't support 24bpp colour expansion this doesn't work, + * It is here only for later use with the 65550 */ +#define ctSETBGCOLOR24(c) {\ + HW_DEBUG(0x2); \ + if ((cAcl->bgColor != (c)) || (cAcl->bgColor == -1)) { \ + cAcl->bgColor = (c); \ + MMIO_OUT32(cPtr->MMIOBase, MR(0x2),((c)&0xFFFFFF)); \ + } \ +} + +#define ctSETFGCOLOR8(c) {\ + HW_DEBUG(0x3); \ + if ((cAcl->fgColor != (c)) || (cAcl->fgColor == -1)) { \ + cAcl->fgColor = (c); \ + MMIO_OUT32(cPtr->MMIOBase, MR(0x3), \ + ((((((c)&0xFF)<<8)|((c)&0xFF))<<16) | \ + ((((c)&0xFF)<<8)|((c)&0xFF)))); \ + } \ +} + +#define ctSETFGCOLOR16(c) {\ + HW_DEBUG(0x3); \ + if ((cAcl->fgColor != (c)) || (cAcl->fgColor == -1)) { \ + cAcl->fgColor = (c); \ + MMIO_OUT32(cPtr->MMIOBase, MR(0x3), \ + ((((c)&0xFFFF)<<16)|((c)&0xFFFF))); \ + } \ +} + +/* As the 6554x doesn't support 24bpp colour expansion this doesn't work, + * It is here only for later use with the 65550 */ +#define ctSETFGCOLOR24(c) {\ + HW_DEBUG(0x3); \ + if ((cAcl->fgColor != (c)) || (cAcl->fgColor == -1)) { \ + cAcl->fgColor = (c); \ + MMIO_OUT32(cPtr->MMIOBase, MR(0x3),((c)&0xFFFFFF)); \ + } \ +} + +/* Define a Macro to replicate a planemask 64 times and write to address + * allocated for planemask pattern */ +#define ctWRITEPLANEMASK8(mask,addr) { \ + if (cAcl->planemask != (mask&0xFF)) { \ + cAcl->planemask = (mask&0xFF); \ + memset((unsigned char *)cPtr->FbBase + addr, (mask&0xFF), 64); \ + } \ +} + +#define ctWRITEPLANEMASK16(mask,addr) { \ + if (cAcl->planemask != (mask&0xFFFF)) { \ + cAcl->planemask = (mask&0xFFFF); \ + { int i; \ + for (i = 0; i < 64; i++) { \ + memcpy((unsigned char *)cPtr->FbBase + addr \ + + i * 2, &mask, 2); \ + } \ + } \ + } \ +} diff --git a/src/ct_Blitter.h b/src/ct_Blitter.h new file mode 100644 index 0000000..ecb84f1 --- /dev/null +++ b/src/ct_Blitter.h @@ -0,0 +1,168 @@ +/* $XConsortium: ct_Blitter.h /main/2 1996/10/25 10:28:37 kaleb $ */ + + + + + +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/chips/ct_Blitter.h,v 1.4 2002/01/25 21:55:58 tsi Exp $ */ + +/* Definitions for the Chips and Technology BitBLT engine communication. */ +/* registers */ +/* Do not read 87D0 while BitBLT is active */ +/* 83D0: 11-0 source offset, width of 'screen' */ +/* 15-12 reserved (0) */ +/* 27-16 destination offset, width of screen */ +/* 31-28 reserved (0) */ +/* 87D0: 20-0 pattern (alinged 8 pixel x 8 line) pointer */ +/* 31-21 reserved (0) */ +/* 8BD0: 15-0 backgroud colour */ +/* 31-6 duplicate of 15-0 */ +/* 8FD0: 15-0 foregroud/solid colour */ +/* 31-6 duplicate of 15-0 */ +/* 93D0: 7-0 ROP, same as MS-Windows */ +/* 8 BitBLT Y direction, if 0 bottom to top, 1 top to bottom */ +/* 9 BitBLT X direction, if 0 right to left, 1 left to right */ +/* 10 source data, if 0 source is selected bit 14, 1 foregourd colour */ +/* 11 source depth, if 0 source is colour, */ +/* 1 source is monochrome(Font expansion) */ +/* 12 pattern depth, if 0 colour, else monochrome */ +/* 13 background, if 0 opaque (8BD0), else transparent */ +/* 14 BitBLT source, if 0 screen, else system memory */ +/* 15 reserved (0, destination?) */ +/* 18-16 starting row of 8x8 pattern */ +/* 19 if 1 solid pattern (Brush), else bitmap */ +/* 20(R) BitBLT status, if 1 active */ +/* 23-21 reserved (0) */ +/* 27-24 vacancy in buffer */ +/* 31-25 reserved (0) */ +/* 97D0: 20-0 source address (byte aligned) */ +/* 31-21 reserved (0) */ +/* 9BD0: 20-0 destination address (byte aligned) */ +/* 31-21 reserved (0) */ +/* 9FD0: 11-0 number of bytes to be transferred per line */ +/* 15-12 reserved (0) */ +/* 27-16 height in lines of the block to be transferred */ +/* 31-28 reserved (0) */ + +/* BitBLT modes for register 93D0. */ + +#define ctPATCOPY 0xF0 +#define ctTOP2BOTTOM 0x100 +#define ctBOTTOM2TOP 0x000 +#define ctLEFT2RIGHT 0x200 +#define ctRIGHT2LEFT 0x000 +#define ctSRCFG 0x400 +#define ctSRCMONO 0x800 +#define ctPATMONO 0x1000 +#define ctBGTRANSPARENT 0x2000 +#define ctSRCSYSTEM 0x4000 +#define ctPATSOLID 0x80000L +#define ctPATSTART0 0x00000L +#define ctPATSTART1 0x10000L +#define ctPATSTART2 0x20000L +#define ctPATSTART3 0x30000L +#define ctPATSTART4 0x40000L +#define ctPATSTART5 0x50000L +#define ctPATSTART6 0x60000L +#define ctPATSTART7 0x70000L + +/* Macros to do useful things with the C&T BitBLT engine */ + +#define ctBLTWAIT \ + {HW_DEBUG(0x4+2); while(inw(cPtr->PIOBase+DR(0x4)+2)&0x10){};} + +#define ctSETROP(op) \ + {HW_DEBUG(0x4); outl(cPtr->PIOBase+DR(0x4),(op));} + +#define ctSETSRCADDR(srcAddr) \ + {HW_DEBUG(0x5); outl(cPtr->PIOBase+DR(0x5),((srcAddr)&0x1FFFFFL));} + +#define ctSETDSTADDR(dstAddr) \ + {HW_DEBUG(0x6); outl(cPtr->PIOBase+DR(0x6),((dstAddr)&0x1FFFFFL));} + +#define ctSETPITCH(srcPitch,dstPitch) \ + {HW_DEBUG(0x0); outl(cPtr->PIOBase+DR(0x0),(((dstPitch)<<16)|(srcPitch)));} + +/* Note that this command signal a blit to commence */ +#define ctSETHEIGHTWIDTHGO(Height,Width)\ + {HW_DEBUG(0x7); outl(cPtr->PIOBase+DR(0x7),(((Height)<<16)|(Width)));} + +#define ctSETPATSRCADDR(srcAddr)\ + {HW_DEBUG(0x1); outl(cPtr->PIOBase+DR(0x1),((srcAddr)&0x1FFFFFL));} + +/* I can't help pointing out at this point that I'm not complaining + * about the american spelling of Colour!! [DGB] */ + +#define ctSETBGCOLOR8(c) {\ + HW_DEBUG(0x2); \ + if ((cAcl->bgColor != (c)) || (cAcl->bgColor == -1)) { \ + cAcl->bgColor = (c); \ + outl(cPtr->PIOBase+DR(0x2),((((((c)&0xFF)<<8)|((c)&0xFF))<<16) | \ + ((((c)&0xFF)<<8)|((c)&0xFF)))); \ + } \ +} + +#define ctSETBGCOLOR16(c) {\ + HW_DEBUG(0x2); \ + if ((cAcl->bgColor != (c)) || (cAcl->bgColor == -1)) { \ + cAcl->bgColor = (c); \ + outl(cPtr->PIOBase+DR(0x2),((((c)&0xFFFF)<<16)|((c)&0xFFFF))); \ + } \ +} + +/* As the 6554x doesn't support 24bpp colour expansion this doesn't work */ +#define ctSETBGCOLOR24(c) {\ + HW_DEBUG(0x2); \ + if ((cAcl->bgColor != (c)) || (cAcl->bgColor == -1)) { \ + cAcl->bgColor = (c); \ + outl(cPtr->PIOBase+DR(0x2),(c)&0xFFFFFF); \ + } \ +} + +#define ctSETFGCOLOR8(c) {\ + HW_DEBUG(0x3); \ + if ((cAcl->fgColor != (c)) || (cAcl->fgColor == -1)) { \ + cAcl->fgColor = (c); \ + outl(cPtr->PIOBase+DR(0x3),((((((c)&0xFF)<<8)|((c)&0xFF))<<16) | \ + ((((c)&0xFF)<<8)|((c)&0xFF)))); \ + } \ +} + +#define ctSETFGCOLOR16(c) {\ + HW_DEBUG(0x3); \ + if ((cAcl->fgColor != (c)) || (cAcl->fgColor == -1)) { \ + cAcl->fgColor = (c); \ + outl(cPtr->PIOBase+DR(0x3),((((c)&0xFFFF)<<16)|((c)&0xFFFF))); \ + } \ +} + +/* As the 6554x doesn't support 24bpp colour expansion this doesn't work */ +#define ctSETFGCOLOR24(c) {\ + HW_DEBUG(0x3); \ + if ((cAcl->fgColor != (c)) || (cAcl->fgColor == -1)) { \ + cAcl->fgColor = (c); \ + outl(cPtr->PIOBase+DR(0x3),(c)&0xFFFFFF); \ + } \ +} + +/* Define a Macro to replicate a planemask 64 times and write to address + * allocated for planemask pattern */ +#define ctWRITEPLANEMASK8(mask,addr) { \ + if (cAcl->planemask != (mask&0xFF)) { \ + cAcl->planemask = (mask&0xFF); \ + memset((unsigned char *)cPtr->FbBase + addr, (mask&0xFF), 64); \ + } \ +} + +#define ctWRITEPLANEMASK16(mask,addr) { \ + if (cAcl->planemask != (mask&0xFFFF)) { \ + cAcl->planemask = (mask&0xFFFF); \ + { int i; \ + for (i = 0; i < 64; i++) { \ + memcpy((unsigned char *)cPtr->FbBase + addr \ + + i * 2, &mask, 2); \ + } \ + } \ + } \ +} + diff --git a/src/ct_BltHiQV.h b/src/ct_BltHiQV.h new file mode 100644 index 0000000..6f135bd --- /dev/null +++ b/src/ct_BltHiQV.h @@ -0,0 +1,178 @@ +/* $XConsortium: ct_BltHiQV.h /main/2 1996/10/25 10:28:43 kaleb $ */ + + + + + +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/chips/ct_BltHiQV.h,v 1.12 2002/11/25 14:04:58 eich Exp $ */ + +/* Definitions for the Chips and Technology BitBLT engine communication. */ +/* These are done using Memory Mapped IO, of the registers */ +/* BitBLT modes for register 93D0. */ + +#define ctPATCOPY 0xF0 +#define ctLEFT2RIGHT 0x000 +#define ctRIGHT2LEFT 0x100 +#define ctTOP2BOTTOM 0x000 +#define ctBOTTOM2TOP 0x200 +#define ctSRCSYSTEM 0x400 +#define ctDSTSYSTEM 0x800 +#define ctSRCMONO 0x1000 +#define ctBGTRANSPARENT 0x22000 +#define ctCOLORTRANSENABLE 0x4000 +#define ctCOLORTRANSDISABLE 0x0 +#define ctCOLORTRANSDST 0x8000 +#define ctCOLORTRANSROP 0x0 +#define ctCOLORTRANSEQUAL 0x10000L +#define ctCOLORTRANSNEQUAL 0x0 +#define ctPATMONO 0x40000L +#define ctPATSOLID 0x80000L +#define ctPATSTART0 0x000000L +#define ctPATSTART1 0x100000L +#define ctPATSTART2 0x200000L +#define ctPATSTART3 0x300000L +#define ctPATSTART4 0x400000L +#define ctPATSTART5 0x500000L +#define ctPATSTART6 0x600000L +#define ctPATSTART7 0x700000L +#define ctSRCFG 0x000000L /* Where is this for the 65550?? */ + +/* The Monochrome expansion register setup */ +#define ctCLIPLEFT(clip) ((clip)&0x3F) +#define ctCLIPRIGHT(clip) (((clip)&0x3F) << 8) +#define ctSRCDISCARD(clip) (((clip)&0x3F) << 16) +#define ctBITALIGN 0x1000000L +#define ctBYTEALIGN 0x2000000L +#define ctWORDALIGN 0x3000000L +#define ctDWORDALIGN 0x4000000L +#define ctQWORDALIGN 0x5000000L +/* This shouldn't be used because not all chip rev's + * have BR09 and BR0A, and I haven't even defined + * macros to write to these registers + */ +#define ctEXPCOLSEL 0x8000000L + +/* Macros to do useful things with the C&T BitBLT engine */ + +/* For some odd reason the blitter busy bit occasionly "locks up" when + * it gets polled to fast. However I have observed this behavior only + * when doing ScreenToScreenColorExpandFill on a 65550. This operation + * was broken anyway (the source offest register is not observed) therefore + * no action was taken. + * + * This function uses indirect access to XR20 to test whether the blitter + * is busy. If the cost of doing this is too high then other options will + * need to be considered. + * + * Note that BR04[31] can't be used as some C&T chipsets lockup when reading + * the BRxx registers. + */ +#define ctBLTWAIT \ + {int timeout; \ + timeout = 0; \ + for (;;) { \ + if (cPtr->Chipset >= CHIPS_CT69000 ) { \ + if (!(MMIO_IN32(cPtr->MMIOBase,BR(0x4))&(1<<31)))\ + break; \ + } else { \ + if (!(cPtr->readXR(cPtr,0x20) & 0x1)) break; \ + } \ + timeout++; \ + if ((cPtr->Chipset < CHIPS_CT69000 && \ + (timeout > 100000)) || timeout > 300000) { \ + unsigned char tmp; \ + ErrorF("timeout\n"); \ + tmp = cPtr->readXR(cPtr, 0x20); \ + cPtr->writeXR(cPtr, 0x20, ((tmp & 0xFD) | 0x2)); \ + xf86UDelay(10000); \ + cPtr->writeXR(cPtr, 0x20, (tmp & 0xFD)); \ + break; \ + } \ + } \ + } + +#define ctSETROP(op) \ + MMIO_OUT32(cPtr->MMIOBase, BR(0x4), op) + +#define ctSETMONOCTL(op) \ + MMIO_OUT32(cPtr->MMIOBase, BR(0x3), op) + +#define ctSETSRCADDR(srcAddr) \ + MMIO_OUT32(cPtr->MMIOBase, BR(0x6), (srcAddr)&0x7FFFFFL) + +#define ctSETDSTADDR(dstAddr) \ + MMIO_OUT32(cPtr->MMIOBase, BR(0x7), (dstAddr)&0x7FFFFFL) + +#define ctSETPITCH(srcPitch,dstPitch) \ + MMIO_OUT32(cPtr->MMIOBase, BR(0x0), (((dstPitch)&0xFFFF)<<16)| \ + ((srcPitch)&0xFFFF)) + +#define ctSETHEIGHTWIDTHGO(Height,Width)\ + MMIO_OUT32(cPtr->MMIOBase, BR(0x8), (((Height)&0xFFFF)<<16)| \ + ((Width)&0xFFFF)) + +#define ctSETPATSRCADDR(srcAddr)\ + MMIO_OUT32(cPtr->MMIOBase, BR(0x5), (srcAddr)&0x7FFFFFL) + +#define ctSETBGCOLOR8(c) {\ + if ((cAcl->bgColor != (c)) || (cAcl->bgColor == -1)) { \ + cAcl->bgColor = (c); \ + MMIO_OUT32(cPtr->MMIOBase, BR(0x1), ((c)&0xFF)); \ + } \ +} + +#define ctSETBGCOLOR16(c) {\ + if ((cAcl->bgColor != (c)) || (cAcl->bgColor == -1)) { \ + cAcl->bgColor = (c); \ + MMIO_OUT32(cPtr->MMIOBase, BR(0x1), ((c)&0xFFFF)); \ + } \ +} + +#define ctSETBGCOLOR24(c) {\ + if ((cAcl->bgColor != (c)) || (cAcl->bgColor == -1)) { \ + cAcl->bgColor = (c); \ + MMIO_OUT32(cPtr->MMIOBase, BR(0x1), ((c)&0xFFFFFF)); \ + } \ +} + +#define ctSETFGCOLOR8(c) {\ + if ((cAcl->fgColor != (c)) || (cAcl->fgColor == -1)) { \ + cAcl->fgColor = (c); \ + MMIO_OUT32(cPtr->MMIOBase, BR(0x2), ((c)&0xFF)); \ + } \ +} + +#define ctSETFGCOLOR16(c) {\ + if ((cAcl->fgColor != (c)) || (cAcl->fgColor == -1)) { \ + cAcl->fgColor = (c); \ + MMIO_OUT32(cPtr->MMIOBase, BR(0x2), ((c)&0xFFFF)); \ + } \ +} + +#define ctSETFGCOLOR24(c) {\ + if ((cAcl->fgColor != (c)) || (cAcl->fgColor == -1)) { \ + cAcl->fgColor = (c); \ + MMIO_OUT32(cPtr->MMIOBase, BR(0x2), ((c)&0xFFFFFF)); \ + } \ +} + +/* Define a Macro to replicate a planemask 64 times and write to address + * allocated for planemask pattern */ +#define ctWRITEPLANEMASK8(mask,addr) { \ + if (cAcl->planemask != (mask&0xFF)) { \ + cAcl->planemask = (mask&0xFF); \ + memset((unsigned char *)cPtr->FbBase + addr, (mask&0xFF), 64); \ + } \ +} + +#define ctWRITEPLANEMASK16(mask,addr) { \ + if (cAcl->planemask != (mask&0xFFFF)) { \ + cAcl->planemask = (mask&0xFFFF); \ + { int i; \ + for (i = 0; i < 64; i++) { \ + memcpy((unsigned char *)cPtr->FbBase + addr \ + + i * 2, &mask, 2); \ + } \ + } \ + } \ +} diff --git a/src/ct_accel.c b/src/ct_accel.c new file mode 100644 index 0000000..d936291 --- /dev/null +++ b/src/ct_accel.c @@ -0,0 +1,1737 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/chips/ct_accel.c,v 1.40 2002/11/25 14:04:58 eich Exp $ */ +/* + * Copyright 1996, 1997, 1998 by David Bateman <dbateman@ee.uts.edu.au> + * Modified 1997, 1998 by Nozomi Ytow + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the authors not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. The authors makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * When monochrome tiles/stipples are cached on the HiQV chipsets the + * pitch of the monochrome data is the displayWidth. The HiQV manuals + * state that the source pitch is ignored with monochrome data, and so + * "offically" there the XAA cached monochrome data can't be used. But + * it appears that by not setting the monochrome source alignment in + * BR03, the monochrome source pitch is forced to the displayWidth!! + * + * To enable the use of this undocumented feature, uncomment the define + * below. + */ +#define UNDOCUMENTED_FEATURE + +/* All drivers should typically include these */ +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86_ansic.h" +#include "compiler.h" + +/* Drivers that need to access the PCI config space directly need this */ +#include "xf86Pci.h" + +/* Drivers for PCI hardware need this */ +#include "xf86PciInfo.h" + +/* Drivers that use XAA need this */ +#include "xf86fbman.h" + +/* Our driver specific include file */ +#include "ct_driver.h" + +#if !defined(UNIXCPP) || defined(ANSICPP) +#define CATNAME(prefix,subname) prefix##subname +#else +#define CATNAME(prefix,subname) prefix/**/subname +#endif + +#ifdef CHIPS_MMIO +#ifdef CHIPS_HIQV +#include "ct_BltHiQV.h" +#define CTNAME(subname) CATNAME(CHIPSHiQV,subname) +#else +#include "ct_BlitMM.h" +#define CTNAME(subname) CATNAME(CHIPSMMIO,subname) +#endif +#else +#include "ct_Blitter.h" +#define CTNAME(subname) CATNAME(CHIPS,subname) +#endif + +#ifdef DEBUG +# define DEBUG_P(x) ErrorF(x"\n"); +#elif defined X_DEBUG +# define DEBUG_P(x) snprintf(CTNAME(accel_debug),1024,x"\n"); +#else +# define DEBUG_P(x) /**/ +#endif + +#ifdef X_DEBUG +static char CTNAME(accel_debug)[1024]; +#endif + +#ifdef CHIPS_HIQV +static void CTNAME(DepthChange)(ScrnInfoPtr pScrn, int depth); +#endif +static void CTNAME(8SetupForSolidFill)(ScrnInfoPtr pScrn, int color, + int rop, unsigned int planemask); +static void CTNAME(16SetupForSolidFill)(ScrnInfoPtr pScrn, int color, + int rop, unsigned int planemask); +static void CTNAME(24SetupForSolidFill)(ScrnInfoPtr pScrn, int color, + int rop, unsigned int planemask); +static void CTNAME(SubsequentSolidFillRect)(ScrnInfoPtr pScrn, + int x, int y, int w, int h); +#ifndef CHIPS_HIQV +static void CTNAME(24SubsequentSolidFillRect)(ScrnInfoPtr pScrn, + int x, int y, int w, int h); +#else +static void CTNAME(32SetupForSolidFill)(ScrnInfoPtr pScrn, int color, + int rop, unsigned int planemask); +static void CTNAME(32SubsequentSolidFillRect)(ScrnInfoPtr pScrn, + int x, int y, int w, int h); +#endif +static void CTNAME(SetupForScreenToScreenCopy)(ScrnInfoPtr pScrn, int xdir, + int ydir, int rop, unsigned int planemask, + int trans); +static void CTNAME(SubsequentScreenToScreenCopy)(ScrnInfoPtr pScrn, + int srcX, int srcY, int dstX, int dstY, + int w, int h); +static void CTNAME(SetupForCPUToScreenColorExpandFill)(ScrnInfoPtr pScrn, int fg, + int bg, int rop, unsigned int planemask); +static void CTNAME(SubsequentCPUToScreenColorExpandFill)(ScrnInfoPtr pScrn, + int x, int y, int w, int h, int skipleft); +#ifndef CHIPS_HIQV +static XAACacheInfoPtr CTNAME(CacheMonoStipple)(ScrnInfoPtr pScrn, + PixmapPtr pPix); +#endif +#if !defined(CHIPS_HIQV) || defined(UNDOCUMENTED_FEATURE) +static void CTNAME(SetupForScreenToScreenColorExpandFill)(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask); +static void CTNAME(SubsequentScreenToScreenColorExpandFill)(ScrnInfoPtr pScrn, + int x, int y, int w, int h, + int srcx, int srcy, int skipleft); +#endif +static void CTNAME(SetupForMono8x8PatternFill)(ScrnInfoPtr pScrn, + int patx, int paty, int fg, int bg, + int rop, unsigned int planemask); +static void CTNAME(SubsequentMono8x8PatternFillRect)(ScrnInfoPtr pScrn, + int patx, int paty, + int x, int y, int w, int h ); +static void CTNAME(SetupForColor8x8PatternFill)(ScrnInfoPtr pScrn, + int patx, int paty, int rop, + unsigned int planemask, int trans); +static void CTNAME(SubsequentColor8x8PatternFillRect)(ScrnInfoPtr pScrn, + int patx, int paty, + int x, int y, int w, int h ); +#ifndef CHIPS_HIQV +static void CTNAME(SetupForImageWrite)(ScrnInfoPtr pScrn, int rop, + unsigned int planemask, + int transparency_color, int bpp, int depth); +static void CTNAME(SubsequentImageWriteRect)(ScrnInfoPtr pScrn, + int x, int y, int w, int h, int skipleft); +#else +static void CTNAME(WritePixmap)(ScrnInfoPtr pScrn, int x, int y, int w, int h, + unsigned char *src, int srcwidth, int rop, + unsigned int planemask, int trans, int bpp, int depth); +#if 0 +static void CTNAME(ReadPixmap)(ScrnInfoPtr pScrn, int x, int y, int w, int h, + unsigned char *dst, int dstwidth, int bpp, int depth); +#endif +#endif + + +Bool +CTNAME(AccelInit)(ScreenPtr pScreen) +{ + XAAInfoRecPtr infoPtr; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSACLPtr cAcl = CHIPSACLPTR(pScrn); + + DEBUG_P("AccelInit"); + cPtr->AccelInfoRec = infoPtr = XAACreateInfoRec(); + if(!infoPtr) return FALSE; + + /* + * Setup some global variables + */ + cAcl->BytesPerPixel = pScrn->bitsPerPixel >> 3; + cAcl->BitsPerPixel = pScrn->bitsPerPixel; + cAcl->PitchInBytes = pScrn->displayWidth * cAcl->BytesPerPixel; + cAcl->planemask = -1; + cAcl->bgColor = -1; + cAcl->fgColor = -1; + cAcl->FbOffset = 0; + + /* + * Set up the main acceleration flags. + */ + if (cAcl->CacheEnd > cAcl->CacheStart) infoPtr->Flags = PIXMAP_CACHE; + + if (cPtr->Flags & ChipsLinearSupport) + infoPtr->Flags |= OFFSCREEN_PIXMAPS | LINEAR_FRAMEBUFFER; + + infoPtr->PixmapCacheFlags |= DO_NOT_BLIT_STIPPLES; + + /* + * The following line installs a "Sync" function, that waits for + * all coprocessor operations to complete. + */ + infoPtr->Sync = CTNAME(Sync); + + /* + * Setup a Screen to Screen copy (BitBLT) primitive + */ +#ifndef CHIPS_HIQV + infoPtr->ScreenToScreenCopyFlags = NO_TRANSPARENCY; + if (cAcl->BitsPerPixel == 24) + infoPtr->ScreenToScreenCopyFlags |= NO_PLANEMASK; +#else + infoPtr->ScreenToScreenCopyFlags = 0; + if ((cAcl->BitsPerPixel == 24) || (cAcl->BitsPerPixel == 32)) + infoPtr->ScreenToScreenCopyFlags |= NO_PLANEMASK; + + /* A Chips and Technologies application notes says that some + * 65550 have a bug that prevents 16bpp transparency. It probably + * applies to 24 bpp as well (Someone with a 65550 care to check?). + * Selection of this controlled in Probe. + */ + if (!(cPtr->Flags & ChipsColorTransparency)) + infoPtr->ScreenToScreenCopyFlags |= NO_TRANSPARENCY; +#endif + + infoPtr->SetupForScreenToScreenCopy = CTNAME(SetupForScreenToScreenCopy); + infoPtr->SubsequentScreenToScreenCopy = + CTNAME(SubsequentScreenToScreenCopy); + + /* + * Install the low-level functions for drawing solid filled rectangles. + */ + infoPtr->SolidFillFlags |= NO_PLANEMASK; + switch (cAcl->BitsPerPixel) { + case 8 : + infoPtr->SetupForSolidFill = CTNAME(8SetupForSolidFill); + infoPtr->SubsequentSolidFillRect = CTNAME(SubsequentSolidFillRect); + break; + case 16 : + infoPtr->SetupForSolidFill = CTNAME(16SetupForSolidFill); + infoPtr->SubsequentSolidFillRect = CTNAME(SubsequentSolidFillRect); + break; + case 24 : + infoPtr->SetupForSolidFill = CTNAME(24SetupForSolidFill); +#ifdef CHIPS_HIQV + infoPtr->SubsequentSolidFillRect = CTNAME(SubsequentSolidFillRect); +#else + /* + * The version of this function here uses three different + * algorithms in an attempt to maximise performance. One + * for RGB_EQUAL, another for !RGB_EQUAL && GXCOPY_ONLY + * and yet another for !RGB_EQUAL && !GXCOPY_ONLY. The + * first two versions use the 8bpp engine for the fill, + * whilst the second uses a framebuffer routine to create + * one scanline of the fill in off screen memory which is + * then used by a CopyArea function with a complex ROP. + */ + infoPtr->SubsequentSolidFillRect = CTNAME(24SubsequentSolidFillRect); + if (cAcl->ScratchAddress < 0) + infoPtr->ScreenToScreenCopyFlags |= GXCOPY_ONLY; +#endif + break; +#ifdef CHIPS_HIQV + case 32: + if (cAcl->ScratchAddress > 0) { + infoPtr->SetupForSolidFill = CTNAME(32SetupForSolidFill); + infoPtr->SubsequentSolidFillRect = + CTNAME(32SubsequentSolidFillRect); + } + break; +#endif + } + +#ifdef CHIPS_HIQV + /* At 32bpp we can't use the other acceleration */ + if (cAcl->BitsPerPixel == 32) goto chips_imagewrite; +#endif + + /* + * Setup the functions that perform monochrome colour expansion + */ + +#ifdef CHIPS_HIQV + infoPtr->CPUToScreenColorExpandFillFlags = + BIT_ORDER_IN_BYTE_MSBFIRST | CPU_TRANSFER_PAD_QWORD | + LEFT_EDGE_CLIPPING | LEFT_EDGE_CLIPPING_NEGATIVE_X | + ROP_NEEDS_SOURCE; +#ifdef UNDOCUMENTED_FEATURE + infoPtr->ScreenToScreenColorExpandFillFlags = BIT_ORDER_IN_BYTE_MSBFIRST + | LEFT_EDGE_CLIPPING; +#endif + if (cAcl->BitsPerPixel == 24) { + infoPtr->CPUToScreenColorExpandFillFlags |= NO_PLANEMASK; +#ifdef UNDOCUMENTED_FEATURE + infoPtr->ScreenToScreenColorExpandFillFlags |= NO_PLANEMASK; +#endif + } + /* The ct65550 has problems with transparency which leads to video + * corruption unless disabled. + */ + if (!(cPtr->Flags & ChipsColorTransparency)) { + infoPtr->CPUToScreenColorExpandFillFlags |= NO_TRANSPARENCY; +#ifdef UNDOCUMENTED_FEATURE + infoPtr->ScreenToScreenColorExpandFillFlags |= NO_TRANSPARENCY; +#endif + } +#else + infoPtr->CPUToScreenColorExpandFillFlags = + BIT_ORDER_IN_BYTE_MSBFIRST | CPU_TRANSFER_PAD_DWORD | + ROP_NEEDS_SOURCE; + infoPtr->ScreenToScreenColorExpandFillFlags = BIT_ORDER_IN_BYTE_MSBFIRST; + infoPtr->CacheColorExpandDensity = 8; + + if (cAcl->BitsPerPixel == 24) + infoPtr->CPUToScreenColorExpandFillFlags |= TRIPLE_BITS_24BPP | + RGB_EQUAL | NO_PLANEMASK; +#endif + + infoPtr->SetupForCPUToScreenColorExpandFill = + CTNAME(SetupForCPUToScreenColorExpandFill); + infoPtr->SubsequentCPUToScreenColorExpandFill = + CTNAME(SubsequentCPUToScreenColorExpandFill); + +#ifndef CHIPS_HIQV + if (cAcl->BitsPerPixel != 24) { +#endif +#if !defined(CHIPS_HIQV) || defined(UNDOCUMENTED_FEATURE) + infoPtr->SetupForScreenToScreenColorExpandFill = + CTNAME(SetupForScreenToScreenColorExpandFill); + infoPtr->SubsequentScreenToScreenColorExpandFill = + CTNAME(SubsequentScreenToScreenColorExpandFill); +#endif +#ifndef CHIPS_HIQV + infoPtr->CacheMonoStipple = CTNAME(CacheMonoStipple); + } +#endif + + infoPtr->ColorExpandBase = (unsigned char *)cAcl->BltDataWindow; + infoPtr->ColorExpandRange = 64 * 1024; + + /* Mono 8x8 pattern fills */ + infoPtr->Mono8x8PatternFillFlags = NO_PLANEMASK | + BIT_ORDER_IN_BYTE_MSBFIRST | HARDWARE_PATTERN_SCREEN_ORIGIN; + +#ifdef CHIPS_HIQV + infoPtr->SetupForMono8x8PatternFill = + CTNAME(SetupForMono8x8PatternFill); + infoPtr->SubsequentMono8x8PatternFillRect = + CTNAME(SubsequentMono8x8PatternFillRect); + if (cAcl->BitsPerPixel == 24) + infoPtr->MonoPatternPitch = 8; /* Need 8 byte alignment */ +#else + if (cAcl->BitsPerPixel != 24) { + infoPtr->SetupForMono8x8PatternFill = + CTNAME(SetupForMono8x8PatternFill); + infoPtr->SubsequentMono8x8PatternFillRect = + CTNAME(SubsequentMono8x8PatternFillRect); + } +#endif + + /* Color 8x8 pattern fills, must have a displayWidth divisible by 64 */ + if (!(pScrn->displayWidth % 64)) { +#ifdef CHIPS_HIQV + infoPtr->Color8x8PatternFillFlags = NO_PLANEMASK | + HARDWARE_PATTERN_SCREEN_ORIGIN; + if (!(cPtr->Flags & ChipsColorTransparency)) + infoPtr->Color8x8PatternFillFlags |= NO_TRANSPARENCY; +#else + infoPtr->Color8x8PatternFillFlags = NO_PLANEMASK | + HARDWARE_PATTERN_SCREEN_ORIGIN | NO_TRANSPARENCY; +#endif + + if (cAcl->BitsPerPixel != 24) { + infoPtr->SetupForColor8x8PatternFill = + CTNAME(SetupForColor8x8PatternFill); + infoPtr->SubsequentColor8x8PatternFillRect = + CTNAME(SubsequentColor8x8PatternFillRect); + } + } + +#ifdef CHIPS_HIQV +chips_imagewrite: +#endif + + /* Setup for the Image Write functions */ +#ifdef CHIPS_HIQV + infoPtr->WritePixmapFlags = CPU_TRANSFER_PAD_QWORD | LEFT_EDGE_CLIPPING + | LEFT_EDGE_CLIPPING_NEGATIVE_X | ROP_NEEDS_SOURCE; + + if (!(cPtr->Flags & ChipsColorTransparency)) + infoPtr->WritePixmapFlags |= NO_TRANSPARENCY; + if ((cAcl->BitsPerPixel == 24) || (cAcl->BitsPerPixel == 32)) + infoPtr->WritePixmapFlags |= NO_PLANEMASK; + + infoPtr->WritePixmap = CTNAME(WritePixmap); +#if 0 /* Not used by XAA as yet, but coming soon */ + if (cPtr->Flags & ChipsImageReadSupport) { + infoPtr->ReadPixmapFlags = CPU_TRANSFER_PAD_QWORD | ROP_NEEDS_SOURCE; + infoPtr->ReadPixmap = CTNAME(ReadPixmap); + } +#endif + +#else + infoPtr->SetupForImageWrite = CTNAME(SetupForImageWrite); + infoPtr->SubsequentImageWriteRect = CTNAME(SubsequentImageWriteRect); + infoPtr->ImageWriteBase = (unsigned char *)cAcl->BltDataWindow; + infoPtr->ImageWriteRange = 64 * 1024; + infoPtr->ImageWriteFlags = NO_TRANSPARENCY | CPU_TRANSFER_PAD_DWORD + | ROP_NEEDS_SOURCE; + if ((cAcl->BitsPerPixel == 24) || (cAcl->BitsPerPixel == 32)) + infoPtr->ImageWriteFlags |= NO_PLANEMASK; +#endif + + +#ifdef CHIPS_HIQV + if (XAAInit(pScreen, infoPtr)) { + if (cPtr->Flags & ChipsOverlay8plus16) + return(XAAInitDualFramebufferOverlay(pScreen, + CTNAME(DepthChange))); + else + return TRUE; + } else + return FALSE; +#else + return(XAAInit(pScreen, infoPtr)); +#endif +} + +#ifdef CHIPS_HIQV +void +CTNAME(DepthChange)(ScrnInfoPtr pScrn, int depth) +{ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSACLPtr cAcl = CHIPSACLPTR(pScrn); + unsigned char mode; + + DEBUG_P("DepthChange"); + switch (depth) { + case 8 : + cPtr->AccelInfoRec->SetupForSolidFill = CTNAME(8SetupForSolidFill); + mode = 0x00; /* BitBLT engine to 8bpp */ + cAcl->BytesPerPixel = 1; + cAcl->FbOffset = 0; + cAcl->BitsPerPixel = 8; + break; + default : + cPtr->AccelInfoRec->SetupForSolidFill = CTNAME(16SetupForSolidFill); + mode = 0x10; /* BitBLT engine to 16bpp */ + cAcl->BytesPerPixel = 2; + cAcl->FbOffset = cPtr->FbOffset16; + cAcl->BitsPerPixel = 16; + break; + } + cAcl->PitchInBytes = pScrn->displayWidth * cAcl->BytesPerPixel; + ctBLTWAIT; + cPtr->writeXR(cPtr, 0x20, mode); /* Change BitBLT engine mode */ +} +#endif + +void +CTNAME(Sync)(ScrnInfoPtr pScrn) +{ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + DEBUG_P("sync"); + ctBLTWAIT; +} + +static void +CTNAME(8SetupForSolidFill)(ScrnInfoPtr pScrn, int color, + int rop, unsigned int planemask) +{ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSACLPtr cAcl = CHIPSACLPTR(pScrn); + + DEBUG_P("8SetupForSolidFill"); + ctBLTWAIT; + ctSETBGCOLOR8(color); + ctSETFGCOLOR8(color); + ctSETROP(ChipsAluConv2[rop & 0xF] | ctTOP2BOTTOM | ctLEFT2RIGHT | + ctPATSOLID | ctPATMONO); + ctSETPITCH(0, cAcl->PitchInBytes); +} + +static void +CTNAME(16SetupForSolidFill)(ScrnInfoPtr pScrn, int color, + int rop, unsigned int planemask) +{ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSACLPtr cAcl = CHIPSACLPTR(pScrn); + + DEBUG_P("16SetupForSolidFill"); + ctBLTWAIT; + ctSETBGCOLOR16(color); + ctSETFGCOLOR16(color); + ctSETROP(ChipsAluConv2[rop & 0xF] | ctTOP2BOTTOM | ctLEFT2RIGHT | + ctPATSOLID | ctPATMONO); + ctSETPITCH(0, cAcl->PitchInBytes); +} + +#ifdef CHIPS_HIQV +static void +CTNAME(24SetupForSolidFill)(ScrnInfoPtr pScrn, int color, + int rop, unsigned int planemask) +{ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSACLPtr cAcl = CHIPSACLPTR(pScrn); + + DEBUG_P("24SetupForSolidFill"); + ctBLTWAIT; + ctSETBGCOLOR24(color); + ctSETFGCOLOR24(color); + ctSETROP(ChipsAluConv2[rop & 0xF] | ctTOP2BOTTOM | ctLEFT2RIGHT | + ctPATSOLID | ctPATMONO); + ctSETPITCH(0, cAcl->PitchInBytes); +} + +static void +CTNAME(32SetupForSolidFill)(ScrnInfoPtr pScrn, int color, + int rop, unsigned int planemask) +{ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSACLPtr cAcl = CHIPSACLPTR(pScrn); + + DEBUG_P("32SetupForSolidFill"); + ctBLTWAIT; + memset((unsigned char *)cPtr->FbBase + cAcl->ScratchAddress, 0xAA, 8); + ctSETFGCOLOR16((color & 0xFFFF)); + ctSETBGCOLOR16(((color >> 16) & 0xFFFF)); + ctSETROP(ChipsAluConv2[rop & 0xF] | ctTOP2BOTTOM | ctLEFT2RIGHT | + ctPATMONO); + ctSETPATSRCADDR(cAcl->ScratchAddress); + ctSETPITCH(1, cAcl->PitchInBytes); +} + +static void +CTNAME(32SubsequentSolidFillRect)(ScrnInfoPtr pScrn, int x, int y, int w, + int h) +{ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + + unsigned int destaddr; + destaddr = (y * pScrn->displayWidth + x) << 2; + w <<= 2; + DEBUG_P("32SubsequentSolidFillRect"); + ctBLTWAIT; + ctSETDSTADDR(destaddr); + ctSETHEIGHTWIDTHGO(h, w); +} +#else + +static void +CTNAME(24SetupForSolidFill)(ScrnInfoPtr pScrn, int color, + int rop, unsigned int planemask) +{ + unsigned char pixel1, pixel2, pixel3; + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSACLPtr cAcl = CHIPSACLPTR(pScrn); + + DEBUG_P("24SetupForSolidFill"); + cAcl->rgb24equal = (((((color & 0xFF) == ((color & 0xFF00) >> 8)) && + ((color & 0xFF) == ((color & 0xFF0000) >> 16)))) || + /* Check the rop for paranoid reasons */ + (rop == GXclear) || (rop == GXnoop) || + (rop == GXinvert) || (rop == GXset)); + if (cAcl->rgb24equal) { + cAcl->CommandFlags = ChipsAluConv2[rop & 0xF] | ctTOP2BOTTOM | + ctLEFT2RIGHT | ctPATSOLID | ctPATMONO; + ctBLTWAIT; + ctSETFGCOLOR8(color&0xFF); + ctSETBGCOLOR8(color&0xFF); + ctSETPITCH(0, cAcl->PitchInBytes); + } else { + cAcl->rop24bpp = rop; + if (rop == GXcopy) { + pixel3 = color & 0xFF; + pixel2 = (color >> 8) & 0xFF; + pixel1 = (color >> 16) & 0xFF; + cAcl->fgpixel = pixel1; + cAcl->bgpixel = pixel2; + cAcl->fillindex = 0; + cAcl->fastfill = FALSE; + + /* Test for the special case where two of the byte of the + * 24bpp colour are the same. This can double the speed + */ + if (pixel1 == pixel2) { + cAcl->fgpixel = pixel3; + cAcl->bgpixel = pixel1; + cAcl->fastfill = TRUE; + cAcl->fillindex = 1; + } else if (pixel1 == pixel3) { + cAcl->fgpixel = pixel2; + cAcl->bgpixel = pixel1; + cAcl->fastfill = TRUE; + cAcl->fillindex = 2; + } else if (pixel2 == pixel3) { + cAcl->fastfill = TRUE; + } else { + cAcl->xorpixel = pixel2 ^ pixel3; + } + + cAcl->CommandFlags = ctSRCMONO | ctSRCSYSTEM | ctTOP2BOTTOM | + ctLEFT2RIGHT; + ctBLTWAIT; + if (cAcl->fastfill) { + ctSETFGCOLOR8(cAcl->fgpixel); + } + ctSETBGCOLOR8(cAcl->bgpixel); + ctSETSRCADDR(0); + ctSETPITCH(0, cAcl->PitchInBytes); + } else { + if (cAcl->color24bpp != color) { + cAcl->color24bpp = color; + cAcl->width24bpp = 0; + } + cAcl->rop24bpp = rop; + ctBLTWAIT; + ctSETROP(ctTOP2BOTTOM | ctLEFT2RIGHT | ChipsAluConv[rop & 0xF]); + ctSETPITCH(cAcl->PitchInBytes, cAcl->PitchInBytes); + } + } +} + +static void +CTNAME(24SubsequentSolidFillRect)(ScrnInfoPtr pScrn, int x, int y, int w, + int h) +{ + static unsigned int dwords[3] = { 0x24499224, 0x92244992, 0x49922449}; + int srcaddr, destaddr, line, i; + register int width; + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSACLPtr cAcl = CHIPSACLPTR(pScrn); + + DEBUG_P("24SubsequentSolidFillRect"); + if (cAcl->rgb24equal) { + destaddr = y * pScrn->displayWidth + x; + destaddr += destaddr << 1; + ctBLTWAIT; + ctSETROP(cAcl->CommandFlags); + ctSETDSTADDR(destaddr); + ctSETHEIGHTWIDTHGO(h, (w + (w << 1))); + } else { + if (cAcl->rop24bpp == GXcopy ) { + unsigned int *base = (unsigned int *)cAcl->BltDataWindow; + destaddr = y * cAcl->PitchInBytes + x * 3; + w *= 3; + width = ((w + 31) & ~31) >> 5; + + ctBLTWAIT; + ctSETDSTADDR(destaddr); + + if (!cAcl->fastfill) ctSETFGCOLOR8(cAcl->fgpixel); + ctSETROP(cAcl->CommandFlags | ChipsAluConv[GXcopy & 0xF]); + ctSETDSTADDR(destaddr); + if (cAcl->fastfill) { + ctSETHEIGHTWIDTHGO(h, w); + line = 0; + while (line < h) { + base = (unsigned int *)cAcl->BltDataWindow; + for (i = 0; i < width; i++) { + *base++ = dwords[((cAcl->fillindex + i) % 3)]; + } + line++; + } + } else { + ctSETHEIGHTWIDTHGO(1, w); + i = 0; + while(i < width){ + *base++ = dwords[(i++ % 3)]; + } + for(line = 0; (h >> line ) > 1; line++){;} + i = 0; + ctBLTWAIT; + ctSETFGCOLOR8(cAcl->xorpixel); + ctSETROP(cAcl->CommandFlags | ChipsAluConv[GXxor & 0xF] | + ctBGTRANSPARENT); + ctSETDSTADDR(destaddr); + ctSETHEIGHTWIDTHGO(1, w); + base = (unsigned int *)cAcl->BltDataWindow; + while(i < width) { + *base++ = dwords[((++i) % 3)]; + } + srcaddr = destaddr; + if(line){ + i = 0; + ctBLTWAIT; + ctSETROP(ctTOP2BOTTOM | ctLEFT2RIGHT | + ChipsAluConv[GXcopy & 0xF]); + ctSETPITCH(cAcl->PitchInBytes, cAcl->PitchInBytes); + ctSETSRCADDR(srcaddr); + + while(i < line){ + destaddr = srcaddr + (cAcl->PitchInBytes << i); + ctBLTWAIT; + ctSETDSTADDR(destaddr); + ctSETHEIGHTWIDTHGO((1 << i), w); + i++; + } + + if((1 << line) < h){ + destaddr = srcaddr + (cAcl->PitchInBytes << line); + ctBLTWAIT; + ctSETDSTADDR(destaddr); + ctSETHEIGHTWIDTHGO(h-(1 << line), w); + } + + ctBLTWAIT; + ctSETROP(ctSRCMONO | ctSRCSYSTEM | ctTOP2BOTTOM | + ctLEFT2RIGHT | ChipsAluConv[GXcopy & 0xF]); + ctSETSRCADDR(0); + ctSETPITCH(0, cAcl->PitchInBytes); + } + } + } else { + register unsigned char *base; + if (cAcl->width24bpp < w) { + base = (unsigned char *)cPtr->FbBase + cAcl->ScratchAddress + + ((3 * cAcl->width24bpp + 3) & ~0x3); + width = w - cAcl->width24bpp; + ctBLTWAIT; + /* Load of a single scanline into framebuffer */ + while (width > 0) { + *(unsigned int *)base = cAcl->color24bpp | + (cAcl->color24bpp << 24); + *(unsigned int *)(base + 4) = (cAcl->color24bpp >> 8) | + (cAcl->color24bpp << 16); + *(unsigned int *)(base + 8) = (cAcl->color24bpp >> 16) | + (cAcl->color24bpp << 8); + base += 12; + width -= 4; + } + cAcl->width24bpp = w - width; + } + line = 0; + destaddr = 3 * (y * pScrn->displayWidth + x); + w *= cAcl->BytesPerPixel; + while (line < h) { + ctBLTWAIT; + ctSETSRCADDR(cAcl->ScratchAddress); + ctSETDSTADDR(destaddr); + ctSETHEIGHTWIDTHGO(1, w); + destaddr += (3 * pScrn->displayWidth); + line++; + } + } + } +} +#endif + +static void +CTNAME(SubsequentSolidFillRect)(ScrnInfoPtr pScrn, int x, int y, int w, + int h) +{ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSACLPtr cAcl = CHIPSACLPTR(pScrn); + int destaddr; + + DEBUG_P("SubsequentSolidFillRect"); + destaddr = (y * pScrn->displayWidth + x) * cAcl->BytesPerPixel; +#ifdef CHIPS_HIQV + destaddr += cAcl->FbOffset; +#endif + w *= cAcl->BytesPerPixel; + ctBLTWAIT; + ctSETDSTADDR(destaddr); + ctSETHEIGHTWIDTHGO(h, w); +} + +/* + * Screen-to-screen BitBLT. + * + */ + +static void +CTNAME(SetupForScreenToScreenCopy)(ScrnInfoPtr pScrn, int xdir, int ydir, + int rop, unsigned int planemask, int trans) +{ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSACLPtr cAcl = CHIPSACLPTR(pScrn); + + DEBUG_P("SetupForScreenToScreenCopy"); + cAcl->CommandFlags = 0; + + /* Set up the blit direction. */ + if (ydir < 0) + cAcl->CommandFlags |= ctBOTTOM2TOP; + else + cAcl->CommandFlags |= ctTOP2BOTTOM; + if (xdir < 0) + cAcl->CommandFlags |= ctRIGHT2LEFT; + else + cAcl->CommandFlags |= ctLEFT2RIGHT; +#ifdef CHIPS_HIQV + if (trans != -1) { + cAcl->CommandFlags |= ctCOLORTRANSENABLE | ctCOLORTRANSROP | + ctCOLORTRANSNEQUAL; + ctBLTWAIT; + /* BR03[0x27] sometimes set after reset, so must ensure it is zero */ + ctSETMONOCTL(ctDWORDALIGN); + switch (cAcl->BitsPerPixel) { + case 8: + ctSETBGCOLOR8(trans); + break; + case 16: + ctSETBGCOLOR16(trans); + break; + case 24: + ctSETBGCOLOR24(trans); + break; + } + } else +#endif + ctBLTWAIT; + switch (cAcl->BitsPerPixel) { +#if 0 + case 8: + if ((planemask & 0xFF) == 0xFF) { + ctSETROP(cAcl->CommandFlags | ChipsAluConv[rop & 0xF]); + } else { + ctSETROP(cAcl->CommandFlags | ChipsAluConv3[rop & 0xF]); + ctSETPATSRCADDR(cAcl->ScratchAddress); + ctWRITEPLANEMASK8(planemask, cAcl->ScratchAddress); + } + break; + case 16: + if ((planemask & 0xFFFF) == 0xFFFF) { + ctSETROP(cAcl->CommandFlags | ChipsAluConv[rop & 0xF]); + } else { + ctSETROP(cAcl->CommandFlags | ChipsAluConv3[rop & 0xF]); + ctSETPATSRCADDR(cAcl->ScratchAddress); + ctWRITEPLANEMASK16(planemask, cAcl->ScratchAddress); + } + break; +#endif + default: + ctSETROP(cAcl->CommandFlags | ChipsAluConv[rop & 0xF]); + break; + } + ctSETPITCH(cAcl->PitchInBytes, cAcl->PitchInBytes); +} + +static void +CTNAME(SubsequentScreenToScreenCopy)(ScrnInfoPtr pScrn, int srcX, int srcY, + int dstX, int dstY, int w, int h) +{ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSACLPtr cAcl = CHIPSACLPTR(pScrn); + unsigned int srcaddr, destaddr; + + DEBUG_P("SubsequentScreenToScreenCopy"); +#ifdef CHIPS_HIQV + if (cAcl->CommandFlags & ctBOTTOM2TOP) { + srcaddr = (srcY + h - 1) * pScrn->displayWidth; + destaddr = (dstY + h - 1) * pScrn->displayWidth; + } else { + srcaddr = srcY * pScrn->displayWidth; + destaddr = dstY * pScrn->displayWidth; + } + if (cAcl->CommandFlags & ctRIGHT2LEFT) { + srcaddr = ( srcaddr + srcX + w ) * cAcl->BytesPerPixel - 1 ; + destaddr = ( destaddr + dstX + w ) * cAcl->BytesPerPixel - 1; + } else { + srcaddr = (srcaddr + srcX) * cAcl->BytesPerPixel; + destaddr = (destaddr + dstX) * cAcl->BytesPerPixel; + } + srcaddr += cAcl->FbOffset; + destaddr += cAcl->FbOffset; +#else + if (cAcl->CommandFlags & ctTOP2BOTTOM) { + srcaddr = srcY * pScrn->displayWidth; + destaddr = dstY * pScrn->displayWidth; + } else { + srcaddr = (srcY + h - 1) * pScrn->displayWidth; + destaddr = (dstY + h - 1) * pScrn->displayWidth; + } + if (cAcl->CommandFlags & ctLEFT2RIGHT) { + srcaddr = (srcaddr + srcX) * cAcl->BytesPerPixel; + destaddr = (destaddr + dstX) * cAcl->BytesPerPixel; + } else { + srcaddr = ( srcaddr + srcX + w ) * cAcl->BytesPerPixel - 1 ; + destaddr = ( destaddr + dstX + w ) * cAcl->BytesPerPixel - 1; + } +#endif + w *= cAcl->BytesPerPixel; + ctBLTWAIT; + ctSETSRCADDR(srcaddr); + ctSETDSTADDR(destaddr); + ctSETHEIGHTWIDTHGO(h, w); +} + + +static void +CTNAME(SetupForCPUToScreenColorExpandFill)(ScrnInfoPtr pScrn, int fg, + int bg, int rop, unsigned int planemask) +{ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSACLPtr cAcl = CHIPSACLPTR(pScrn); + + DEBUG_P("SetupForCPUToScreenColorExpandFill"); + ctBLTWAIT; + cAcl->CommandFlags = 0; + if (bg == -1) { + cAcl->CommandFlags |= ctBGTRANSPARENT; /* Background = Destination */ + switch (cAcl->BitsPerPixel) { + case 8: + ctSETFGCOLOR8(fg); + break; + case 16: + ctSETFGCOLOR16(fg); + break; + case 24: +#ifdef CHIPS_HIQV + ctSETFGCOLOR24(fg); +#else + ctSETFGCOLOR8(fg); +#endif + break; + } + } + else { + switch (cAcl->BitsPerPixel) { + case 8: + ctSETBGCOLOR8(bg); + ctSETFGCOLOR8(fg); + break; + case 16: + ctSETBGCOLOR16(bg); + ctSETFGCOLOR16(fg); + break; + case 24: +#ifdef CHIPS_HIQV + ctSETBGCOLOR24(bg); + ctSETFGCOLOR24(fg); +#else + ctSETBGCOLOR8(bg); + ctSETFGCOLOR8(fg); +#endif + break; + } + } + +#ifdef CHIPS_HIQV + ctSETMONOCTL(ctDWORDALIGN); +#endif + + ctSETSRCADDR(0); + + switch (cAcl->BitsPerPixel) { + case 8: + if ((planemask & 0xFF) == 0xFF) { + ctSETROP(ctSRCSYSTEM | ctSRCMONO | ctTOP2BOTTOM | ctLEFT2RIGHT | + ChipsAluConv[rop & 0xF] | cAcl->CommandFlags); + } else { + ctSETROP(ctSRCSYSTEM | ctSRCMONO | ctTOP2BOTTOM | ctLEFT2RIGHT | + ChipsAluConv3[rop & 0xF] | cAcl->CommandFlags); + ctSETPATSRCADDR(cAcl->ScratchAddress); + ctWRITEPLANEMASK8(planemask, cAcl->ScratchAddress); + } + break; + case 16: + if ((planemask & 0xFFFF) == 0xFFFF) { + ctSETROP(ctSRCSYSTEM | ctSRCMONO | ctTOP2BOTTOM | ctLEFT2RIGHT | + ChipsAluConv[rop & 0xF] | cAcl->CommandFlags); + } else { + ctSETROP(ctSRCSYSTEM | ctSRCMONO | ctTOP2BOTTOM | ctLEFT2RIGHT | + ChipsAluConv3[rop & 0xF] | cAcl->CommandFlags); + ctSETPATSRCADDR(cAcl->ScratchAddress); + ctWRITEPLANEMASK16(planemask, cAcl->ScratchAddress); + } + break; + default: + ctSETROP(ctSRCSYSTEM | ctSRCMONO | ctTOP2BOTTOM | ctLEFT2RIGHT | + ChipsAluConv[rop & 0xF] | cAcl->CommandFlags); + break; + } + ctSETPITCH(0, cAcl->PitchInBytes); +} + +static void +CTNAME(SubsequentCPUToScreenColorExpandFill)(ScrnInfoPtr pScrn, + int x, int y, int w, int h, int skipleft) +{ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSACLPtr cAcl = CHIPSACLPTR(pScrn); + int destaddr; + + DEBUG_P("SubsequentCPUToScreenColorExpandFill"); + destaddr = (y * pScrn->displayWidth + x + skipleft) * + cAcl->BytesPerPixel; +#ifdef CHIPS_HIQV + destaddr += cAcl->FbOffset; +#endif + w = (w - skipleft) * cAcl->BytesPerPixel; + ctBLTWAIT; + ctSETDSTADDR(destaddr); +#ifdef CHIPS_HIQV + ctSETMONOCTL(ctDWORDALIGN | ctCLIPLEFT(skipleft)); +#endif + ctSETHEIGHTWIDTHGO(h, w); +} + +#if !defined(CHIPS_HIQV) || defined(UNDOCUMENTED_FEATURE) +static void +CTNAME(SetupForScreenToScreenColorExpandFill)(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask) +{ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSACLPtr cAcl = CHIPSACLPTR(pScrn); + + DEBUG_P("SetupForScreenToScreenColorExpandFill"); + cAcl->CommandFlags = 0; + ctBLTWAIT; + if (bg == -1) { + cAcl->CommandFlags |= ctBGTRANSPARENT; /* Background = Destination */ + switch (cAcl->BitsPerPixel) { + case 8: + ctSETFGCOLOR8(fg); + break; + case 16: + ctSETFGCOLOR16(fg); + break; + case 24: +#ifdef CHIPS_HIQV + ctSETFGCOLOR24(fg); +#else + ctSETFGCOLOR8(fg); +#endif + break; + } + } + else { + switch (cAcl->BitsPerPixel) { + case 8: + ctSETBGCOLOR8(bg); + ctSETFGCOLOR8(fg); + break; + case 16: + ctSETBGCOLOR16(bg); + ctSETFGCOLOR16(fg); + break; + case 24: +#ifdef CHIPS_HIQV + ctSETBGCOLOR24(bg); + ctSETFGCOLOR24(fg); +#else + ctSETBGCOLOR8(bg); + ctSETFGCOLOR8(fg); +#endif + break; + } + } + + switch (cAcl->BitsPerPixel) { + case 8: + if ((planemask & 0xFF) == 0xFF) { + ctSETROP(ctSRCMONO | ctTOP2BOTTOM | ctLEFT2RIGHT | + ChipsAluConv[rop & 0xF] | cAcl->CommandFlags); + } else { + ctSETROP(ctSRCMONO | ctTOP2BOTTOM | ctLEFT2RIGHT | + ChipsAluConv3[rop & 0xF] | cAcl->CommandFlags); + ctSETPATSRCADDR(cAcl->ScratchAddress); + ctWRITEPLANEMASK8(planemask, cAcl->ScratchAddress); + } + break; + case 16: + if ((planemask & 0xFFFF) == 0xFFFF) { + ctSETROP(ctSRCMONO | ctTOP2BOTTOM | ctLEFT2RIGHT | + ChipsAluConv[rop & 0xF] | cAcl->CommandFlags); + } else { + ctSETROP(ctSRCMONO | ctTOP2BOTTOM | ctLEFT2RIGHT | + ChipsAluConv3[rop & 0xF] | cAcl->CommandFlags); + ctSETPATSRCADDR(cAcl->ScratchAddress); + ctWRITEPLANEMASK16(planemask, cAcl->ScratchAddress); + } + break; + default: + ctSETROP(ctSRCMONO | ctTOP2BOTTOM | ctLEFT2RIGHT | + ChipsAluConv[rop & 0xF] | cAcl->CommandFlags); + break; + } + ctSETPITCH(cAcl->PitchInBytes, cAcl->PitchInBytes); +} +#endif +#ifndef CHIPS_HIQV +/* + * The non-HiQV chips don't have left-edge clippling of monochrome sources. + * However you can have the monochrome source starting on a byte boundary. + * Hence have 8 rotated copies of the monochrome source to simulate left + * edge clipping with these chips. This requires the XAACacheMonoStipple + * function to be replaced, if we are to use ScreenToScreenColorExpand. + */ + +static XAACacheInfoPtr +CTNAME(CacheMonoStipple)(ScrnInfoPtr pScrn, PixmapPtr pPix) +{ + int w = pPix->drawable.width; + int h = pPix->drawable.height; + XAAInfoRecPtr infoRec = (CHIPSPTR(pScrn))->AccelInfoRec; + XAAPixmapCachePrivatePtr pCachePriv = + (XAAPixmapCachePrivatePtr)infoRec->PixmapCachePrivate; + XAACacheInfoPtr pCache, cacheRoot = NULL; + CHIPSACLPtr cAcl = CHIPSACLPTR(pScrn); + int i, j, max = 0, funcNo, pad, dwords, bpp = cAcl->BitsPerPixel; + int *current; + StippleScanlineProcPtr StippleFunc; + unsigned char *data, *srcPtr, *dstPtr; + + DEBUG_P("CacheMonoStipple"); + if((h <= 128) && (w <= 128 * bpp / 8)) { + if(pCachePriv->Info128) { + cacheRoot = pCachePriv->Info128; + max = pCachePriv->Num128x128; + current = &pCachePriv->Current128; + } else { + cacheRoot = pCachePriv->InfoPartial; + max = pCachePriv->NumPartial; + current = &pCachePriv->CurrentPartial; + } + } else if((h <= 256) && (w <= 256 * bpp / 8)){ + cacheRoot = pCachePriv->Info256; + max = pCachePriv->Num256x256; + current = &pCachePriv->Current256; + } else if((h <= 512) && (w <= 512 * bpp / 8)){ + cacheRoot = pCachePriv->Info512; + max = pCachePriv->Num512x512; + current = &pCachePriv->Current512; + } else { /* something's wrong */ + ErrorF("Something's wrong in XAACacheMonoStipple()\n"); + return pCachePriv->Info128; + } + + pCache = cacheRoot; + + /* lets look for it */ + for(i = 0; i < max; i++, pCache++) { + if((pCache->serialNumber == pPix->drawable.serialNumber) && + (pCache->fg == -1) && (pCache->bg == -1)) { + pCache->trans_color = -1; + dwords = + cAcl->SlotWidth = ((pCache->w * bpp) >> 5) >> 1; + return pCache; + } + } + + pCache = &cacheRoot[(*current)++]; + if(*current >= max) *current = 0; + + pCache->serialNumber = pPix->drawable.serialNumber; + pCache->trans_color = pCache->bg = pCache->fg = -1; + pCache->orig_w = w; pCache->orig_h = h; + + if(w <= 32) { + if(w & (w - 1)) funcNo = 1; + else funcNo = 0; + } else funcNo = 2; + + pad = (((pCache->w * bpp) + 31) >> 5) << 2; + dstPtr = data = (unsigned char*)ALLOCATE_LOCAL(pad * pCache->h); + srcPtr = (unsigned char*)pPix->devPrivate.ptr; + StippleFunc = XAAStippleScanlineFuncMSBFirst[funcNo]; + + dwords = ((pCache->w * bpp) >> 5) >> 3; + cAcl->SlotWidth = dwords << 2; + + for(i = 0; i < h; i++) { + for(j = 0; j < 8; j++) { + (*StippleFunc)((CARD32*)dstPtr + j * dwords, + (CARD32*)srcPtr, j, w, dwords); + } + srcPtr += pPix->devKind; + dstPtr += pad; + } + + while((h<<1) <= pCache->h) { + memcpy(data + (pad * h), data, pad * h); + h <<= 1; + } + + if(h < pCache->h) + memcpy(data + (pad * h), data, pad * (pCache->h - h)); + + (*infoRec->WritePixmapToCache)( + pScrn, pCache->x, pCache->y, pCache->w, pCache->h, data, + pad, bpp, pScrn->depth); + + DEALLOCATE_LOCAL(data); + + return pCache; +} +#endif +#if !defined(CHIPS_HIQV) || defined(UNDOCUMENTED_FEATURE) +static void +CTNAME(SubsequentScreenToScreenColorExpandFill)(ScrnInfoPtr pScrn, + int x, int y, int w, int h, + int srcx, int srcy, int skipleft) +{ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSACLPtr cAcl = CHIPSACLPTR(pScrn); + int srcaddr, destaddr; + + DEBUG_P("SubsequentScreenToScreenColorExpandFill"); +#ifdef CHIPS_HIQV + srcaddr = (srcy * pScrn->displayWidth + srcx) * cAcl->BytesPerPixel + + ((skipleft & ~0x3F) >> 3); + if ( y < pScrn->virtualY) + srcaddr += cAcl->FbOffset; + else + srcaddr += cPtr->FbOffset16; +#else + srcaddr = (srcy * pScrn->displayWidth + srcx) * cAcl->BytesPerPixel + + ((skipleft & 0x07) * cAcl->SlotWidth) + + ((skipleft & ~0x07) >> 3); +#endif + destaddr = (y * pScrn->displayWidth + x) * cAcl->BytesPerPixel; +#ifdef CHIPS_HIQV + destaddr += cAcl->FbOffset; +#endif + w *= cAcl->BytesPerPixel; + ctBLTWAIT; +#ifdef CHIPS_HIQV + if ((y >= pScrn->virtualY) && (cPtr->Flags & ChipsOverlay8plus16) && + (pScrn->depth == 8)) + ctSETPITCH(cAcl->PitchInBytes << 1, cAcl->PitchInBytes); +#endif + ctSETSRCADDR(srcaddr); + ctSETDSTADDR(destaddr); +#ifdef CHIPS_HIQV + ctSETMONOCTL(ctCLIPLEFT(skipleft & 0x3F)); +#endif + ctSETHEIGHTWIDTHGO(h, w); +} +#endif +static void +CTNAME(SetupForColor8x8PatternFill)(ScrnInfoPtr pScrn, int patx, int paty, + int rop, unsigned int planemask, + int trans) +{ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSACLPtr cAcl = CHIPSACLPTR(pScrn); + unsigned int patternaddr; + + DEBUG_P("SetupForColor8x8PatternFill"); + cAcl->CommandFlags = ChipsAluConv2[rop & 0xF] | ctTOP2BOTTOM | + ctLEFT2RIGHT; + patternaddr = (paty * pScrn->displayWidth + + (patx & ~0x3F)) * cAcl->BytesPerPixel; + cAcl->patternyrot = (patx & 0x3F) >> 3; +#ifdef CHIPS_HIQV + if (cPtr->Flags & ChipsOverlay8plus16) + patternaddr += cPtr->FbOffset16; +#endif + + ctBLTWAIT; + ctSETPATSRCADDR(patternaddr); +#ifdef CHIPS_HIQV + if (trans != -1) { + cAcl->CommandFlags |= ctCOLORTRANSENABLE | ctCOLORTRANSROP | + ctCOLORTRANSNEQUAL; + ctSETMONOCTL(ctDWORDALIGN); + switch (cAcl->BitsPerPixel) { + case 8: + ctSETBGCOLOR8(trans); + break; + case 16: + ctSETBGCOLOR16(trans); + break; + case 24: + ctSETBGCOLOR24(trans); + break; + } + } else +#endif + ctSETPITCH(8 * cAcl->BytesPerPixel, cAcl->PitchInBytes); +} + +static void +CTNAME(SubsequentColor8x8PatternFillRect)(ScrnInfoPtr pScrn, int patx, int paty, + int x, int y, int w, int h) +{ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSACLPtr cAcl = CHIPSACLPTR(pScrn); + unsigned int destaddr; + + DEBUG_P("SubsequentColor8x8PatternFillRect"); + destaddr = (y * pScrn->displayWidth + x) * cAcl->BytesPerPixel; +#ifdef CHIPS_HIQV + destaddr += cAcl->FbOffset; +#endif + w *= cAcl->BytesPerPixel; + ctBLTWAIT; + ctSETDSTADDR(destaddr); +#ifdef CHIPS_HIQV + ctSETROP(cAcl->CommandFlags | (((y + cAcl->patternyrot) & 0x7) << 20)); +#else + ctSETROP(cAcl->CommandFlags | (((y + cAcl->patternyrot) & 0x7) << 16)); +#endif + ctSETHEIGHTWIDTHGO(h, w); +} + +static void +CTNAME(SetupForMono8x8PatternFill)(ScrnInfoPtr pScrn, int patx, int paty, + int fg, int bg, int rop, + unsigned int planemask) +{ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSACLPtr cAcl = CHIPSACLPTR(pScrn); + unsigned int patternaddr; + + DEBUG_P("SetupForMono8x8PatternFill"); + cAcl->CommandFlags = ctPATMONO | ctTOP2BOTTOM | ctLEFT2RIGHT | + ChipsAluConv2[rop & 0xF]; + +#ifdef CHIPS_HIQV + patternaddr = paty * pScrn->displayWidth + patx; + if (cPtr->Flags & ChipsOverlay8plus16) + patternaddr = patternaddr * 2 + cPtr->FbOffset16; + else + patternaddr *= cAcl->BytesPerPixel; +#else + patternaddr = (paty * pScrn->displayWidth + patx) * cAcl->BytesPerPixel; +#endif + ctBLTWAIT; + ctSETPATSRCADDR(patternaddr); + if (bg == -1) { + cAcl->CommandFlags |= ctBGTRANSPARENT; /* Background = Destination */ + switch (cAcl->BitsPerPixel) { + case 8: + ctSETFGCOLOR8(fg); + break; + case 16: + ctSETFGCOLOR16(fg); + break; + case 24: + ctSETFGCOLOR24(fg); + break; + } + } + else { + switch (cAcl->BitsPerPixel) { + case 8: + ctSETBGCOLOR8(bg); + ctSETFGCOLOR8(fg); + break; + case 16: + ctSETBGCOLOR16(bg); + ctSETFGCOLOR16(fg); + break; + case 24: + ctSETBGCOLOR24(bg); + ctSETFGCOLOR24(fg); + break; + } + } +#ifdef CHIPS_HIQV + ctSETMONOCTL(ctDWORDALIGN); +#endif + ctSETPITCH(1,cAcl->PitchInBytes); +} + +static void +CTNAME(SubsequentMono8x8PatternFillRect)(ScrnInfoPtr pScrn, int patx, + int paty, int x, int y, int w, int h ) +{ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSACLPtr cAcl = CHIPSACLPTR(pScrn); + int destaddr; + DEBUG_P("SubsequentMono8x8PatternFillRect"); + destaddr = (y * pScrn->displayWidth + x) * cAcl->BytesPerPixel; +#ifdef CHIPS_HIQV + destaddr += cAcl->FbOffset; +#endif + w *= cAcl->BytesPerPixel; + + ctBLTWAIT; + ctSETDSTADDR(destaddr); +#ifdef CHIPS_HIQV + ctSETROP(cAcl->CommandFlags | ((y & 0x7) << 20)); +#else + ctSETROP(cAcl->CommandFlags | ((y & 0x7) << 16)); +#endif + ctSETHEIGHTWIDTHGO(h, w); +} + +#ifndef CHIPS_HIQV +static void +CTNAME(SetupForImageWrite)(ScrnInfoPtr pScrn, int rop, unsigned int planemask, + int transparency_color, int bpp, int depth) +{ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSACLPtr cAcl = CHIPSACLPTR(pScrn); + + DEBUG_P("SetupForImageWrite"); + cAcl->CommandFlags = ctSRCSYSTEM | ctTOP2BOTTOM | ctLEFT2RIGHT; + ctBLTWAIT; + + switch (cAcl->BitsPerPixel) { + case 8: + if ((planemask & 0xFF) == 0xFF) { + ctSETROP(cAcl->CommandFlags | ChipsAluConv[rop & 0xF]); + } else { + ctSETROP(cAcl->CommandFlags | ChipsAluConv3[rop & 0xF]); + ctSETPATSRCADDR(cAcl->ScratchAddress); + ctWRITEPLANEMASK8(planemask, cAcl->ScratchAddress); + } + break; + case 16: + if ((planemask & 0xFFFF) == 0xFFFF) { + ctSETROP(cAcl->CommandFlags | ChipsAluConv[rop & 0xF]); + } else { + ctSETROP(cAcl->CommandFlags | ChipsAluConv3[rop & 0xF]); + ctSETPATSRCADDR(cAcl->ScratchAddress); + ctWRITEPLANEMASK16(planemask, cAcl->ScratchAddress); + } + break; + default: + ctSETROP(cAcl->CommandFlags | ChipsAluConv[rop & 0xF]); + break; + } + ctSETSRCADDR(0); +} + +static void +CTNAME(SubsequentImageWriteRect)(ScrnInfoPtr pScrn, int x, int y, int w, int h, + int skipleft) +{ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSACLPtr cAcl = CHIPSACLPTR(pScrn); + int destaddr = (y * pScrn->displayWidth + x) * cAcl->BytesPerPixel; + DEBUG_P("SubsequentImageWriteRect"); + w *= cAcl->BytesPerPixel; + ctBLTWAIT; + ctSETPITCH(((w + 3) & ~0x3), cAcl->PitchInBytes); + ctSETDSTADDR(destaddr); + ctSETHEIGHTWIDTHGO(h, w); +} + +#else +/* + * Copyright 1997 + * Digital Equipment Corporation. All rights reserved. + * This software is furnished under license and may be used and copied only in + * accordance with the following terms and conditions. Subject to these + * conditions, you may download, copy, install, use, modify and distribute + * this software in source and/or binary form. No title or ownership is + * transferred hereby. + * 1) Any source code used, modified or distributed must reproduce and retain + * this copyright notice and list of conditions as they appear in the + * source file. + * + * 2) No right is granted to use any trade name, trademark, or logo of Digital + * Equipment Corporation. Neither the "Digital Equipment Corporation" name + * nor any trademark or logo of Digital Equipment Corporation may be used + * to endorse or promote products derived from this software without the + * prior written permission of Digital Equipment Corporation. + * + * 3) This software is provided "AS-IS" and any express or implied warranties, + * including but not limited to, any implied warranties of merchantability, + * fitness for a particular purpose, or non-infringement are disclaimed. In + * no event shall DIGITAL be liable for any damages whatsoever, and in + * particular, DIGITAL shall not be liable for special, indirect, + * consequential, or incidental damages or damages for lost profits, loss + * of revenue or loss of use, whether such damages arise in contract, + * negligence, tort, under statute, in equity, at law or otherwise, even if + * advised of the possibility of such damage. + */ + +/* The code below comes from the idea supplied by the people at DEC, like + * the copyright above says. But its had to go through a large evolution + * to fit it into the new design for XFree86 4.0 + */ + +static void +MoveDWORDS(register CARD32* dest, register CARD32* src, register int dwords ) +{ + while(dwords & ~0x03) { + *dest = *src; + *(dest + 1) = *(src + 1); + *(dest + 2) = *(src + 2); + *(dest + 3) = *(src + 3); + src += 4; + dest += 4; + dwords -= 4; + } + switch(dwords){ + case 1: + *dest = *src; + break; + case 2: + *dest = *src; + *(dest + 1) = *(src + 1); + break; + case 3: + *dest = *src; + *(dest + 1) = *(src + 1); + *(dest + 2) = *(src + 2); + break; + } +} + +static __inline__ void +MoveDataFromCPU(unsigned char *src, unsigned char *dest, int srcwidth, + int window, int h, int dwords) +{ + if(srcwidth == (dwords << 2)) { + int decrement = window / dwords; + while(h > decrement) { + MoveDWORDS((CARD32*)dest, (CARD32*)src, dwords * decrement); + src += (srcwidth * decrement); + h -= decrement; + } + if(h) { + MoveDWORDS((CARD32*)dest, (CARD32*)src, dwords * h); + } + } else { + while(h--) { + MoveDWORDS((CARD32*)dest, (CARD32*)src, dwords); + src += srcwidth; + } + } +} + +static __inline__ void +MoveDataToCPU(unsigned char *src, unsigned char *dest, int dstwidth, + int window, int h, int dwords) +{ + if(dstwidth == (dwords << 2)) { + int decrement = window / dwords; + while(h > decrement) { + MoveDWORDS((CARD32*)dest, (CARD32*)src, dwords * decrement); + dest += (dstwidth * decrement); + h -= decrement; + } + if(h) { + MoveDWORDS((CARD32*)dest, (CARD32*)src, dwords * h); + } + } else { + while(h--) { + MoveDWORDS((CARD32*)dest, (CARD32*)src, dwords); + dest += dstwidth; + } + } +} + +static void +CTNAME(WritePixmap)(ScrnInfoPtr pScrn, int x, int y, int w, int h, + unsigned char *src, int srcwidth, int rop, + unsigned int planemask, int trans, int bpp, int depth) +{ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSACLPtr cAcl = CHIPSACLPTR(pScrn); + unsigned int bytesPerLine; + unsigned int byteWidthSrc; + unsigned int destpitch; + int dwords; + int skipleft; + int destaddr; + + DEBUG_P("WritePixmap"); +#ifdef DEBUG + ErrorF("WritePixmap x %d, y %d, w %d, h %d, src 0x%X, srcwidth %d, rop 0x%X, planemask 0x%X, trans 0x%X, bpp %d, depth %d\n", x, y, w, h, src, srcwidth, rop, planemask, trans, bpp, depth); +#endif + bytesPerLine = w * (bpp >> 3); + byteWidthSrc = ((srcwidth * (bpp >> 3) + 3L) & ~0x3L); + cAcl->CommandFlags = ctSRCSYSTEM | ctLEFT2RIGHT | ctTOP2BOTTOM; + skipleft = (unsigned long)src & 0x7; + src = (unsigned char *)((unsigned long)src & ~0x7L); + dwords = (((skipleft + bytesPerLine + 0x7) & ~0x7)) >> 2; + destaddr = (y * pScrn->displayWidth + x) * (bpp >> 3); + destpitch = pScrn->displayWidth * (bpp >> 3); + if ((y >= pScrn->virtualY) && (cPtr->Flags & ChipsOverlay8plus16)) + destaddr += cPtr->FbOffset16; + else + destaddr += cAcl->FbOffset; + + ctBLTWAIT; + + if (trans != -1) { + cAcl->CommandFlags |= ctCOLORTRANSENABLE | ctCOLORTRANSROP | + ctCOLORTRANSNEQUAL; + ctSETMONOCTL(ctDWORDALIGN); + switch (cAcl->BitsPerPixel) { + case 8: + ctSETBGCOLOR8(trans); + break; + case 16: + ctSETBGCOLOR16(trans); + break; + case 24: + ctSETBGCOLOR24(trans); + break; + } + } + + switch (cAcl->BitsPerPixel) { + case 8: + if ((planemask & 0xFF) == 0xFF) { + ctSETROP(cAcl->CommandFlags | ChipsAluConv[rop & 0xF]); + } else { + ctSETROP(cAcl->CommandFlags | ChipsAluConv3[rop & 0xF]); + ctSETPATSRCADDR(cAcl->ScratchAddress); + ctWRITEPLANEMASK8(planemask, cAcl->ScratchAddress); + } + break; + case 16: + if ((planemask & 0xFFFF) == 0xFFFF) { + ctSETROP(cAcl->CommandFlags | ChipsAluConv[rop & 0xF]); + } else { + ctSETROP(cAcl->CommandFlags | ChipsAluConv3[rop & 0xF]); + ctSETPATSRCADDR(cAcl->ScratchAddress); + ctWRITEPLANEMASK16(planemask, cAcl->ScratchAddress); + } + break; + default: + ctSETROP(cAcl->CommandFlags | ChipsAluConv[rop & 0xF]); + break; + } + + /* + * + * CT6555X requires quad-word padding, but XAA provides double-word + * padding. If the width of a region to be transferred happens to be + * quad-word aligned, the transfer is straightforward. If the + * region is double-word aligned, a pair of contiguous scanlines + * is quad-word aligned. In latter case, we can use interleaved + * transfer twice. It is faster than transfer line by line. + * + */ + + ctSETSRCADDR(skipleft); + ctSETDSTADDR(destaddr); + + if ((byteWidthSrc & 0x7) == 0) { /* quad-word aligned */ + + ctSETPITCH(byteWidthSrc, destpitch); + ctSETHEIGHTWIDTHGO(h, bytesPerLine); + + MoveDataFromCPU((unsigned char *)src, + (unsigned char *)cAcl->BltDataWindow, + srcwidth, 16384, h, dwords); + + } else { + unsigned int vert = h; + + h = (vert + 1) >> 1; + + ctSETPITCH(byteWidthSrc << 1, destpitch << 1); + ctSETHEIGHTWIDTHGO(h, bytesPerLine); + + MoveDataFromCPU((unsigned char *)src, + (unsigned char *)cAcl->BltDataWindow, + srcwidth<<1, 16384, h, dwords); + + h = vert >> 1; + src += srcwidth; + y++; + + destaddr = (y * pScrn->displayWidth + x) * (bpp >> 3); + if ((y >= pScrn->virtualY) && (cPtr->Flags & ChipsOverlay8plus16)) + destaddr += cPtr->FbOffset16; + else + destaddr += cAcl->FbOffset; + + ctBLTWAIT; + ctSETDSTADDR(destaddr); + ctSETHEIGHTWIDTHGO(h, bytesPerLine); + + MoveDataFromCPU((unsigned char *)src, + (unsigned char *)cAcl->BltDataWindow, + srcwidth<<1, 16384, h, dwords); + } + + cPtr->AccelInfoRec->NeedToSync = TRUE; +} + +#if 0 +static void +CTNAME(ReadPixmap)(ScrnInfoPtr pScrn, int x, int y, int w, int h, + unsigned char *dst, int dstwidth, int bpp, int depth) +{ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSACLPtr cAcl = CHIPSACLPTR(pScrn); + unsigned int bytesPerLine; + unsigned int byteWidthDst; + unsigned int srcpitch; + int dwords; + int srcaddr; + + DEBUG_P("ReadPixmap"); + bytesPerLine = w * (bpp >> 3); + byteWidthDst = ((dstwidth * (bpp >> 3) + 3L) & ~0x3L); + dwords = (((bytesPerLine + 0x7) & ~0x7)) >> 2; + srcaddr = (y * pScrn->displayWidth + x) * (bpp >> 3); + srcpitch = pScrn->displayWidth * (bpp >> 3); + if ((y >= pScrn->virtualY) && (cPtr->Flags & ChipsOverlay8plus16)) + srcaddr += cPtr->FbOffset16; + else + srcaddr += cAcl->FbOffset; + + ctBLTWAIT; + ctSETROP( ctDSTSYSTEM | ctLEFT2RIGHT | ctTOP2BOTTOM | + ChipsAluConv[GXcopy & 0xF]); + ctSETDSTADDR(0); + ctSETSRCADDR(srcaddr); + + if ((byteWidthDst & 0x7) == 0) { /* quad-word aligned */ + + ctSETPITCH(srcpitch, byteWidthDst); + ctSETHEIGHTWIDTHGO(h, bytesPerLine); + + MoveDataToCPU((unsigned char *)cAcl->BltDataWindow, + (unsigned char *)dst, dstwidth, 16384, h, dwords); + + } else { + unsigned int vert = h; + + h = (vert + 1) >> 1; + + ctSETPITCH(srcpitch << 1, byteWidthDst << 1); + ctSETHEIGHTWIDTHGO(h, bytesPerLine); + + MoveDataToCPU((unsigned char *)cAcl->BltDataWindow, + (unsigned char *)dst, dstwidth<<1, 16384, h, dwords); + + h = vert >> 1; + dst += dstwidth; + y++; + srcaddr = (y * pScrn->displayWidth + x) * (bpp >> 3); + if ((y >= pScrn->virtualY) && (cPtr->Flags & ChipsOverlay8plus16)) + srcaddr += cPtr->FbOffset16; + else + srcaddr += cAcl->FbOffset; + ctBLTWAIT; + ctSETSRCADDR(srcaddr); + ctSETHEIGHTWIDTHGO(h, bytesPerLine); + + MoveDataToCPU((unsigned char *)cAcl->BltDataWindow, + (unsigned char *)dst, dstwidth<<1, 16384, h, dwords); + } + + cPtr->AccelInfoRec->NeedToSync = TRUE; +} +#endif /* ReadPixmap */ + +#endif diff --git a/src/ct_bank.c b/src/ct_bank.c new file mode 100644 index 0000000..1e478ee --- /dev/null +++ b/src/ct_bank.c @@ -0,0 +1,626 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/chips/ct_bank.c,v 1.6 2002/01/25 21:55:58 tsi Exp $ */ + +/* + * Copyright 1997 + * Digital Equipment Corporation. All rights reserved. + * This software is furnished under license and may be used and copied only in + * accordance with the following terms and conditions. Subject to these + * conditions, you may download, copy, install, use, modify and distribute + * this software in source and/or binary form. No title or ownership is + * transferred hereby. + * 1) Any source code used, modified or distributed must reproduce and retain + * this copyright notice and list of conditions as they appear in the + * source file. + * + * 2) No right is granted to use any trade name, trademark, or logo of Digital + * Equipment Corporation. Neither the "Digital Equipment Corporation" name + * nor any trademark or logo of Digital Equipment Corporation may be used + * to endorse or promote products derived from this software without the + * prior written permission of Digital Equipment Corporation. + * + * 3) This software is provided "AS-IS" and any express or implied warranties, + * including but not limited to, any implied warranties of merchantability, + * fitness for a particular purpose, or non-infringement are disclaimed. In + * no event shall DIGITAL be liable for any damages whatsoever, and in + * particular, DIGITAL shall not be liable for special, indirect, + * consequential, or incidental damages or damages for lost profits, loss + * of revenue or loss of use, whether such damages arise in contract, + * negligence, tort, under statute, in equity, at law or otherwise, even if + * advised of the possibility of such damage. + */ +#define PSZ 8 + +/* + * Define DIRECT_REGISTER_ACCESS if you want to bypass the wrapped register + * access functions + */ +/* #define DIRECT_REGISTER_ACCESS */ + +/* All drivers should typically include these */ +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86_ansic.h" + +/* Everything using inb/outb, etc needs "compiler.h" */ +#include "compiler.h" + +/* Drivers for PCI hardware need this */ +#include "xf86PciInfo.h" + +/* Drivers that need to access the PCI config space directly need this */ +#include "xf86Pci.h" + +/* Driver specific headers */ +#include "ct_driver.h" + +#ifdef __arm32__ +/*#include <machine/sysarch.h>*/ +#define arm32_drain_writebuf() sysarch(1, 0) +#define ChipsBank(pScreen) CHIPSPTR(xf86Screens[pScreen->myNum])->Bank +#endif + +#ifdef DIRECT_REGISTER_ACCESS +int +CHIPSSetRead(ScreenPtr pScreen, int bank) +{ + CHIPSPtr cPtr = CHIPSPTR(xf86Screens[pScreen->myNum]); + + outw(cPtr->PIOBase + 0x3D6, ((((bank << 3) & 0xFF) << 8) | 0x10)); + +#ifdef __arm32__ + /* Must drain StrongARM write buffer on bank switch! */ + if (bank != ChipsBank(pScreen)) { + arm32_drain_writebuf(); + ChipsBank(pScreen) = bank; + } +#endif + + return 0; +} + + +int +CHIPSSetWrite(ScreenPtr pScreen, int bank) +{ + CHIPSPtr cPtr = CHIPSPTR(xf86Screens[pScreen->myNum]); + + outw(cPtr->PIOBase + 0x3D6, ((((bank << 3) & 0xFF) << 8) | 0x11)); + +#ifdef __arm32__ + /* Must drain StrongARM write buffer on bank switch! */ + if (bank != ChipsBank(pScreen)) { + arm32_drain_writebuf(); + ChipsBank(pScreen) = bank; + } +#endif + + return 0; +} + + +int +CHIPSSetReadWrite(ScreenPtr pScreen, int bank) +{ + CHIPSPtr cPtr = CHIPSPTR(xf86Screens[pScreen->myNum]); + + outw(cPtr->PIOBase + 0x3D6, ((((bank << 3) & 0xFF) << 8) | 0x10)); + outw(cPtr->PIOBase + 0x3D6, ((((bank << 3) & 0xFF) << 8) | 0x11)); + +#ifdef __arm32__ + /* Must drain StrongARM write buffer on bank switch! */ + if (bank != ChipsBank(pScreen)) { + arm32_drain_writebuf(); + ChipsBank(pScreen) = bank; + } +#endif + + return 0; +} + +int +CHIPSSetReadPlanar(ScreenPtr pScreen, int bank) +{ + CHIPSPtr cPtr = CHIPSPTR(xf86Screens[pScreen->myNum]); + + outw(cPtr->PIOBase + 0x3D6, ((((bank << 5) & 0xFF) << 8) | 0x10)); + +#ifdef __arm32__ + /* Must drain StrongARM write buffer on bank switch! */ + if (bank != ChipsBank(pScreen)) { + arm32_drain_writebuf(); + ChipsBank(pScreen) = bank; + } +#endif + + return 0; +} + +int +CHIPSSetWritePlanar(ScreenPtr pScreen, int bank) +{ + CHIPSPtr cPtr = CHIPSPTR(xf86Screens[pScreen->myNum]); + + outw(cPtr->PIOBase + 0x3D6, ((((bank << 5) & 0xFF) << 8) | 0x11)); + +#ifdef __arm32__ + /* Must drain StrongARM write buffer on bank switch! */ + if (bank != ChipsBank(pScreen)) { + arm32_drain_writebuf(); + ChipsBank(pScreen) = bank; + } +#endif + + return 0; +} + +int +CHIPSSetReadWritePlanar(ScreenPtr pScreen, int bank) +{ + CHIPSPtr cPtr = CHIPSPTR(xf86Screens[pScreen->myNum]); + + outw(cPtr->PIOBase + 0x3D6, ((((bank << 5) & 0xFF) << 8) | 0x10)); + outw(cPtr->PIOBase + 0x3D6, ((((bank << 5) & 0xFF) << 8) | 0x11)); + +#ifdef __arm32__ + /* Must drain StrongARM write buffer on bank switch! */ + if (bank != ChipsBank(pScreen)) { + arm32_drain_writebuf(); + ChipsBank(pScreen) = bank; + } +#endif + + return 0; +} + +int +CHIPSWINSetRead(ScreenPtr pScreen, int bank) +{ + CHIPSPtr cPtr = CHIPSPTR(xf86Screens[pScreen->myNum]); + register unsigned char tmp; + + outw(cPtr->PIOBase + 0x3D6, ((((bank << 3) & 0xFF) << 8) | 0x10)); + outb(cPtr->PIOBase + 0x3D6, 0x0C); + tmp = inb(cPtr->PIOBase + 0x3D7) & 0xEF; + outw(cPtr->PIOBase + 0x3D6, (((((bank >> 1) & 0x10) | tmp) << 8) | 0x0C)); + +#ifdef __arm32__ + /* Must drain StrongARM write buffer on bank switch! */ + if (bank != ChipsBank(pScreen)) { + arm32_drain_writebuf(); + ChipsBank(pScreen) = bank; + } +#endif + + return 0; +} + + +int +CHIPSWINSetWrite(ScreenPtr pScreen, int bank) +{ + CHIPSPtr cPtr = CHIPSPTR(xf86Screens[pScreen->myNum]); + register unsigned char tmp; + + outw(cPtr->PIOBase + 0x3D6, ((((bank << 3) & 0xFF) << 8) | 0x11)); + outb(cPtr->PIOBase + 0x3D6, 0x0C); + tmp = inb(cPtr->PIOBase + 0x3D7) & 0xBF; + outw(cPtr->PIOBase + 0x3D6, (((((bank << 1) & 0x40) | tmp) << 8) | 0x0C)); + +#ifdef __arm32__ + /* Must drain StrongARM write buffer on bank switch! */ + if (bank != ChipsBank(pScreen)) { + arm32_drain_writebuf(); + ChipsBank(pScreen) = bank; + } +#endif + + return 0; +} + +int +CHIPSWINSetReadWrite(ScreenPtr pScreen, int bank) +{ + CHIPSPtr cPtr = CHIPSPTR(xf86Screens[pScreen->myNum]); + register unsigned char tmp; + + outw(cPtr->PIOBase + 0x3D6, ((((bank << 3) & 0xFF) << 8) | 0x10)); + outw(cPtr->PIOBase + 0x3D6, ((((bank << 3) & 0xFF) << 8) | 0x11)); + outb(cPtr->PIOBase + 0x3D6, 0x0C); + tmp = inb(cPtr->PIOBase + 0x3D7) & 0xAF; + outw(cPtr->PIOBase + 0x3D6, + (((((bank << 1) & 0x40) | ((bank >> 1) & 0x10) | tmp) << 8) | 0x0C)); + +#ifdef __arm32__ + /* Must drain StrongARM write buffer on bank switch! */ + if (bank != ChipsBank(pScreen)) { + arm32_drain_writebuf(); + ChipsBank(pScreen) = bank; + } +#endif + + return 0; +} + +int +CHIPSWINSetReadPlanar(ScreenPtr pScreen, int bank) +{ + CHIPSPtr cPtr = CHIPSPTR(xf86Screens[pScreen->myNum]); + register unsigned char tmp; + + outw(cPtr->PIOBase + 0x3D6, ((((bank << 5) & 0xFF) << 8) | 0x10)); + outb(cPtr->PIOBase + 0x3D6, 0x0C); + tmp = inb(cPtr->PIOBase + 0x3D7) & 0xEF; + outw(cPtr->PIOBase + 0x3D6, (((((bank << 1) & 0x10) | tmp) << 8) | 0x0C)); + +#ifdef __arm32__ + /* Must drain StrongARM write buffer on bank switch! */ + if (bank != ChipsBank(pScreen)) { + arm32_drain_writebuf(); + ChipsBank(pScreen) = bank; + } +#endif + + return 0; +} + +int +CHIPSWINSetWritePlanar(ScreenPtr pScreen, int bank) +{ + CHIPSPtr cPtr = CHIPSPTR(xf86Screens[pScreen->myNum]); + register unsigned char tmp; + + outw(cPtr->PIOBase + 0x3D6, ((((bank << 5) & 0xFF) << 8) | 0x11)); + outb(cPtr->PIOBase + 0x3D6, 0x0C); + tmp = inb(cPtr->PIOBase + 0x3D7) & 0xBF; + outw(cPtr->PIOBase + 0x3D6, (((((bank << 3) & 0x40) | tmp) << 8) | 0x0C)); + +#ifdef __arm32__ + /* Must drain StrongARM write buffer on bank switch! */ + if (bank != ChipsBank(pScreen)) { + arm32_drain_writebuf(); + ChipsBank(pScreen) = bank; + } +#endif + + return 0; +} + +int +CHIPSWINSetReadWritePlanar(ScreenPtr pScreen, int bank) +{ + CHIPSPtr cPtr = CHIPSPTR(xf86Screens[pScreen->myNum]); + register unsigned char tmp; + + outw(cPtr->PIOBase + 0x3D6, ((((bank << 5) & 0xFF) << 8) | 0x10)); + outw(cPtr->PIOBase + 0x3D6, ((((bank << 5) & 0xFF) << 8) | 0x11)); + outb(cPtr->PIOBase + 0x3D6, 0x0C); + tmp = inb(cPtr->PIOBase + 0x3D7) & 0xAF; + outw(cPtr->PIOBase + 0x3D6, + (((((bank << 3) & 0x40) | ((bank << 1) & 0x10) | tmp) << 8) | 0x0C)); + +#ifdef __arm32__ + /* Must drain StrongARM write buffer on bank switch! */ + if (bank != ChipsBank(pScreen)) { + arm32_drain_writebuf(); + ChipsBank(pScreen) = bank; + } +#endif + + return 0; +} + +int +CHIPSHiQVSetReadWrite(ScreenPtr pScreen, int bank) +{ + CHIPSPtr cPtr = CHIPSPTR(xf86Screens[pScreen->myNum]); + + outw(cPtr->PIOBase + 0x3D6, (((bank & 0x7F) << 8) | 0x0E)); + +#ifdef __arm32__ + /* Must drain StrongARM write buffer on bank switch! */ + if (bank != ChipsBank(pScreen)) { + arm32_drain_writebuf(); + ChipsBank(pScreen) = bank; + } +#endif + + return 0; +} + +int +CHIPSHiQVSetReadWritePlanar(ScreenPtr pScreen, int bank) +{ + CHIPSPtr cPtr = CHIPSPTR(xf86Screens[pScreen->myNum]); + + outw(cPtr->PIOBase + 0x3D6, ((((bank << 2) & 0x7F) << 8) | 0x0E)); + +#ifdef __arm32__ + /* Must drain StrongARM write buffer on bank switch! */ + if (bank != ChipsBank(pScreen)) { + arm32_drain_writebuf(); + ChipsBank(pScreen) = bank; + } +#endif + + return 0; +} + +#else /* DIRECT_REGISTER_ACCESS */ + +int +CHIPSSetRead(ScreenPtr pScreen, int bank) +{ + CHIPSPtr cPtr = CHIPSPTR(xf86Screens[pScreen->myNum]); + + cPtr->writeXR(cPtr, 0x10, ((bank << 3) & 0xFF)); + +#ifdef __arm32__ + /* Must drain StrongARM write buffer on bank switch! */ + if (bank != cPtr->Bank) { + arm32_drain_writebuf(); + cPtr->Bank = bank; + } +#endif + + return 0; +} + + +int +CHIPSSetWrite(ScreenPtr pScreen, int bank) +{ + CHIPSPtr cPtr = CHIPSPTR(xf86Screens[pScreen->myNum]); + + cPtr->writeXR(cPtr, 0x11, ((bank << 3) & 0xFF)); + +#ifdef __arm32__ + /* Must drain StrongARM write buffer on bank switch! */ + if (bank != cPtr->Bank) { + arm32_drain_writebuf(); + cPtr->Bank = bank; + } +#endif + + return 0; +} + + +int +CHIPSSetReadWrite(ScreenPtr pScreen, int bank) +{ + CHIPSPtr cPtr = CHIPSPTR(xf86Screens[pScreen->myNum]); + + cPtr->writeXR(cPtr, 0x10, ((bank << 3) & 0xFF)); + cPtr->writeXR(cPtr, 0x11, ((bank << 3) & 0xFF)); + +#ifdef __arm32__ + /* Must drain StrongARM write buffer on bank switch! */ + if (bank != cPtr->Bank) { + arm32_drain_writebuf(); + cPtr->Bank = bank; + } +#endif + + return 0; +} + +int +CHIPSSetReadPlanar(ScreenPtr pScreen, int bank) +{ + CHIPSPtr cPtr = CHIPSPTR(xf86Screens[pScreen->myNum]); + + cPtr->writeXR(cPtr, 0x10, ((bank << 5) & 0xFF)); + +#ifdef __arm32__ + /* Must drain StrongARM write buffer on bank switch! */ + if (bank != cPtr->Bank) { + arm32_drain_writebuf(); + cPtr->Bank = bank; + } +#endif + + return 0; +} + +int +CHIPSSetWritePlanar(ScreenPtr pScreen, int bank) +{ + CHIPSPtr cPtr = CHIPSPTR(xf86Screens[pScreen->myNum]); + + cPtr->writeXR(cPtr, 0x11, ((bank << 5) & 0xFF)); + +#ifdef __arm32__ + /* Must drain StrongARM write buffer on bank switch! */ + if (bank != cPtr->Bank) { + arm32_drain_writebuf(); + cPtr->Bank = bank; + } +#endif + + return 0; +} + +int +CHIPSSetReadWritePlanar(ScreenPtr pScreen, int bank) +{ + CHIPSPtr cPtr = CHIPSPTR(xf86Screens[pScreen->myNum]); + + cPtr->writeXR(cPtr, 0x10, ((bank << 5) & 0xFF)); + cPtr->writeXR(cPtr, 0x11, ((bank << 5) & 0xFF)); + +#ifdef __arm32__ + /* Must drain StrongARM write buffer on bank switch! */ + if (bank != cPtr->Bank) { + arm32_drain_writebuf(); + cPtr->Bank = bank; + } +#endif + + return 0; +} + +int +CHIPSWINSetRead(ScreenPtr pScreen, int bank) +{ + CHIPSPtr cPtr = CHIPSPTR(xf86Screens[pScreen->myNum]); + register unsigned char tmp; + + cPtr->writeXR(cPtr, 0x10, ((bank << 3) & 0xFF)); + tmp = cPtr->readXR(cPtr, 0x0C) & 0xEF; + cPtr->writeXR(cPtr, 0x0C, ((bank >> 1) & 0x10) | tmp); + +#ifdef __arm32__ + /* Must drain StrongARM write buffer on bank switch! */ + if (bank != cPtr->Bank) { + arm32_drain_writebuf(); + cPtr->Bank = bank; + } +#endif + + return 0; +} + + +int +CHIPSWINSetWrite(ScreenPtr pScreen, int bank) +{ + CHIPSPtr cPtr = CHIPSPTR(xf86Screens[pScreen->myNum]); + register unsigned char tmp; + + cPtr->writeXR(cPtr, 0x11, ((bank << 3) & 0xFF)); + tmp = cPtr->readXR(cPtr, 0x0C) & 0xBF; + cPtr->writeXR(cPtr, 0x0C, ((bank << 1) & 0x40) | tmp); + +#ifdef __arm32__ + /* Must drain StrongARM write buffer on bank switch! */ + if (bank != cPtr->Bank) { + arm32_drain_writebuf(); + cPtr->Bank = bank; + } +#endif + + return 0; +} + +int +CHIPSWINSetReadWrite(ScreenPtr pScreen, int bank) +{ + CHIPSPtr cPtr = CHIPSPTR(xf86Screens[pScreen->myNum]); + register unsigned char tmp; + + cPtr->writeXR(cPtr, 0x10, ((bank << 3) & 0xFF)); + cPtr->writeXR(cPtr, 0x11, ((bank << 3) & 0xFF)); + tmp = cPtr->readXR(cPtr, 0x0C) & 0xAF; + cPtr->writeXR(cPtr, 0x0C, ((bank << 1) & 0x40) | ((bank >> 1) & 0x10) | tmp); + +#ifdef __arm32__ + /* Must drain StrongARM write buffer on bank switch! */ + if (bank != cPtr->Bank) { + arm32_drain_writebuf(); + cPtr->Bank = bank; + } +#endif + + return 0; +} + +int +CHIPSWINSetReadPlanar(ScreenPtr pScreen, int bank) +{ + CHIPSPtr cPtr = CHIPSPTR(xf86Screens[pScreen->myNum]); + register unsigned char tmp; + + cPtr->writeXR(cPtr, 0x10, ((bank << 5) & 0xFF)); + tmp = cPtr->readXR(cPtr, 0x0C) & 0xEF; + cPtr->writeXR(cPtr, 0x0C, ((bank << 1) & 0x10) | tmp); + +#ifdef __arm32__ + /* Must drain StrongARM write buffer on bank switch! */ + if (bank != cPtr->Bank) { + arm32_drain_writebuf(); + cPtr->Bank = bank; + } +#endif + + return 0; +} + +int +CHIPSWINSetWritePlanar(ScreenPtr pScreen, int bank) +{ + CHIPSPtr cPtr = CHIPSPTR(xf86Screens[pScreen->myNum]); + register unsigned char tmp; + + cPtr->writeXR(cPtr, 0x11, ((bank << 5) & 0xFF)); + tmp = cPtr->readXR(cPtr, 0x0C) & 0xBF; + cPtr->writeXR(cPtr, 0x0C, ((bank << 3) & 0x40) | tmp); + +#ifdef __arm32__ + /* Must drain StrongARM write buffer on bank switch! */ + if (bank != cPtr->Bank) { + arm32_drain_writebuf(); + cPtr->Bank = bank; + } +#endif + + return 0; +} + +int +CHIPSWINSetReadWritePlanar(ScreenPtr pScreen, int bank) +{ + CHIPSPtr cPtr = CHIPSPTR(xf86Screens[pScreen->myNum]); + register unsigned char tmp; + + cPtr->writeXR(cPtr, 0x10, ((bank << 5) & 0xFF)); + cPtr->writeXR(cPtr, 0x11, ((bank << 5) & 0xFF)); + tmp = cPtr->readXR(cPtr, 0x0C) & 0xAF; + cPtr->writeXR(cPtr, 0x0C, ((bank << 3) & 0x40) | ((bank << 1) & 0x10) | tmp); + +#ifdef __arm32__ + /* Must drain StrongARM write buffer on bank switch! */ + if (bank != cPtr->Bank) { + arm32_drain_writebuf(); + cPtr->Bank = bank; + } +#endif + + return 0; +} + +int +CHIPSHiQVSetReadWrite(ScreenPtr pScreen, int bank) +{ + CHIPSPtr cPtr = CHIPSPTR(xf86Screens[pScreen->myNum]); + + cPtr->writeXR(cPtr, 0x0E, bank & 0x7F); + +#ifdef __arm32__ + /* Must drain StrongARM write buffer on bank switch! */ + if (bank != cPtr->Bank) { + arm32_drain_writebuf(); + cPtr->Bank = bank; + } +#endif + + return 0; +} + +int +CHIPSHiQVSetReadWritePlanar(ScreenPtr pScreen, int bank) +{ + CHIPSPtr cPtr = CHIPSPTR(xf86Screens[pScreen->myNum]); + + cPtr->writeXR(cPtr, 0x0E, (bank << 2) & 0x7F); + +#ifdef __arm32__ + /* Must drain StrongARM write buffer on bank switch! */ + if (bank != cPtr->Bank) { + arm32_drain_writebuf(); + cPtr->Bank = bank; + } +#endif + + return 0; +} +#endif diff --git a/src/ct_cursor.c b/src/ct_cursor.c new file mode 100644 index 0000000..44a7e8a --- /dev/null +++ b/src/ct_cursor.c @@ -0,0 +1,481 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/chips/ct_cursor.c,v 1.27 2002/11/25 14:04:58 eich Exp $ */ + +/* + * Copyright 1994 The XFree86 Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * DAVID WEXELBLAT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Hardware Cursor for Trident utilizing XAA Cursor code. + * Written by Alan Hourihane <alanh@fairlite.demon.co.uk> + * Modified for Chips and Technologies by David Bateman <dbateman@eng.uts.edu.au> + */ + +/* All drivers should typically include these */ +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86_ansic.h" + +/* Everything using inb/outb, etc needs "compiler.h" */ +#include "compiler.h" + +/* Drivers for PCI hardware need this */ +#include "xf86PciInfo.h" + +/* Drivers that need to access the PCI config space directly need this */ +#include "xf86Pci.h" + +#include "xf86Cursor.h" + +/* Driver specific headers */ +#include "ct_driver.h" + +/* Sync function, maybe this should check infoRec->NeedToSync before syncing */ +#define CURSOR_SYNC(pScrn) \ + if (IS_HiQV(cPtr)) { \ + CHIPSHiQVSync(pScrn); \ + } else { \ + if(!cPtr->UseMMIO) { \ + CHIPSSync(pScrn); \ + } else { \ + CHIPSMMIOSync(pScrn); \ + } \ + } + +/* Swing your cursor bytes round and round... yeehaw! */ +#if X_BYTE_ORDER == X_BIG_ENDIAN +#define P_SWAP32( a , b ) \ + ((char *)a)[0] = ((char *)b)[3]; \ + ((char *)a)[1] = ((char *)b)[2]; \ + ((char *)a)[2] = ((char *)b)[1]; \ + ((char *)a)[3] = ((char *)b)[0] + +#define P_SWAP16( a , b ) \ + ((char *)a)[0] = ((char *)b)[1]; \ + ((char *)a)[1] = ((char *)b)[0]; \ + ((char *)a)[2] = ((char *)b)[3]; \ + ((char *)a)[3] = ((char *)b)[2] +#endif + +static void +CHIPSShowCursor(ScrnInfoPtr pScrn) +{ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + unsigned char tmp; + + CURSOR_SYNC(pScrn); + + /* turn the cursor on */ + if (IS_HiQV(cPtr)) { + tmp = cPtr->readXR(cPtr, 0xA0); + cPtr->writeXR(cPtr, 0xA0, (tmp & 0xF8) | 5); + if (cPtr->UseDualChannel && + (! xf86IsEntityShared(pScrn->entityList[0]))) { + unsigned int IOSS, MSS; + IOSS = cPtr->readIOSS(cPtr); + MSS = cPtr->readMSS(cPtr); + cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) | + IOSS_PIPE_B)); + cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), ((cPtr->storeMSS & + MSS_MASK) | MSS_PIPE_B)); + tmp = cPtr->readXR(cPtr, 0xA0); + cPtr->writeXR(cPtr, 0xA0, (tmp & 0xF8) | 5); + cPtr->writeIOSS(cPtr, IOSS); + cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), MSS); + } + } else { + if(!cPtr->UseMMIO) { + HW_DEBUG(0x8); + outw(cPtr->PIOBase+DR(0x8), 0x21); + } else { + HW_DEBUG(DR(8)); + /* Used to be: MMIOmemw(MR(8)) = 0x21; */ + MMIOmeml(MR(8)) = 0x21; + } + } + cPtr->HWCursorShown = TRUE; +} + +static void +CHIPSHideCursor(ScrnInfoPtr pScrn) +{ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + unsigned char tmp; + + CURSOR_SYNC(pScrn); + + /* turn the cursor off */ + if (IS_HiQV(cPtr)) { + tmp = cPtr->readXR(cPtr, 0xA0); + cPtr->writeXR(cPtr, 0xA0, tmp & 0xF8); + if (cPtr->UseDualChannel && + (! xf86IsEntityShared(pScrn->entityList[0]))) { + unsigned int IOSS, MSS; + IOSS = cPtr->readIOSS(cPtr); + MSS = cPtr->readMSS(cPtr); + cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) | + IOSS_PIPE_B)); + cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), ((cPtr->storeMSS & + MSS_MASK) | MSS_PIPE_B)); + tmp = cPtr->readXR(cPtr, 0xA0); + cPtr->writeXR(cPtr, 0xA0, tmp & 0xF8); + cPtr->writeIOSS(cPtr, IOSS); + cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), MSS); + } + } else { + if(!cPtr->UseMMIO) { + HW_DEBUG(0x8); + outw(cPtr->PIOBase+DR(0x8), 0x20); + } else { + HW_DEBUG(DR(0x8)); + /* Used to be: MMIOmemw(DR(0x8)) = 0x20; */ + MMIOmeml(DR(0x8)) = 0x20; + } + } + cPtr->HWCursorShown = FALSE; +} + +static void +CHIPSSetCursorPosition(ScrnInfoPtr pScrn, int x, int y) +{ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + + CURSOR_SYNC(pScrn); + + if (pScrn->currentMode->Flags & V_DBLSCAN) + y *= 2; + + if (x < 0) + x = ~(x-1) | 0x8000; + if (y < 0) + y = ~(y-1) | 0x8000; + + /* Program the cursor origin (offset into the cursor bitmap). */ + if (IS_HiQV(cPtr)) { + cPtr->writeXR(cPtr, 0xA4, x & 0xFF); + cPtr->writeXR(cPtr, 0xA5, (x >> 8) & 0x87); + cPtr->writeXR(cPtr, 0xA6, y & 0xFF); + cPtr->writeXR(cPtr, 0xA7, (y >> 8) & 0x87); + if (cPtr->UseDualChannel && + (! xf86IsEntityShared(pScrn->entityList[0]))) { + unsigned int IOSS, MSS; + IOSS = cPtr->readIOSS(cPtr); + MSS = cPtr->readMSS(cPtr); + cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) | + IOSS_PIPE_B)); + cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), ((cPtr->storeMSS & + MSS_MASK) | MSS_PIPE_B)); + cPtr->writeXR(cPtr, 0xA4, x & 0xFF); + cPtr->writeXR(cPtr, 0xA5, (x >> 8) & 0x87); + cPtr->writeXR(cPtr, 0xA6, y & 0xFF); + cPtr->writeXR(cPtr, 0xA7, (y >> 8) & 0x87); + cPtr->writeIOSS(cPtr, IOSS); + cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), MSS); + } + } else { + CARD32 xy; + + xy = y; + xy = (xy << 16) | x; + if(!cPtr->UseMMIO) { + HW_DEBUG(0xB); + outl(cPtr->PIOBase+DR(0xB), xy); + } else { + HW_DEBUG(MR(0xB)); + MMIOmeml(MR(0xB)) = xy; + } + } +} + +static void +CHIPSSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) +{ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + vgaHWPtr hwp = VGAHWPTR(pScrn); + CARD32 packedcolfg, packedcolbg; + + CURSOR_SYNC(pScrn); + + if (IS_HiQV(cPtr)) { + unsigned char xr80; + + /* Enable extended palette addressing */ + xr80 = cPtr->readXR(cPtr, 0x80); + cPtr->writeXR(cPtr, 0x80, xr80 | 0x1); + + /* Write the new colours to the extended VGA palette. Palette + * index is incremented after each write, so only write index + * once + */ + hwp->writeDacWriteAddr(hwp, 0x04); + if (xr80 & 0x80) { + /* 8bit DAC */ + hwp->writeDacData(hwp, (bg >> 16) & 0xFF); + hwp->writeDacData(hwp, (bg >> 8) & 0xFF); + hwp->writeDacData(hwp, bg & 0xFF); + hwp->writeDacData(hwp, (fg >> 16) & 0xFF); + hwp->writeDacData(hwp, (fg >> 8) & 0xFF); + hwp->writeDacData(hwp, fg & 0xFF); + } else { + /* 6bit DAC */ + hwp->writeDacData(hwp, (bg >> 18) & 0xFF); + hwp->writeDacData(hwp, (bg >> 10) & 0xFF); + hwp->writeDacData(hwp, (bg >> 2) & 0xFF); + hwp->writeDacData(hwp, (fg >> 18) & 0xFF); + hwp->writeDacData(hwp, (fg >> 10) & 0xFF); + hwp->writeDacData(hwp, (fg >> 2) & 0xFF); + } + /* Enable normal palette addressing */ + cPtr->writeXR(cPtr, 0x80, xr80); + + if (cPtr->UseDualChannel && + (! xf86IsEntityShared(pScrn->entityList[0]))) { + unsigned int IOSS, MSS; + IOSS = cPtr->readIOSS(cPtr); + MSS = cPtr->readMSS(cPtr); + cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) | + IOSS_PIPE_B)); + cPtr->writeMSS(cPtr, hwp, ((cPtr->storeMSS & MSS_MASK) | + MSS_PIPE_B)); + /* Enable extended palette addressing */ + xr80 = cPtr->readXR(cPtr, 0x80); + cPtr->writeXR(cPtr, 0x80, xr80 | 0x1); + + /* Write the new colours to the extended VGA palette. Palette + * index is incremented after each write, so only write index + * once + */ + hwp->writeDacWriteAddr(hwp, 0x04); + if (xr80 & 0x80) { + /* 8bit DAC */ + hwp->writeDacData(hwp, (bg >> 16) & 0xFF); + hwp->writeDacData(hwp, (bg >> 8) & 0xFF); + hwp->writeDacData(hwp, bg & 0xFF); + hwp->writeDacData(hwp, (fg >> 16) & 0xFF); + hwp->writeDacData(hwp, (fg >> 8) & 0xFF); + hwp->writeDacData(hwp, fg & 0xFF); + } else { + /* 6bit DAC */ + hwp->writeDacData(hwp, (bg >> 18) & 0xFF); + hwp->writeDacData(hwp, (bg >> 10) & 0xFF); + hwp->writeDacData(hwp, (bg >> 2) & 0xFF); + hwp->writeDacData(hwp, (fg >> 18) & 0xFF); + hwp->writeDacData(hwp, (fg >> 10) & 0xFF); + hwp->writeDacData(hwp, (fg >> 2) & 0xFF); + } + /* Enable normal palette addressing */ + cPtr->writeXR(cPtr, 0x80, xr80); + cPtr->writeIOSS(cPtr, IOSS); + cPtr->writeMSS(cPtr, hwp, MSS); + } + } else if (IS_Wingine(cPtr)) { + outl(cPtr->PIOBase+DR(0xA), (bg & 0xFFFFFF)); + outl(cPtr->PIOBase+DR(0x9), (fg & 0xFFFFFF)); + } else { + packedcolfg = ((fg & 0xF80000) >> 8) | ((fg & 0xFC00) >> 5) + | ((fg & 0xF8) >> 3); + packedcolbg = ((bg & 0xF80000) >> 8) | ((bg & 0xFC00) >> 5) + | ((bg & 0xF8) >> 3); + packedcolfg = (packedcolfg << 16) | packedcolbg; + if(!cPtr->UseMMIO) { + HW_DEBUG(0x9); + outl(cPtr->PIOBase+DR(0x9), packedcolfg); + } else { + MMIOmeml(MR(0x9)) = packedcolfg; + HW_DEBUG(MR(0x9)); + } + } +} + +static void +CHIPSLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src) +{ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSACLPtr cAcl = CHIPSACLPTR(pScrn); +#if X_BYTE_ORDER == X_BIG_ENDIAN + CARD32 *s = (pointer)src; + CARD32 *d = (pointer)(cPtr->FbBase + cAcl->CursorAddress); + int y; +#endif + + CURSOR_SYNC(pScrn); + + if (cPtr->cursorDelay) { + usleep(200000); + cPtr->cursorDelay = FALSE; + } + + if (IS_Wingine(cPtr)) { + int i; + CARD32 *tmp = (CARD32 *)src; + + outl(cPtr->PIOBase+DR(0x8),0x20); + for (i=0; i<64; i++) { + outl(cPtr->PIOBase+DR(0xC),*(CARD32 *)tmp); + tmp++; + } + } else { + if (cPtr->Flags & ChipsLinearSupport) { +#if X_BYTE_ORDER == X_BIG_ENDIAN + /* On big endian machines we must flip our cursor image around. */ + switch(cAcl->BytesPerPixel) { + case 4: + case 3: + for (y = 0; y < 64; y++) { + P_SWAP32(d,s); + d++; s++; + P_SWAP32(d,s); + d++; s++; + P_SWAP32(d,s); + d++; s++; + P_SWAP32(d,s); + d++; s++; + } + break; + case 2: + for (y = 0; y < 64; y++) { + P_SWAP16(d,s); + d++; s++; + P_SWAP16(d,s); + d++; s++; + P_SWAP16(d,s); + d++; s++; + P_SWAP16(d,s); + d++; s++; + P_SWAP16(d,s); + d++; s++; + } + break; + default: + for (y = 0; y < 64; y++) { + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + } + } +#else + memcpy((unsigned char *)cPtr->FbBase + cAcl->CursorAddress, + src, cPtr->CursorInfoRec->MaxWidth * + cPtr->CursorInfoRec->MaxHeight / 4); +#endif + } else { + /* + * The cursor can only be in the last 16K of video memory, + * which fits in the last banking window. + */ + if (IS_HiQV(cPtr)) + if (pScrn->bitsPerPixel < 8) + CHIPSHiQVSetReadWritePlanar(pScrn->pScreen, + (int)(cAcl->CursorAddress >> 16)); + else + CHIPSHiQVSetReadWrite(pScrn->pScreen, + (int)(cAcl->CursorAddress >> 16)); + else + if (pScrn->bitsPerPixel < 8) + CHIPSSetWritePlanar(pScrn->pScreen, + (int)(cAcl->CursorAddress >> 16)); + else + CHIPSSetWrite(pScrn->pScreen, + (int)(cAcl->CursorAddress >> 16)); + memcpy((unsigned char *)cPtr->FbBase + (cAcl->CursorAddress & + 0xFFFF), src, cPtr->CursorInfoRec->MaxWidth * + cPtr->CursorInfoRec->MaxHeight / 4); + } + } + + /* set cursor address here or we loose the cursor on video mode change */ + if (IS_HiQV(cPtr)) { + cPtr->writeXR(cPtr, 0xA2, (cAcl->CursorAddress >> 8) & 0xFF); + cPtr->writeXR(cPtr, 0xA3, (cAcl->CursorAddress >> 16) & 0x3F); + if (cPtr->UseDualChannel && + (! xf86IsEntityShared(pScrn->entityList[0]))) { + unsigned int IOSS, MSS; + IOSS = cPtr->readIOSS(cPtr); + MSS = cPtr->readMSS(cPtr); + cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) | + IOSS_PIPE_B)); + cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), ((cPtr->storeMSS & + MSS_MASK) | MSS_PIPE_B)); + cPtr->writeXR(cPtr, 0xA2, (cAcl->CursorAddress >> 8) & 0xFF); + cPtr->writeXR(cPtr, 0xA3, (cAcl->CursorAddress >> 16) & 0x3F); + cPtr->writeIOSS(cPtr, IOSS); + cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), MSS); + } + } else if (!IS_Wingine(cPtr)) { + if (!cPtr->UseMMIO) { + HW_DEBUG(0xC); + outl(cPtr->PIOBase+DR(0xC), cAcl->CursorAddress); + } else { + HW_DEBUG(MR(0xC)); + MMIOmeml(MR(0xC)) = cAcl->CursorAddress; + } + } +} + +static Bool +CHIPSUseHWCursor(ScreenPtr pScr, CursorPtr pCurs) +{ + CHIPSPtr cPtr = CHIPSPTR(xf86Screens[pScr->myNum]); + return ((cPtr->Flags & ChipsHWCursor) != 0); +} + +Bool +CHIPSCursorInit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + CHIPSPtr cPtr = CHIPSPTR(pScrn); + xf86CursorInfoPtr infoPtr; + + infoPtr = xf86CreateCursorInfoRec(); + if(!infoPtr) return FALSE; + + cPtr->CursorInfoRec = infoPtr; + + infoPtr->Flags = +#if X_BYTE_ORDER == X_LITTLE_ENDIAN + HARDWARE_CURSOR_BIT_ORDER_MSBFIRST | +#endif + HARDWARE_CURSOR_INVERT_MASK | + HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK | + HARDWARE_CURSOR_TRUECOLOR_AT_8BPP; + + if (IS_HiQV(cPtr)) { + infoPtr->Flags |= HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64; + infoPtr->MaxHeight = 64; + infoPtr->MaxWidth = 64; + } else if (IS_Wingine(cPtr)) { + infoPtr->Flags |= HARDWARE_CURSOR_SOURCE_MASK_NOT_INTERLEAVED; + infoPtr->MaxHeight = 32; + infoPtr->MaxWidth = 32; + } else { + infoPtr->Flags |= HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_8; + infoPtr->MaxHeight = 32; + infoPtr->MaxWidth = 32; + } + + infoPtr->SetCursorColors = CHIPSSetCursorColors; + infoPtr->SetCursorPosition = CHIPSSetCursorPosition; + infoPtr->LoadCursorImage = CHIPSLoadCursorImage; + infoPtr->HideCursor = CHIPSHideCursor; + infoPtr->ShowCursor = CHIPSShowCursor; + infoPtr->UseHWCursor = CHIPSUseHWCursor; + + return(xf86InitCursor(pScreen, infoPtr)); +} + diff --git a/src/ct_ddc.c b/src/ct_ddc.c new file mode 100644 index 0000000..0286685 --- /dev/null +++ b/src/ct_ddc.c @@ -0,0 +1,282 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/chips/ct_ddc.c,v 1.8 2001/05/09 19:57:04 dbateman Exp $ */ + +/* All drivers should typically include these */ +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86_ansic.h" + +/* Everything using inb/outb, etc needs "compiler.h" */ +#include "compiler.h" + +/* Drivers for PCI hardware need this */ +#include "xf86PciInfo.h" + +/* Drivers that need to access the PCI config space directly need this */ +#include "xf86Pci.h" + +#include "ct_driver.h" + +static Bool chips_TestI2C(int scrnIndex); +static Bool chips_setI2CBits(I2CBusPtr I2CPtr, ScrnInfoPtr pScrn); + +static unsigned int +chips_ddc1Read(ScrnInfoPtr pScrn) +{ + unsigned char ddc_mask = ((CHIPSPtr)pScrn->driverPrivate)->ddc_mask; + CHIPSPtr cPtr = CHIPSPTR(pScrn); + vgaHWPtr hwp = VGAHWPTR(pScrn); + + register unsigned int tmp; + + while ((hwp->readST01(hwp)) & 0x08){}; + while (!(hwp->readST01(hwp)) & 0x08){}; + tmp = cPtr->readXR(cPtr, 0x63); + return (tmp & ddc_mask); +} + +void +chips_ddc1(ScrnInfoPtr pScrn) +{ + unsigned char FR0B, FR0C, XR62; + unsigned char mask_c = 0x00; + unsigned char val, tmp_val; + int i; + CHIPSPtr cPtr = CHIPSPTR(pScrn); + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Probing for DDC1\n"); + + FR0C = cPtr->readFR(cPtr, 0x0C); + XR62 = cPtr->readXR(cPtr, 0x62); + switch (cPtr->Chipset) { + case CHIPS_CT65550: + cPtr->ddc_mask = 0x1F; /* GPIO 0-4 */ + FR0B = cPtr->readFR(cPtr, 0x0B); + if (!(FR0B & 0x10)) /* GPIO 2 is used as 32 kHz input */ + cPtr->ddc_mask &= 0xFB; + if (cPtr->Bus == ChipsVLB) /* GPIO 3-7 are used as address bits */ + cPtr->ddc_mask &= 0x07; + break; + case CHIPS_CT65554: + case CHIPS_CT65555: + case CHIPS_CT68554: + cPtr->ddc_mask = 0x0F; /* GPIO 0-3 */ + break; + case CHIPS_CT69000: + case CHIPS_CT69030: + cPtr->ddc_mask = 0x9F; /* GPIO 0-4,7? */ + break; + default: + cPtr->ddc_mask = 0x0C; /* GPIO 2,3 */ + break; + } + if (!(FR0C & 0x80)) { /* GPIO 1 is not available */ + mask_c |= 0xC0; + cPtr->ddc_mask &= 0xFE; + } + if (!(FR0C & 0x10)) { /* GPIO 0 is not available */ + mask_c |= 0x18; + cPtr->ddc_mask &= 0xFD; + } + + /* set GPIO 0,1 to read if available */ + cPtr->writeFR(cPtr, 0x0C, (FR0C & mask_c) | (~mask_c & 0x90)); + /* set remaining GPIO to read */ + cPtr->writeXR(cPtr, 0x62, 0x00); + + val = chips_ddc1Read(pScrn); + for (i = 0; i < 70; i++) { + tmp_val = chips_ddc1Read(pScrn); + if (tmp_val != val) + break; + } + cPtr->ddc_mask = val ^ tmp_val; + if (cPtr->ddc_mask) + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DDC1 found\n"); + else return; + + xf86PrintEDID(xf86DoEDID_DDC1(pScrn->scrnIndex,vgaHWddc1SetSpeed, + chips_ddc1Read)); + + /* restore */ + cPtr->writeFR(cPtr, 0x0C, FR0C); + cPtr->writeXR(cPtr, 0x62, XR62); +} + +static void +chips_I2CGetBits(I2CBusPtr b, int *clock, int *data) +{ + CHIPSI2CPtr pI2C_c = (CHIPSI2CPtr) (b->DriverPrivate.ptr); + unsigned char FR0C, XR62, val; + + FR0C = pI2C_c->cPtr->readFR(pI2C_c->cPtr, 0x0C); + if (pI2C_c->i2cDataBit & 0x01 || pI2C_c->i2cClockBit & 0x01) + FR0C = (FR0C & 0xE7) | 0x10; + if (pI2C_c->i2cDataBit & 0x02 || pI2C_c->i2cClockBit & 0x02) + FR0C = (FR0C & 0x3F) | 0x80; + XR62 = pI2C_c->cPtr->readXR(pI2C_c->cPtr, 0x62); + XR62 &= (~pI2C_c->i2cDataBit) & (~pI2C_c->i2cClockBit); + pI2C_c->cPtr->writeFR(pI2C_c->cPtr, 0x0C, FR0C); + pI2C_c->cPtr->writeXR(pI2C_c->cPtr, 0x62, XR62); + val = pI2C_c->cPtr->readXR(pI2C_c->cPtr, 0x63); + *clock = (val & pI2C_c->i2cClockBit) != 0; + *data = (val & pI2C_c->i2cDataBit) != 0; +} + +static void +chips_I2CPutBits(I2CBusPtr b, int clock, int data) +{ + CHIPSI2CPtr pI2C_c = (CHIPSI2CPtr) (b->DriverPrivate.ptr); + unsigned char FR0C, XR62, val; + + FR0C = pI2C_c->cPtr->readFR(pI2C_c->cPtr, 0x0C); + if (((pI2C_c->i2cDataBit & 0x01) && data) + || ((pI2C_c->i2cClockBit & 0x01) && clock)) + FR0C |= 0x18; + else if ((pI2C_c->i2cDataBit & 0x01) + || (pI2C_c->i2cClockBit & 0x01)) + FR0C |= 0x10; + if (((pI2C_c->i2cDataBit & 0x02) && data) + || ((pI2C_c->i2cClockBit & 0x02) && clock)) + FR0C |= 0xC0; + else if ((pI2C_c->i2cDataBit & 0x02) + || (pI2C_c->i2cClockBit & 0x02)) + FR0C |= 0x80; + XR62 = pI2C_c->cPtr->readXR(pI2C_c->cPtr, 0x62); + XR62 = (XR62 & ~pI2C_c->i2cClockBit) | (clock ? pI2C_c->i2cClockBit : 0); + XR62 = (XR62 & ~pI2C_c->i2cDataBit) | (data ? pI2C_c->i2cDataBit : 0); + pI2C_c->cPtr->writeFR(pI2C_c->cPtr, 0x0C, FR0C); + pI2C_c->cPtr->writeXR(pI2C_c->cPtr, 0x62, XR62); + val = pI2C_c->cPtr->readXR(pI2C_c->cPtr, 0x63); + val = (val & ~pI2C_c->i2cClockBit) | (clock ? pI2C_c->i2cClockBit : 0); + val = (val & ~pI2C_c->i2cDataBit) | (data ? pI2C_c->i2cDataBit : 0); + pI2C_c->cPtr->writeXR(pI2C_c->cPtr, 0x63, val); +} + + +Bool +chips_i2cInit(ScrnInfoPtr pScrn) +{ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + I2CBusPtr I2CPtr; + + I2CPtr = xf86CreateI2CBusRec(); + if(!I2CPtr) return FALSE; + + cPtr->I2C = I2CPtr; + + I2CPtr->BusName = "DDC"; + I2CPtr->scrnIndex = pScrn->scrnIndex; + I2CPtr->I2CPutBits = chips_I2CPutBits; + I2CPtr->I2CGetBits = chips_I2CGetBits; + I2CPtr->DriverPrivate.ptr = xalloc(sizeof(CHIPSI2CRec)); + ((CHIPSI2CPtr)(I2CPtr->DriverPrivate.ptr))->cPtr = cPtr; + + if (!xf86I2CBusInit(I2CPtr)) + return FALSE; + + if (!chips_setI2CBits(I2CPtr, pScrn)) + return FALSE; + + return TRUE; +} + +static Bool +chips_setI2CBits(I2CBusPtr b, ScrnInfoPtr pScrn) +{ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSI2CPtr pI2C_c = (CHIPSI2CPtr) (b->DriverPrivate.ptr); + unsigned char FR0B, FR0C; + unsigned char bits, data_bits, clock_bits; + int i,j; + + FR0C = cPtr->readFR(cPtr, 0x0C); + switch (cPtr->Chipset) { + case CHIPS_CT65550: + bits = 0x1F; /* GPIO 0-4 */ + FR0B = cPtr->readFR(cPtr, 0x0B); + if (!(FR0B & 0x10)) /* GPIO 2 is used as 32 kHz input */ + bits &= 0xFB; + pI2C_c->i2cDataBit = 0x01; + pI2C_c->i2cClockBit = 0x02; + if (cPtr->Bus == ChipsVLB) /* GPIO 3-7 are used as address bits */ + bits &= 0x07; + break; + case CHIPS_CT65554: + case CHIPS_CT65555: + case CHIPS_CT68554: + bits = 0x0F; /* GPIO 0-3 */ + pI2C_c->i2cDataBit = 0x04; + pI2C_c->i2cClockBit = 0x08; + break; + case CHIPS_CT69000: + case CHIPS_CT69030: + bits = 0x9F; /* GPIO 0-4,7? */ + pI2C_c->i2cDataBit = 0x04; + pI2C_c->i2cClockBit = 0x08; + break; + default: + bits = 0x0C; /* GPIO 2,3 */ + pI2C_c->i2cDataBit = 0x04; + pI2C_c->i2cClockBit = 0x08; + break; + } + if (!(FR0C & 0x80)) { /* GPIO 1 is not available */ + bits &= 0xFE; + } + if (!(FR0C & 0x10)) { /* GPIO 0 is not available */ + bits &= 0xFD; + } + pI2C_c->i2cClockBit &= bits; + pI2C_c->i2cDataBit &= bits; + /* + * first we test out the "favorite" GPIO bits ie. the ones suggested + * by the data book; if we don't succeed test all other combinations + * of possible GPIO pins as data/clock lines as the manufacturer might + * have its own ideas. + */ + if (chips_TestI2C(pScrn->scrnIndex)) return TRUE; + + data_bits = bits; + pI2C_c->i2cDataBit = 0x01; + for (i = 0; i<8; i++) { + if (data_bits & 0x01) { + clock_bits = bits; + pI2C_c->i2cClockBit = 0x01; + for (j = 0; j<8; j++) { + if (clock_bits & 0x01) + if (chips_TestI2C(pScrn->scrnIndex)) return TRUE; + clock_bits >>= 1; + pI2C_c->i2cClockBit <<= 1; + } + } + data_bits >>= 1; + pI2C_c->i2cDataBit <<= 1; + } + /* + * We haven't found a valid clock/data line combination - that + * doesn't mean there aren't any. We just haven't received an + * answer from the relevant DDC I2C addresses. We'll have to wait + * and see, if this is too restrictive (eg one wants to use I2C + * for something else than DDC we might have to probe more addresses + * or just fall back to the "favorite" GPIO lines. + */ + return FALSE; +} + +static Bool +chips_TestI2C(int scrnIndex) +{ + int i; + I2CBusPtr b; + + b = xf86I2CFindBus(scrnIndex, "DDC"); + if (b == NULL) return FALSE; + else { + for(i = 0xA0; i < 0xA8; i += 2) + if(xf86I2CProbeAddress(b, i)) + return TRUE; + } + return FALSE; +} + + diff --git a/src/ct_dga.c b/src/ct_dga.c new file mode 100644 index 0000000..3d0fe26 --- /dev/null +++ b/src/ct_dga.c @@ -0,0 +1,316 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/chips/ct_dga.c,v 1.5 2002/11/25 14:04:58 eich Exp $ */ + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86_ansic.h" +#include "xf86Pci.h" +#include "xf86PciInfo.h" +#include "xaa.h" +#include "xaalocal.h" +#include "ct_driver.h" +#include "dgaproc.h" + + +static Bool CHIPS_OpenFramebuffer(ScrnInfoPtr, char **, unsigned char **, + int *, int *, int *); +static Bool CHIPS_SetMode(ScrnInfoPtr, DGAModePtr); +static int CHIPS_GetViewport(ScrnInfoPtr); +static void CHIPS_SetViewport(ScrnInfoPtr, int, int, int); +static void CHIPS_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long); +static void CHIPS_BlitRect(ScrnInfoPtr, int, int, int, int, int, int); +#if 0 +static void CHIPS_BlitTransRect(ScrnInfoPtr, int, int, int, int, int, int, + unsigned long); +#endif + +static +DGAFunctionRec CHIPS_DGAFuncs = { + CHIPS_OpenFramebuffer, + NULL, + CHIPS_SetMode, + CHIPS_SetViewport, + CHIPS_GetViewport, + CHIPSSync, + CHIPS_FillRect, + CHIPS_BlitRect, +#if 0 + CHIPS_BlitTransRect +#else + NULL +#endif +}; + +static +DGAFunctionRec CHIPS_MMIODGAFuncs = { + CHIPS_OpenFramebuffer, + NULL, + CHIPS_SetMode, + CHIPS_SetViewport, + CHIPS_GetViewport, + CHIPSMMIOSync, + CHIPS_FillRect, + CHIPS_BlitRect, +#if 0 + CHIPS_BlitTransRect +#else + NULL +#endif +}; + +static +DGAFunctionRec CHIPS_HiQVDGAFuncs = { + CHIPS_OpenFramebuffer, + NULL, + CHIPS_SetMode, + CHIPS_SetViewport, + CHIPS_GetViewport, + CHIPSHiQVSync, + CHIPS_FillRect, + CHIPS_BlitRect, +#if 0 + CHIPS_BlitTransRect +#else + NULL +#endif +}; + + +Bool +CHIPSDGAInit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + CHIPSPtr cPtr = CHIPSPTR(pScrn); + DGAModePtr modes = NULL, newmodes = NULL, currentMode; + DisplayModePtr pMode, firstMode; + int Bpp = pScrn->bitsPerPixel >> 3; + int num = 0; + Bool oneMore; + int imlines = (pScrn->videoRam * 1024) / + (pScrn->displayWidth * (pScrn->bitsPerPixel >> 3)); + + pMode = firstMode = pScrn->modes; + + while(pMode) { + + if(0 /*pScrn->displayWidth != pMode->HDisplay*/) { + newmodes = xrealloc(modes, (num + 2) * sizeof(DGAModeRec)); + oneMore = TRUE; + } else { + newmodes = xrealloc(modes, (num + 1) * sizeof(DGAModeRec)); + oneMore = FALSE; + } + + if(!newmodes) { + xfree(modes); + return FALSE; + } + modes = newmodes; + +SECOND_PASS: + + currentMode = modes + num; + num++; + + currentMode->mode = pMode; + currentMode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE; + if(cPtr->Flags & ChipsAccelSupport) + currentMode->flags |= (cPtr->Flags & ChipsAccelSupport) + ? (DGA_FILL_RECT | DGA_BLIT_RECT) : 0; + if(pMode->Flags & V_DBLSCAN) + currentMode->flags |= DGA_DOUBLESCAN; + if(pMode->Flags & V_INTERLACE) + currentMode->flags |= DGA_INTERLACED; + currentMode->byteOrder = pScrn->imageByteOrder; + currentMode->depth = pScrn->depth; + currentMode->bitsPerPixel = pScrn->bitsPerPixel; + currentMode->red_mask = pScrn->mask.red; + currentMode->green_mask = pScrn->mask.green; + currentMode->blue_mask = pScrn->mask.blue; + currentMode->visualClass = (Bpp == 1) ? PseudoColor : TrueColor; + currentMode->viewportWidth = pMode->HDisplay; + currentMode->viewportHeight = pMode->VDisplay; + currentMode->xViewportStep = 1; + currentMode->yViewportStep = 1; + currentMode->viewportFlags = DGA_FLIP_RETRACE | DGA_FLIP_IMMEDIATE; + currentMode->offset = 0; + currentMode->address = cPtr->FbBase; + + if(oneMore) { /* first one is narrow width */ + currentMode->bytesPerScanline = ((pMode->HDisplay * Bpp) + 3) & ~3L; + currentMode->imageWidth = pMode->HDisplay; + currentMode->imageHeight = imlines; + currentMode->pixmapWidth = currentMode->imageWidth; + currentMode->pixmapHeight = currentMode->imageHeight; + currentMode->maxViewportX = currentMode->imageWidth - + currentMode->viewportWidth; + /* this might need to get clamped to some maximum */ + currentMode->maxViewportY = currentMode->imageHeight - + currentMode->viewportHeight; + oneMore = FALSE; + goto SECOND_PASS; + } else { + currentMode->bytesPerScanline = + ((pScrn->displayWidth * Bpp) + 3) & ~3L; + currentMode->imageWidth = pScrn->displayWidth; + currentMode->imageHeight = imlines; + currentMode->pixmapWidth = currentMode->imageWidth; + currentMode->pixmapHeight = currentMode->imageHeight; + currentMode->maxViewportX = currentMode->imageWidth - + currentMode->viewportWidth; + /* this might need to get clamped to some maximum */ + currentMode->maxViewportY = currentMode->imageHeight - + currentMode->viewportHeight; + } + + pMode = pMode->next; + if(pMode == firstMode) + break; + } + + cPtr->numDGAModes = num; + cPtr->DGAModes = modes; + + if (IS_HiQV(cPtr)) { + return DGAInit(pScreen, &CHIPS_HiQVDGAFuncs, modes, num); + } else { + if(!cPtr->UseMMIO) { + return DGAInit(pScreen, &CHIPS_DGAFuncs, modes, num); + } else { + return DGAInit(pScreen, &CHIPS_MMIODGAFuncs, modes, num); + } + } +} + + +static Bool +CHIPS_SetMode( + ScrnInfoPtr pScrn, + DGAModePtr pMode +){ + static int OldDisplayWidth[MAXSCREENS]; + int index = pScrn->pScreen->myNum; + + CHIPSPtr cPtr = CHIPSPTR(pScrn); + + if (!pMode) { /* restore the original mode */ + /* put the ScreenParameters back */ + if (cPtr->DGAactive) { + pScrn->displayWidth = OldDisplayWidth[index]; + pScrn->EnterVT(pScrn->scrnIndex,0); + + cPtr->DGAactive = FALSE; + } + } else { + if(!cPtr->DGAactive) { /* save the old parameters */ + OldDisplayWidth[index] = pScrn->displayWidth; + pScrn->LeaveVT(pScrn->scrnIndex,0); + cPtr->DGAactive = TRUE; + } + + pScrn->displayWidth = pMode->bytesPerScanline / + (pMode->bitsPerPixel >> 3); + + CHIPSSwitchMode(index, pMode->mode, 0); + } + + return TRUE; +} + + + +static int +CHIPS_GetViewport( + ScrnInfoPtr pScrn +){ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + + return cPtr->DGAViewportStatus; +} + +static void +CHIPS_SetViewport( + ScrnInfoPtr pScrn, + int x, int y, + int flags + ){ + vgaHWPtr hwp = VGAHWPTR(pScrn); + CHIPSPtr cPtr = CHIPSPTR(pScrn); + + if (flags & DGA_FLIP_RETRACE) { + while ((hwp->readST01(hwp)) & 0x08){}; + while (!(hwp->readST01(hwp)) & 0x08){}; + } + + CHIPSAdjustFrame(pScrn->pScreen->myNum, x, y, flags); + cPtr->DGAViewportStatus = 0; /* CHIPSAdjustFrame loops until finished */ +} + +static void +CHIPS_FillRect ( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned long color +){ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + + if(cPtr->AccelInfoRec) { + (*cPtr->AccelInfoRec->SetupForSolidFill)(pScrn, color, GXcopy, ~0); + (*cPtr->AccelInfoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h); + SET_SYNC_FLAG(cPtr->AccelInfoRec); + } +} + +static void +CHIPS_BlitRect( + ScrnInfoPtr pScrn, + int srcx, int srcy, + int w, int h, + int dstx, int dsty +){ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + + if(cPtr->AccelInfoRec) { + int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1; + int ydir = (srcy < dsty) ? -1 : 1; + + (*cPtr->AccelInfoRec->SetupForScreenToScreenCopy)( + pScrn, xdir, ydir, GXcopy, ~0, -1); + (*cPtr->AccelInfoRec->SubsequentScreenToScreenCopy)( + pScrn, srcx, srcy, dstx, dsty, w, h); + SET_SYNC_FLAG(cPtr->AccelInfoRec); + } +} + +#if 0 +static void +CHIPS_BlitTransRect( + ScrnInfoPtr pScrn, + int srcx, int srcy, + int w, int h, + int dstx, int dsty, + unsigned long color +){ + /* this one should be separate since the XAA function would + prohibit usage of ~0 as the key */ +} +#endif + +static Bool +CHIPS_OpenFramebuffer( + ScrnInfoPtr pScrn, + char **name, + unsigned char **mem, + int *size, + int *offset, + int *flags +){ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + + *name = NULL; /* no special device */ + *mem = (unsigned char*)cPtr->FbAddress; + *size = cPtr->FbMapSize; + *offset = 0; + *flags = DGA_NEED_ROOT; + + return TRUE; +} diff --git a/src/ct_driver.c b/src/ct_driver.c new file mode 100644 index 0000000..2aa6cc2 --- /dev/null +++ b/src/ct_driver.c @@ -0,0 +1,7487 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/chips/ct_driver.c,v 1.122 2002/11/25 14:04:58 eich Exp $ */ + +/* + * Copyright 1993 by Jon Block <block@frc.com> + * Modified by Mike Hollick <hollick@graphics.cis.upenn.edu> + * Modified 1994 by Régis Cridlig <cridlig@dmi.ens.fr> + * + * Major Contributors to XFree86 3.2 + * Modified 1995/6 by Nozomi Ytow + * Modified 1996 by Egbert Eich <eich@xfree86.org> + * Modified 1996 by David Bateman <dbateman@club-internet.fr> + * Modified 1996 by Xavier Ducoin <xavier@rd.lectra.fr> + * + * Contributors to XFree86 3.2 + * Modified 1995/6 by Ken Raeburn <raeburn@raeburn.org> + * Modified 1996 by Shigehiro Nomura <nomura@sm.sony.co.jp> + * Modified 1996 by Marc de Courville <marc@courville.org> + * Modified 1996 by Adam Sulmicki <adam@cfar.umd.edu> + * Modified 1996 by Jens Maurer <jmaurer@cck.uni-kl.de> + * + * Large parts rewritten for XFree86 4.0 + * Modified 1998 by David Bateman <dbateman@club-internet.fr> + * Modified 1998 by Egbert Eich <eich@xfree86.org> + * Modified 1998 by Nozomi Ytow + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the authors not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. The authors makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +/* + * Copyright 1997 + * Digital Equipment Corporation. All rights reserved. + * This software is furnished under license and may be used and copied only in + * accordance with the following terms and conditions. Subject to these + * conditions, you may download, copy, install, use, modify and distribute + * this software in source and/or binary form. No title or ownership is + * transferred hereby. + * 1) Any source code used, modified or distributed must reproduce and retain + * this copyright notice and list of conditions as they appear in the + * source file. + * + * 2) No right is granted to use any trade name, trademark, or logo of Digital + * Equipment Corporation. Neither the "Digital Equipment Corporation" name + * nor any trademark or logo of Digital Equipment Corporation may be used + * to endorse or promote products derived from this software without the + * prior written permission of Digital Equipment Corporation. + * + * 3) This software is provided "AS-IS" and any express or implied warranties, + * including but not limited to, any implied warranties of merchantability, + * fitness for a particular purpose, or non-infringement are disclaimed. In + * no event shall DIGITAL be liable for any damages whatsoever, and in + * particular, DIGITAL shall not be liable for special, indirect, + * consequential, or incidental damages or damages for lost profits, loss + * of revenue or loss of use, whether such damages arise in contract, + * negligence, tort, under statute, in equity, at law or otherwise, even if + * advised of the possibility of such damage. + */ + +/* All drivers should typically include these */ +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86_ansic.h" + +/* Everything using inb/outb, etc needs "compiler.h" */ +#include "compiler.h" + +/* Drivers for PCI hardware need this */ +#include "xf86PciInfo.h" + +/* Drivers that need to access the PCI config space directly need this */ +#include "xf86Pci.h" + +/* This is used for module versioning */ +#include "xf86Version.h" + +/* Standard resources are defined here */ +#include "xf86Resources.h" + +/* All drivers using the vgahw module need this */ +#include "vgaHW.h" + +/* All drivers initialising the SW cursor need this */ +#include "mipointer.h" + +/* All drivers implementing backing store need this */ +#include "mibstore.h" + +/* All drivers using the mi banking wrapper need this */ +#include "mibank.h" + +/* All drivers using the mi colormap manipulation need this */ +#include "micmap.h" + +#include "fb.h" +#include "cfb8_16.h" + + +/* Needed for the 1 and 4 bpp framebuffers */ +#include "xf1bpp.h" +#include "xf4bpp.h" + +/* Needed by Resources Access Control (RAC) */ +#include "xf86RAC.h" + +/* int10 */ +#include "xf86int10.h" +#include "vbe.h" + +/* Needed by the Shadow Framebuffer */ +#include "shadowfb.h" + +/* Needed for replacement LoadPalette function for Gamma Correction */ +#include "xf86cmap.h" + +#include "dixstruct.h" + +/* Driver specific headers */ +#include "ct_driver.h" + +/* Mandatory functions */ +static const OptionInfoRec * CHIPSAvailableOptions(int chipid, int busid); +static void CHIPSIdentify(int flags); +static Bool CHIPSProbe(DriverPtr drv, int flags); +static Bool CHIPSPreInit(ScrnInfoPtr pScrn, int flags); +static Bool CHIPSScreenInit(int Index, ScreenPtr pScreen, int argc, + char **argv); +static Bool CHIPSEnterVT(int scrnIndex, int flags); +static void CHIPSLeaveVT(int scrnIndex, int flags); +static Bool CHIPSCloseScreen(int scrnIndex, ScreenPtr pScreen); +static void CHIPSFreeScreen(int scrnIndex, int flags); +static int CHIPSValidMode(int scrnIndex, DisplayModePtr mode, + Bool verbose, int flags); +static Bool CHIPSSaveScreen(ScreenPtr pScreen, int mode); + +/* Internally used functions */ +static int chipsFindIsaDevice(GDevPtr dev); +static Bool chipsClockSelect(ScrnInfoPtr pScrn, int no); +Bool chipsModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode); +static void chipsSave(ScrnInfoPtr pScrn, vgaRegPtr VgaSave, + CHIPSRegPtr ChipsSave); +static void chipsRestore(ScrnInfoPtr pScrn, vgaRegPtr VgaReg, + CHIPSRegPtr ChipsReg, Bool restoreFonts); +static void chipsLock(ScrnInfoPtr pScrn); +static void chipsUnlock(ScrnInfoPtr pScrn); +static void chipsClockSave(ScrnInfoPtr pScrn, CHIPSClockPtr Clock); +static void chipsClockLoad(ScrnInfoPtr pScrn, CHIPSClockPtr Clock); +static Bool chipsClockFind(ScrnInfoPtr pScrn, int no, CHIPSClockPtr Clock); +static void chipsCalcClock(ScrnInfoPtr pScrn, int Clock, + unsigned char *vclk); +static int chipsGetHWClock(ScrnInfoPtr pScrn); +static Bool chipsPreInit655xx(ScrnInfoPtr pScrn, int flags); +static Bool chipsPreInitHiQV(ScrnInfoPtr pScrn, int flags); +static Bool chipsPreInitWingine(ScrnInfoPtr pScrn, int flags); +static int chipsSetMonitor(ScrnInfoPtr pScrn); +static Bool chipsMapMem(ScrnInfoPtr pScrn); +static Bool chipsUnmapMem(ScrnInfoPtr pScrn); +static void chipsProtect(ScrnInfoPtr pScrn, Bool on); +static void chipsBlankScreen(ScrnInfoPtr pScrn, Bool unblank); +static void chipsRestoreExtendedRegs(ScrnInfoPtr pScrn, CHIPSRegPtr Regs); +static void chipsRestoreStretching(ScrnInfoPtr pScrn, + unsigned char ctHorizontalStretch, + unsigned char ctVerticalStretch); +static Bool chipsModeInitHiQV(ScrnInfoPtr pScrn, DisplayModePtr mode); +static Bool chipsModeInitWingine(ScrnInfoPtr pScrn, DisplayModePtr mode); +static Bool chipsModeInit655xx(ScrnInfoPtr pScrn, DisplayModePtr mode); +static int chipsVideoMode(int vgaBitsPerPixel,int displayHSize, + int displayVSize); +static void chipsDisplayPowerManagementSet(ScrnInfoPtr pScrn, + int PowerManagementMode, int flags); +static void chipsHWCursorOn(CHIPSPtr cPtr, ScrnInfoPtr pScrn); +static void chipsHWCursorOff(CHIPSPtr cPtr, ScrnInfoPtr pScrn); +static void chipsFixResume(ScrnInfoPtr pScrn); +static void chipsLoadPalette(ScrnInfoPtr pScrn, int numColors, + int *indices, LOCO *colors, VisualPtr pVisual); +static void chipsLoadPalette16(ScrnInfoPtr pScrn, int numColors, + int *indices, LOCO *colors, VisualPtr pVisual); +static void chipsSetPanelType(CHIPSPtr cPtr); +static void chipsBlockHandler(int, pointer, pointer, pointer); + +/* + * This is intentionally screen-independent. It indicates the binding + * choice made in the first PreInit. + */ +static int pix24bpp = 0; + +/* + * Index of Entity + */ +static int CHIPSEntityIndex = -1; + + +/* Set the non-documented SAR04 register for overlay/video */ +#define SAR04 + +/* + * Initialise some arrays that are used in multiple instances of the + * acceleration code. Set them up here as its a convenient place to do it. + */ +/* alu to C&T conversion for use with source data */ +int ChipsAluConv[] = +{ + 0x00, /* dest = 0; GXclear, 0 */ + 0x88, /* dest &= src; GXand, 0x1 */ + 0x44, /* dest = src & ~dest; GXandReverse, 0x2 */ + 0xCC, /* dest = src; GXcopy, 0x3 */ + 0x22, /* dest &= ~src; GXandInverted, 0x4 */ + 0xAA, /* dest = dest; GXnoop, 0x5 */ + 0x66, /* dest = ^src; GXxor, 0x6 */ + 0xEE, /* dest |= src; GXor, 0x7 */ + 0x11, /* dest = ~src & ~dest;GXnor, 0x8 */ + 0x99, /* dest ^= ~src ;GXequiv, 0x9 */ + 0x55, /* dest = ~dest; GXInvert, 0xA */ + 0xDD, /* dest = src|~dest ;GXorReverse, 0xB */ + 0x33, /* dest = ~src; GXcopyInverted, 0xC */ + 0xBB, /* dest |= ~src; GXorInverted, 0xD */ + 0x77, /* dest = ~src|~dest ;GXnand, 0xE */ + 0xFF, /* dest = 0xFF; GXset, 0xF */ +}; + +/* alu to C&T conversion for use with pattern data */ +int ChipsAluConv2[] = +{ + 0x00, /* dest = 0; GXclear, 0 */ + 0xA0, /* dest &= src; GXand, 0x1 */ + 0x50, /* dest = src & ~dest; GXandReverse, 0x2 */ + 0xF0, /* dest = src; GXcopy, 0x3 */ + 0x0A, /* dest &= ~src; GXandInverted, 0x4 */ + 0xAA, /* dest = dest; GXnoop, 0x5 */ + 0x5A, /* dest = ^src; GXxor, 0x6 */ + 0xFA, /* dest |= src; GXor, 0x7 */ + 0x05, /* dest = ~src & ~dest;GXnor, 0x8 */ + 0xA5, /* dest ^= ~src ;GXequiv, 0x9 */ + 0x55, /* dest = ~dest; GXInvert, 0xA */ + 0xF5, /* dest = src|~dest ;GXorReverse, 0xB */ + 0x0F, /* dest = ~src; GXcopyInverted, 0xC */ + 0xAF, /* dest |= ~src; GXorInverted, 0xD */ + 0x5F, /* dest = ~src|~dest ;GXnand, 0xE */ + 0xFF, /* dest = 0xFF; GXset, 0xF */ +}; + +/* alu to C&T conversion for use with pattern data as a planemask */ +int ChipsAluConv3[] = +{ + 0x0A, /* dest = 0; GXclear, 0 */ + 0x8A, /* dest &= src; GXand, 0x1 */ + 0x4A, /* dest = src & ~dest; GXandReverse, 0x2 */ + 0xCA, /* dest = src; GXcopy, 0x3 */ + 0x2A, /* dest &= ~src; GXandInverted, 0x4 */ + 0xAA, /* dest = dest; GXnoop, 0x5 */ + 0x6A, /* dest = ^src; GXxor, 0x6 */ + 0xEA, /* dest |= src; GXor, 0x7 */ + 0x1A, /* dest = ~src & ~dest;GXnor, 0x8 */ + 0x9A, /* dest ^= ~src ;GXequiv, 0x9 */ + 0x5A, /* dest = ~dest; GXInvert, 0xA */ + 0xDA, /* dest = src|~dest ;GXorReverse, 0xB */ + 0x3A, /* dest = ~src; GXcopyInverted, 0xC */ + 0xBA, /* dest |= ~src; GXorInverted, 0xD */ + 0x7A, /* dest = ~src|~dest ;GXnand, 0xE */ + 0xFA, /* dest = 0xFF; GXset, 0xF */ +}; + +/* The addresses of the acceleration registers */ +unsigned int ChipsReg32HiQV[] = +{ + 0x00, /* BR00 Source and Destination offset register */ + 0x04, /* BR01 Color expansion background color */ + 0x08, /* BR02 Color expansion foreground color */ + 0x0C, /* BR03 Monochrome source control register */ + 0x10, /* BR04 BitBLT control register */ + 0x14, /* BR05 Pattern address register */ + 0x18, /* BR06 Source address register */ + 0x1C, /* BR07 Destination address register */ + 0x20 /* BR08 Destination width and height register */ +}; + +unsigned int ChipsReg32[] = +{ + /*BitBLT */ + 0x83D0, /*DR0 src/dest offset */ + 0x87D0, /*DR1 BitBlt. address of freeVram? */ + 0x8BD0, /*DR2 BitBlt. paintBrush, or tile pat.*/ + 0x8FD0, /*DR3 */ + 0x93D0, /*DR4 BitBlt. */ + 0x97D0, /*DR5 BitBlt. srcAddr, or 0 in VRAM */ + 0x9BD0, /*DR6 BitBlt. dest? */ + 0x9FD0, /*DR7 BitBlt. width << 16 | height */ + /*H/W cursor */ + 0xA3D0, /*DR8 write/erase cursor */ + /*bit 0-1 if 0 cursor is not shown + * if 1 32x32 cursor + * if 2 64x64 cursor + * if 3 128x128 cursor + */ + /* bit 7 if 1 cursor is not shown */ + /* bit 9 cursor expansion in X */ + /* bit 10 cursor expansion in Y */ + 0xA7D0, /* DR9 foreGroundCursorColor */ + 0xABD0, /* DR0xA backGroundCursorColor */ + 0xAFD0, /* DR0xB cursorPosition */ + /* bit 0-7 x coordinate */ + /* bit 8-14 0 */ + /* bit 15 x signum */ + /* bit 16-23 y coordinate */ + /* bit 24-30 0 */ + /* bit 31 y signum */ + 0xB3D0, /* DR0xC address of cursor pattern */ +}; + +#if defined(__arm32__) && defined(__NetBSD__) +/* + * Built in TV output modes: These modes have been tested on NetBSD with + * CT65550 and StrongARM. They give what seems to be the best output for + * a roughly 640x480 display. To enable one of the built in modes, add + * the identifier "NTSC" or "PAL" to the list of modes in the appropriate + * "Display" subsection of the "Screen" section in the XF86Config file. + * Note that the call to xf86SetTVOut(), which tells the kernel to enable + * TV output results in hardware specific actions. There must be code to + * support this in the kernel or TV output won't work. + */ +static DisplayModeRec ChipsPALMode = { + NULL, NULL, /* prev, next */ + "PAL", /* identifier of this mode */ + MODE_OK, /* mode status */ + M_T_BUILTIN, /* mode type */ + 15000, /* Clock frequency */ + 776, /* HDisplay */ + 800, /* HSyncStart */ + 872, /* HSyncEnd */ + 960, /* HTotal */ + 0, /* HSkew */ + 585, /* VDisplay */ + 590, /* VSyncStart */ + 595, /* VSyncEnd */ + 625, /* VTotal */ + 0, /* VScan */ + V_INTERLACE, /* Flags */ + -1, /* ClockIndex */ + 15000, /* SynthClock */ + 776, /* CRTC HDisplay */ + 800, /* CRTC HBlankStart */ + 800, /* CRTC HSyncStart */ + 872, /* CRTC HSyncEnd */ + 872, /* CRTC HBlankEnd */ + 960, /* CRTC HTotal */ + 0, /* CRTC HSkew */ + 585, /* CRTC VDisplay */ + 590, /* CRTC VBlankStart */ + 590, /* CRTC VSyncStart */ + 595, /* CRTC VSyncEnd */ + 595, /* CRTC VBlankEnd */ + 625, /* CRTC VTotal */ + FALSE, /* CrtcHAdjusted */ + FALSE, /* CrtcVAdjusted */ + 0, /* PrivSize */ + NULL, /* Private */ + 0.0, /* HSync */ + 0.0 /* VRefresh */ +}; + +/* +** So far, it looks like SECAM uses the same values as PAL +*/ +static DisplayModeRec ChipsSECAMMode = { + NULL, /* prev */ + &ChipsPALMode, /* next */ + "SECAM", /* identifier of this mode */ + MODE_OK, /* mode status */ + M_T_BUILTIN, /* mode type */ + 15000, /* Clock frequency */ + 776, /* HDisplay */ + 800, /* HSyncStart */ + 872, /* HSyncEnd */ + 960, /* HTotal */ + 0, /* HSkew */ + 585, /* VDisplay */ + 590, /* VSyncStart */ + 595, /* VSyncEnd */ + 625, /* VTotal */ + 0, /* VScan */ + V_INTERLACE, /* Flags */ + -1, /* ClockIndex */ + 15000, /* SynthClock */ + 776, /* CRTC HDisplay */ + 800, /* CRTC HBlankStart */ + 800, /* CRTC HSyncStart */ + 872, /* CRTC HSyncEnd */ + 872, /* CRTC HBlankEnd */ + 960, /* CRTC HTotal */ + 0, /* CRTC HSkew */ + 585, /* CRTC VDisplay */ + 590, /* CRTC VBlankStart */ + 590, /* CRTC VSyncStart */ + 595, /* CRTC VSyncEnd */ + 595, /* CRTC VBlankEnd */ + 625, /* CRTC VTotal */ + FALSE, /* CrtcHAdjusted */ + FALSE, /* CrtcVAdjusted */ + 0, /* PrivSize */ + NULL, /* Private */ + 0.0, /* HSync */ + 0.0 /* VRefresh */ +}; + + +static DisplayModeRec ChipsNTSCMode = { + NULL, /* prev */ + &ChipsSECAMMode,/* next */ + "NTSC", /* identifier of this mode */ + MODE_OK, /* mode status */ + M_T_BUILTIN, /* mode type */ + 11970, /* Clock frequency */ + 584, /* HDisplay */ + 640, /* HSyncStart */ + 696, /* HSyncEnd */ + 760, /* HTotal */ + 0, /* HSkew */ + 450, /* VDisplay */ + 479, /* VSyncStart */ + 485, /* VSyncEnd */ + 525, /* VTotal */ + 0, /* VScan */ + V_INTERLACE | V_NVSYNC | V_NHSYNC , /* Flags */ + -1, /* ClockIndex */ + 11970, /* SynthClock */ + 584, /* CRTC HDisplay */ + 640, /* CRTC HBlankStart */ + 640, /* CRTC HSyncStart */ + 696, /* CRTC HSyncEnd */ + 696, /* CRTC HBlankEnd */ + 760, /* CRTC HTotal */ + 0, /* CRTC HSkew */ + 450, /* CRTC VDisplay */ + 479, /* CRTC VBlankStart */ + 479, /* CRTC VSyncStart */ + 485, /* CRTC VSyncEnd */ + 485, /* CRTC VBlankEnd */ + 525, /* CRTC VTotal */ + FALSE, /* CrtcHAdjusted */ + FALSE, /* CrtcVAdjusted */ + 0, /* PrivSize */ + NULL, /* Private */ + 0.0, /* HSync */ + 0.0 /* VRefresh */ +}; +#endif + +#define VERSION 4000 +#define CHIPS_NAME "CHIPS" +#define CHIPS_DRIVER_NAME "chips" +#define CHIPS_MAJOR_VERSION 1 +#define CHIPS_MINOR_VERSION 0 +#define CHIPS_PATCHLEVEL 0 + +/* + * This contains the functions needed by the server after loading the driver + * module. It must be supplied, and gets passed back by the SetupProc + * function in the dynamic case. In the static case, a reference to this + * is compiled in, and this requires that the name of this DriverRec be + * an upper-case version of the driver name. + */ + +DriverRec CHIPS = { + VERSION, + CHIPS_DRIVER_NAME, + CHIPSIdentify, + CHIPSProbe, + CHIPSAvailableOptions, + NULL, + 0 +}; + +static SymTabRec CHIPSChipsets[] = { + { CHIPS_CT65520, "ct65520" }, + { CHIPS_CT65525, "ct65525" }, + { CHIPS_CT65530, "ct65530" }, + { CHIPS_CT65535, "ct65535" }, + { CHIPS_CT65540, "ct65540" }, + { CHIPS_CT65545, "ct65545" }, + { CHIPS_CT65546, "ct65546" }, + { CHIPS_CT65548, "ct65548" }, + { CHIPS_CT65550, "ct65550" }, + { CHIPS_CT65554, "ct65554" }, + { CHIPS_CT65555, "ct65555" }, + { CHIPS_CT68554, "ct68554" }, + { CHIPS_CT69000, "ct69000" }, + { CHIPS_CT69030, "ct69030" }, + { CHIPS_CT64200, "ct64200" }, + { CHIPS_CT64300, "ct64300" }, + { -1, NULL } +}; + +/* Conversion PCI ID to chipset name */ +static PciChipsets CHIPSPCIchipsets[] = { + { CHIPS_CT65545, PCI_CHIP_65545, RES_SHARED_VGA }, + { CHIPS_CT65548, PCI_CHIP_65548, RES_SHARED_VGA }, + { CHIPS_CT65550, PCI_CHIP_65550, RES_SHARED_VGA }, + { CHIPS_CT65554, PCI_CHIP_65554, RES_SHARED_VGA }, + { CHIPS_CT65555, PCI_CHIP_65555, RES_SHARED_VGA }, + { CHIPS_CT68554, PCI_CHIP_68554, RES_SHARED_VGA }, + { CHIPS_CT69000, PCI_CHIP_69000, RES_SHARED_VGA }, + { CHIPS_CT69030, PCI_CHIP_69030, RES_SHARED_VGA }, + { -1, -1, RES_UNDEFINED} +}; + +static IsaChipsets CHIPSISAchipsets[] = { + { CHIPS_CT65520, RES_EXCLUSIVE_VGA }, + { CHIPS_CT65525, RES_EXCLUSIVE_VGA }, + { CHIPS_CT65530, RES_EXCLUSIVE_VGA }, + { CHIPS_CT65535, RES_EXCLUSIVE_VGA }, + { CHIPS_CT65540, RES_EXCLUSIVE_VGA }, + { CHIPS_CT65545, RES_EXCLUSIVE_VGA }, + { CHIPS_CT65546, RES_EXCLUSIVE_VGA }, + { CHIPS_CT65548, RES_EXCLUSIVE_VGA }, + { CHIPS_CT65550, RES_EXCLUSIVE_VGA }, + { CHIPS_CT65554, RES_EXCLUSIVE_VGA }, + { CHIPS_CT65555, RES_EXCLUSIVE_VGA }, + { CHIPS_CT68554, RES_EXCLUSIVE_VGA }, + { CHIPS_CT69000, RES_EXCLUSIVE_VGA }, + { CHIPS_CT69030, RES_EXCLUSIVE_VGA }, + { CHIPS_CT64200, RES_EXCLUSIVE_VGA }, + { CHIPS_CT64300, RES_EXCLUSIVE_VGA }, + { -1, RES_UNDEFINED } +}; + +/* The options supported by the Chips and Technologies Driver */ +typedef enum { + OPTION_LINEAR, + OPTION_NOACCEL, + OPTION_HW_CLKS, + OPTION_SW_CURSOR, + OPTION_HW_CURSOR, + OPTION_STN, + OPTION_USE_MODELINE, + OPTION_LCD_STRETCH, + OPTION_LCD_CENTER, + OPTION_MMIO, + OPTION_FULL_MMIO, + OPTION_SUSPEND_HACK, + OPTION_RGB_BITS, + OPTION_SYNC_ON_GREEN, + OPTION_PANEL_SIZE, + OPTION_18_BIT_BUS, + OPTION_SHOWCACHE, + OPTION_SHADOW_FB, + OPTION_OVERLAY, + OPTION_COLOR_KEY, + OPTION_VIDEO_KEY, + OPTION_FP_CLOCK_8, + OPTION_FP_CLOCK_16, + OPTION_FP_CLOCK_24, + OPTION_FP_CLOCK_32, + OPTION_SET_MCLK, + OPTION_ROTATE, + OPTION_NO_TMED, + OPTION_CRT2_MEM, + OPTION_DUAL_REFRESH, + OPTION_CRT_CLK_INDX, + OPTION_FP_CLK_INDX, + OPTION_FP_MODE +} CHIPSOpts; + +static const OptionInfoRec Chips655xxOptions[] = { + { OPTION_LINEAR, "Linear", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_HW_CLKS, "HWclocks", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_STN, "STN", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_USE_MODELINE, "UseModeline", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_LCD_STRETCH, "NoStretch", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_LCD_CENTER, "LcdCenter", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_MMIO, "MMIO", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_SUSPEND_HACK, "SuspendHack", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_PANEL_SIZE, "FixPanelSize", OPTV_BOOLEAN, {0}, FALSE }, +#if 0 + { OPTION_RGB_BITS, "RGBbits", OPTV_INTEGER, {0}, FALSE }, +#endif + { OPTION_18_BIT_BUS, "18BitBus", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_SHOWCACHE, "ShowCache", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE }, + { OPTION_SET_MCLK, "SetMclk", OPTV_FREQ, {0}, FALSE }, + { OPTION_FP_CLOCK_8, "FPClock8", OPTV_FREQ, {0}, FALSE }, + { OPTION_FP_CLOCK_16, "FPClock16", OPTV_FREQ, {0}, FALSE }, + { OPTION_FP_CLOCK_24, "FPClock24", OPTV_FREQ, {0}, FALSE }, + { OPTION_FP_MODE, "FPMode", OPTV_BOOLEAN, {0}, FALSE }, + { -1, NULL, OPTV_NONE, {0}, FALSE } +}; + +static const OptionInfoRec ChipsWingineOptions[] = { + { OPTION_LINEAR, "Linear", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_HW_CLKS, "HWclocks", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE }, +#if 0 + { OPTION_RGB_BITS, "RGBbits", OPTV_INTEGER, {0}, FALSE }, +#endif + { OPTION_SHOWCACHE, "ShowCache", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE }, + { -1, NULL, OPTV_NONE, {0}, FALSE } +}; + +static const OptionInfoRec ChipsHiQVOptions[] = { + { OPTION_LINEAR, "Linear", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_STN, "STN", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_USE_MODELINE, "UseModeline", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_LCD_STRETCH, "NoStretch", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_LCD_CENTER, "LcdCenter", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_MMIO, "MMIO", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_FULL_MMIO, "FullMMIO", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_SUSPEND_HACK, "SuspendHack", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_PANEL_SIZE, "FixPanelSize", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_RGB_BITS, "RGBbits", OPTV_INTEGER, {0}, FALSE }, + { OPTION_SYNC_ON_GREEN, "SyncOnGreen", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_SHOWCACHE, "ShowCache", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE }, + { OPTION_OVERLAY, "Overlay", OPTV_ANYSTR, {0}, FALSE }, + { OPTION_COLOR_KEY, "ColorKey", OPTV_INTEGER, {0}, FALSE }, + { OPTION_VIDEO_KEY, "VideoKey", OPTV_INTEGER, {0}, FALSE }, + { OPTION_FP_CLOCK_8, "FPClock8", OPTV_FREQ, {0}, FALSE }, + { OPTION_FP_CLOCK_16, "FPClock16", OPTV_FREQ, {0}, FALSE }, + { OPTION_FP_CLOCK_24, "FPClock24", OPTV_FREQ, {0}, FALSE }, + { OPTION_FP_CLOCK_32, "FPClock32", OPTV_FREQ, {0}, FALSE }, + { OPTION_SET_MCLK, "SetMclk", OPTV_FREQ, {0}, FALSE }, + { OPTION_NO_TMED, "NoTMED", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_CRT2_MEM, "Crt2Memory", OPTV_INTEGER, {0}, FALSE }, + { OPTION_DUAL_REFRESH, "DualRefresh", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_CRT_CLK_INDX, "CrtClkIndx", OPTV_INTEGER, {0}, FALSE }, + { OPTION_FP_CLK_INDX, "FPClkIndx", OPTV_INTEGER, {0}, FALSE }, + { OPTION_FP_MODE, "FPMode", OPTV_BOOLEAN, {0}, FALSE }, + { -1, NULL, OPTV_NONE, {0}, FALSE } +}; + +/* + * List of symbols from other modules that this module references. This + * list is used to tell the loader that it is OK for symbols here to be + * unresolved providing that it hasn't been told that they haven't been + * told that they are essential via a call to xf86LoaderReqSymbols() or + * xf86LoaderReqSymLists(). The purpose is this is to avoid warnings about + * unresolved symbols that are not required. + */ + +static const char *vgahwSymbols[] = { + "vgaHWAllocDefaultRegs", + "vgaHWFreeHWRec", + "vgaHWGetHWRec", + "vgaHWGetIOBase", + "vgaHWGetIndex", + "vgaHWHBlankKGA", + "vgaHWInit", + "vgaHWLock", + "vgaHWMapMem", + "vgaHWProtect", + "vgaHWRestore", + "vgaHWSave", + "vgaHWUnlock", + "vgaHWVBlankKGA", + "vgaHWddc1SetSpeed", + NULL +}; + +static const char *miscfbSymbols[] = { + "xf1bppScreenInit", + "xf4bppScreenInit", + "cfb8_16ScreenInit", + NULL +}; + +static const char *fbSymbols[] = { + "fbScreenInit", + "fbPictureInit", + NULL +}; + +static const char *xaaSymbols[] = { + "XAACreateInfoRec", + "XAADestroyInfoRec", + "XAAFillSolidRects" , + "XAAInit", + "XAAInitDualFramebufferOverlay", + "XAAStippleScanlineFuncMSBFirst", + NULL +}; + +static const char *ramdacSymbols[] = { + "xf86CreateCursorInfoRec", + "xf86DestroyCursorInfoRec", + "xf86InitCursor", + NULL +}; + +static const char *ddcSymbols[] = { + "xf86DoEDID_DDC1", + "xf86DoEDID_DDC2", + "xf86PrintEDID", + "xf86SetDDCproperties", + NULL +}; + +static const char *i2cSymbols[] = { + "xf86CreateI2CBusRec", + "xf86I2CBusInit", + "xf86I2CFindBus", + "xf86I2CProbeAddress", + NULL +}; + +static const char *shadowSymbols[] = { + "ShadowFBInit", + NULL +}; + +static const char *vbeSymbols[] = { + "VBEInit", + "vbeDoEDID", + "vbeFree", + NULL +}; + +#ifdef XFree86LOADER + +static MODULESETUPPROTO(chipsSetup); + +static XF86ModuleVersionInfo chipsVersRec = +{ + "chips", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XF86_VERSION_CURRENT, + CHIPS_MAJOR_VERSION, CHIPS_MINOR_VERSION, CHIPS_PATCHLEVEL, + ABI_CLASS_VIDEODRV, + ABI_VIDEODRV_VERSION, + MOD_CLASS_VIDEODRV, + {0,0,0,0} +}; + +/* + * This is the module init data. + * Its name has to be the driver name followed by ModuleData + */ +XF86ModuleData chipsModuleData = { &chipsVersRec, chipsSetup, NULL }; + +static pointer +chipsSetup(pointer module, pointer opts, int *errmaj, int *errmin) +{ + static Bool setupDone = FALSE; + + if (!setupDone) { + setupDone = TRUE; + xf86AddDriver(&CHIPS, module, 0); + + /* + * Modules that this driver always requires can be loaded here + * by calling LoadSubModule(). + */ + + /* + * Tell the loader about symbols from other modules that this module + * might refer to. + */ + LoaderRefSymLists(vgahwSymbols, miscfbSymbols, fbSymbols, xaaSymbols, + ramdacSymbols, ddcSymbols, i2cSymbols, + shadowSymbols, vbeSymbols, NULL); + + /* + * The return value must be non-NULL on success even though there + * is no TearDownProc. + */ + return (pointer)1; + } else { + if (errmaj) *errmaj = LDR_ONCEONLY; + return NULL; + } +} + +#endif /* XFree86LOADER */ + +static Bool +CHIPSGetRec(ScrnInfoPtr pScrn) +{ + /* + * Allocate a CHIPSRec, and hook it into pScrn->driverPrivate. + * pScrn->driverPrivate is initialised to NULL, so we can check if + * the allocation has already been done. + */ + if (pScrn->driverPrivate != NULL) + return TRUE; + + pScrn->driverPrivate = xnfcalloc(sizeof(CHIPSRec), 1); + + if (pScrn->driverPrivate == NULL) + return FALSE; + + return TRUE; +} + +static void +CHIPSFreeRec(ScrnInfoPtr pScrn) +{ + if (pScrn->driverPrivate == NULL) + return; + xfree(pScrn->driverPrivate); + pScrn->driverPrivate = NULL; +} + +/* Mandatory */ +static void +CHIPSIdentify(int flags) +{ + xf86PrintChipsets(CHIPS_NAME, "Driver for Chips and Technologies chipsets", + CHIPSChipsets); +} + +static const OptionInfoRec * +CHIPSAvailableOptions(int chipid, int busid) +{ + int chip = chipid & 0x0000ffff; + + if (busid == BUS_ISA) { + if ((chip == CHIPS_CT64200) || (chip == CHIPS_CT64300)) + return ChipsWingineOptions; + } + if (busid == BUS_PCI) { + if ((chip >= CHIPS_CT65550) && (chip <= CHIPS_CT69030)) + return ChipsHiQVOptions; + } + return Chips655xxOptions; +} + +/* Mandatory */ +static Bool +CHIPSProbe(DriverPtr drv, int flags) +{ + Bool foundScreen = FALSE; + int numDevSections, numUsed; + GDevPtr *devSections; + int *usedChips; + int i; + + /* + * Find the config file Device sections that match this + * driver, and return if there are none. + */ + if ((numDevSections = xf86MatchDevice(CHIPS_DRIVER_NAME, + &devSections)) <= 0) { + return FALSE; + } + /* PCI BUS */ + if (xf86GetPciVideoInfo() ) { + numUsed = xf86MatchPciInstances(CHIPS_NAME, PCI_VENDOR_CHIPSTECH, + CHIPSChipsets, CHIPSPCIchipsets, + devSections,numDevSections, drv, + &usedChips); + if (numUsed > 0) { + if (flags & PROBE_DETECT) + foundScreen = TRUE; + else for (i = 0; i < numUsed; i++) { + EntityInfoPtr pEnt; + /* Allocate a ScrnInfoRec */ + ScrnInfoPtr pScrn = NULL; + if ((pScrn = xf86ConfigPciEntity(pScrn,0,usedChips[i], + CHIPSPCIchipsets,NULL, + NULL,NULL,NULL,NULL))){ + pScrn->driverVersion = VERSION; + pScrn->driverName = CHIPS_DRIVER_NAME; + pScrn->name = CHIPS_NAME; + pScrn->Probe = CHIPSProbe; + pScrn->PreInit = CHIPSPreInit; + pScrn->ScreenInit = CHIPSScreenInit; + pScrn->SwitchMode = CHIPSSwitchMode; + pScrn->AdjustFrame = CHIPSAdjustFrame; + pScrn->EnterVT = CHIPSEnterVT; + pScrn->LeaveVT = CHIPSLeaveVT; + pScrn->FreeScreen = CHIPSFreeScreen; + pScrn->ValidMode = CHIPSValidMode; + foundScreen = TRUE; + } + + /* + * For cards that can do dual head per entity, mark the entity + * as sharable. + */ + pEnt = xf86GetEntityInfo(usedChips[i]); + if (pEnt->chipset == CHIPS_CT69030) { + CHIPSEntPtr cPtrEnt = NULL; + DevUnion *pPriv; + + xf86SetEntitySharable(usedChips[i]); + /* Allocate an entity private if necessary */ + if (CHIPSEntityIndex < 0) + CHIPSEntityIndex = xf86AllocateEntityPrivateIndex(); + pPriv = xf86GetEntityPrivate(pScrn->entityList[0], + CHIPSEntityIndex); + if (!pPriv->ptr) { + pPriv->ptr = xnfcalloc(sizeof(CHIPSEntRec), 1); + cPtrEnt = pPriv->ptr; + cPtrEnt->lastInstance = -1; + } else { + cPtrEnt = pPriv->ptr; + } + /* + * Set the entity instance for this instance of the + * driver. For dual head per card, instance 0 is the + * "master" instance, driving the primary head, and + * instance 1 is the "slave". + */ + cPtrEnt->lastInstance++; + xf86SetEntityInstanceForScreen(pScrn, pScrn->entityList[0], + cPtrEnt->lastInstance); + } + + } + xfree(usedChips); + } + } + + /* Isa Bus */ + numUsed = xf86MatchIsaInstances(CHIPS_NAME,CHIPSChipsets,CHIPSISAchipsets, + drv,chipsFindIsaDevice,devSections, + numDevSections,&usedChips); + if (numUsed > 0) { + if (flags & PROBE_DETECT) + foundScreen = TRUE; + else for (i = 0; i < numUsed; i++) { + ScrnInfoPtr pScrn = NULL; + if ((pScrn = xf86ConfigIsaEntity(pScrn,0, + usedChips[i], + CHIPSISAchipsets,NULL, + NULL,NULL,NULL,NULL))) { + pScrn->driverVersion = VERSION; + pScrn->driverName = CHIPS_DRIVER_NAME; + pScrn->name = CHIPS_NAME; + pScrn->Probe = CHIPSProbe; + pScrn->PreInit = CHIPSPreInit; + pScrn->ScreenInit = CHIPSScreenInit; + pScrn->SwitchMode = CHIPSSwitchMode; + pScrn->AdjustFrame = CHIPSAdjustFrame; + pScrn->EnterVT = CHIPSEnterVT; + pScrn->LeaveVT = CHIPSLeaveVT; + pScrn->FreeScreen = CHIPSFreeScreen; + pScrn->ValidMode = CHIPSValidMode; + foundScreen = TRUE; + } + xfree(usedChips); + } + } + + xfree(devSections); + return foundScreen; +} + +static int +chipsFindIsaDevice(GDevPtr dev) +{ + int found = -1; + unsigned char tmp; + + /* + * This function has the only direct register access in the C&T driver. + * All other register access through functions to allow for full MMIO. + */ + outb(0x3D6, 0x00); + tmp = inb(0x3D7); + + switch (tmp & 0xF0) { + case 0x70: /* CT65520 */ + found = CHIPS_CT65520; break; + case 0x80: /* CT65525 or CT65530 */ + found = CHIPS_CT65530; break; + case 0xA0: /* CT64200 */ + found = CHIPS_CT64200; break; + case 0xB0: /* CT64300 */ + found = CHIPS_CT64300; break; + case 0xC0: /* CT65535 */ + found = CHIPS_CT65535; break; + default: + switch (tmp & 0xF8) { + case 0xD0: /* CT65540 */ + found = CHIPS_CT65540; break; + case 0xD8: /* CT65545 or CT65546 or CT65548 */ + switch (tmp & 7) { + case 3: + found = CHIPS_CT65546; break; + case 4: + found = CHIPS_CT65548; break; + default: + found = CHIPS_CT65545; break; + + } + break; + default: + if (tmp == 0x2C) { + outb(0x3D6, 0x01); + tmp = inb(0x3D7); + if (tmp != 0x10) break; + outb(0x3D6, 0x02); + tmp = inb(0x3D7); + switch (tmp) { + case 0xE0: /* CT65550 */ + found = CHIPS_CT65550; break; + case 0xE4: /* CT65554 */ + found = CHIPS_CT65554; break; + case 0xE5: /* CT65555 */ + found = CHIPS_CT65555; break; + case 0xF4: /* CT68554 */ + found = CHIPS_CT68554; break; + case 0xC0: /* CT69000 */ + found = CHIPS_CT69000; break; + case 0x30: /* CT69030 */ + outb(0x3D6, 0x03); + tmp = inb(0x3D7); + if (tmp == 0xC) + found = CHIPS_CT69030; + break; + default: + break; + } + } + break; + } + break; + } + /* We only want ISA/VL Bus - so check for PCI Bus */ + if(found > CHIPS_CT65548) { + outb(0x3D6, 0x08); + tmp = inb(0x3D7); + if(tmp & 0x01) found = -1; + } else if(found > CHIPS_CT65535) { + outb(0x3D6, 0x01); + tmp = inb(0x3D7); + if ((tmp & 0x07) == 0x06) found = -1; + } + return found; +} + +/* Mandatory */ +Bool +CHIPSPreInit(ScrnInfoPtr pScrn, int flags) +{ + pciVideoPtr pciPtr; + ClockRangePtr clockRanges; + int i; + CHIPSPtr cPtr; + Bool res = FALSE; + CHIPSEntPtr cPtrEnt = NULL; + + if (flags & PROBE_DETECT) return FALSE; + + /* The vgahw module should be loaded here when needed */ + if (!xf86LoadSubModule(pScrn, "vgahw")) + return FALSE; + xf86LoaderReqSymLists(vgahwSymbols, NULL); + + /* Allocate the ChipsRec driverPrivate */ + if (!CHIPSGetRec(pScrn)) { + return FALSE; + } + cPtr = CHIPSPTR(pScrn); + + /* XXX Check the number of entities, and fail if it isn't one. */ + if (pScrn->numEntities != 1) + return FALSE; + + /* Since the capabilities are determined by the chipset the very + * first thing to do is, figure out the chipset and its capabilities + */ + + /* This is the general case */ + for (i = 0; i<pScrn->numEntities; i++) { + cPtr->pEnt = xf86GetEntityInfo(pScrn->entityList[i]); + if (cPtr->pEnt->resources) return FALSE; + cPtr->Chipset = cPtr->pEnt->chipset; + pScrn->chipset = (char *)xf86TokenToString(CHIPSChipsets, + cPtr->pEnt->chipset); + if ((cPtr->Chipset == CHIPS_CT64200) || + (cPtr->Chipset == CHIPS_CT64300)) cPtr->Flags |= ChipsWingine; + if ((cPtr->Chipset >= CHIPS_CT65550) && + (cPtr->Chipset <= CHIPS_CT69030)) cPtr->Flags |= ChipsHiQV; + + /* This driver can handle ISA and PCI buses */ + if (cPtr->pEnt->location.type == BUS_PCI) { + pciPtr = xf86GetPciInfoForEntity(cPtr->pEnt->index); + cPtr->PciInfo = pciPtr; + cPtr->PciTag = pciTag(cPtr->PciInfo->bus, + cPtr->PciInfo->device, + cPtr->PciInfo->func); + } + } + /* INT10 */ +#if 0 + if (xf86LoadSubModule(pScrn, "int10")) { + xf86Int10InfoPtr pInt; + xf86LoaderReqSymLists(int10Symbols, NULL); +#if 1 + xf86DrvMsg(pScrn->scrnIndex,X_INFO,"initializing int10\n"); + pInt = xf86InitInt10(cPtr->pEnt->index); + xf86FreeInt10(pInt); +#endif + } +#endif + + if (xf86LoadSubModule(pScrn, "vbe")) { + xf86LoaderReqSymLists(vbeSymbols, NULL); + cPtr->pVbe = VBEInit(NULL,cPtr->pEnt->index); + } + + /* Now that we've identified the chipset, setup the capabilities flags */ + switch (cPtr->Chipset) { + case CHIPS_CT69030: + cPtr->Flags |= ChipsDualChannelSupport; + case CHIPS_CT69000: + cPtr->Flags |= ChipsFullMMIOSupport; + /* Fall through */ + case CHIPS_CT65555: + cPtr->Flags |= ChipsImageReadSupport; /* Does the 69000 support it? */ + /* Fall through */ + case CHIPS_CT68554: + cPtr->Flags |= ChipsTMEDSupport; + /* Fall through */ + case CHIPS_CT65554: + case CHIPS_CT65550: + cPtr->Flags |= ChipsGammaSupport; + cPtr->Flags |= ChipsVideoSupport; + /* Fall through */ + case CHIPS_CT65548: + case CHIPS_CT65546: + case CHIPS_CT65545: + cPtr->Flags |= ChipsMMIOSupport; + /* Fall through */ + case CHIPS_CT64300: + cPtr->Flags |= ChipsAccelSupport; + /* Fall through */ + case CHIPS_CT65540: + cPtr->Flags |= ChipsHDepthSupport; + cPtr->Flags |= ChipsDPMSSupport; + /* Fall through */ + case CHIPS_CT65535: + case CHIPS_CT65530: + case CHIPS_CT65525: + cPtr->Flags |= ChipsLinearSupport; + /* Fall through */ + case CHIPS_CT64200: + case CHIPS_CT65520: + break; + } + + /* Check for shared entities */ + if (xf86IsEntityShared(pScrn->entityList[0])) { + if (!(cPtr->Flags & ChipsDualChannelSupport)) + return FALSE; + + /* Make sure entity is PCI for now, though this might not be needed. */ + if (cPtr->pEnt->location.type != BUS_PCI) + return FALSE; + + /* Allocate an entity private if necessary */ + if (xf86IsEntityShared(pScrn->entityList[0])) { + cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0], + CHIPSEntityIndex)->ptr; + cPtr->entityPrivate = cPtrEnt; + } +#if 0 + /* Set cPtr->device to the relevant Device section */ + cPtr->device = xf86GetDevFromEntity(pScrn->entityList[0], + pScrn->entityInstanceList[0]); +#endif + } + + /* Set the driver to use the PIO register functions by default */ + CHIPSSetStdExtFuncs(cPtr); + + /* Call the device specific PreInit */ + if (IS_HiQV(cPtr)) + res = chipsPreInitHiQV(pScrn, flags); + else if (IS_Wingine(cPtr)) + res = chipsPreInitWingine(pScrn, flags); + else + res = chipsPreInit655xx(pScrn, flags); + + if (cPtr->UseFullMMIO) + chipsUnmapMem(pScrn); + + if (!res) { + vbeFree(cPtr->pVbe); + cPtr->pVbe = NULL; + return FALSE; + } + +/*********/ + /* + * Setup the ClockRanges, which describe what clock ranges are available, + * and what sort of modes they can be used for. + */ + clockRanges = xnfcalloc(sizeof(ClockRange), 1); + clockRanges->next = NULL; + clockRanges->ClockMulFactor = cPtr->ClockMulFactor; + clockRanges->minClock = cPtr->MinClock; + clockRanges->maxClock = cPtr->MaxClock; + clockRanges->clockIndex = -1; /* programmable */ + if (cPtr->PanelType & ChipsLCD) { + clockRanges->interlaceAllowed = FALSE; + clockRanges->doubleScanAllowed = FALSE; + } else { + clockRanges->interlaceAllowed = TRUE; + clockRanges->doubleScanAllowed = TRUE; + } + /* + * Reduce the amount of video ram for the modes, so that they + * don't overlap with the DSTN framebuffer + */ + pScrn->videoRam -= (cPtr->FrameBufferSize + 1023) / 1024; + + cPtr->Rounding = 8 * (pScrn->bitsPerPixel <= 8 ? 8 + : pScrn->bitsPerPixel); + + i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, + pScrn->display->modes, clockRanges, + NULL, 256, 2048, cPtr->Rounding, + 128, 2048, pScrn->display->virtualX, + pScrn->display->virtualY, cPtr->FbMapSize, + LOOKUP_BEST_REFRESH); + + if (i == -1) { + vbeFree(cPtr->pVbe); + cPtr->pVbe = NULL; + CHIPSFreeRec(pScrn); + return FALSE; + } + + /* + * Put the DSTN framebuffer back into the video ram + */ + pScrn->videoRam += (cPtr->FrameBufferSize + 1023) / 1024; + + /* Prune the modes marked as invalid */ + xf86PruneDriverModes(pScrn); + + if (i == 0 || pScrn->modes == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); + vbeFree(cPtr->pVbe); + cPtr->pVbe = NULL; + CHIPSFreeRec(pScrn); + return FALSE; + } + + /* + * Set the CRTC parameters for all of the modes based on the type + * of mode, and the chipset's interlace requirements. + * + * Calling this is required if the mode->Crtc* values are used by the + * driver and if the driver doesn't provide code to set them. They + * are not pre-initialised at all. + */ + xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V); + + /* Set the current mode to the first in the list */ + pScrn->currentMode = pScrn->modes; + + /* Print the list of modes being used */ + xf86PrintModes(pScrn); + + /* If monitor resolution is set on the command line, use it */ + xf86SetDpi(pScrn, 0, 0); + + /* Load bpp-specific modules */ + switch (pScrn->bitsPerPixel) { + case 1: + if (xf86LoadSubModule(pScrn, "xf1bpp") == NULL) { + vbeFree(cPtr->pVbe); + cPtr->pVbe = NULL; + CHIPSFreeRec(pScrn); + return FALSE; + } + xf86LoaderReqSymbols("xf1bppScreenInit", NULL); + break; + case 4: + if (xf86LoadSubModule(pScrn, "xf4bpp") == NULL) { + vbeFree(cPtr->pVbe); + cPtr->pVbe = NULL; + CHIPSFreeRec(pScrn); + return FALSE; + } + xf86LoaderReqSymbols("xf4bppScreenInit", NULL); + break; + case 16: + if (cPtr->Flags & ChipsOverlay8plus16) { + if (xf86LoadSubModule(pScrn, "xf8_16bpp") == NULL) { + vbeFree(cPtr->pVbe); + cPtr->pVbe = NULL; + CHIPSFreeRec(pScrn); + return FALSE; + } + xf86LoaderReqSymbols("cfb8_16bppScreenInit", NULL); + break; + } + default: + if (xf86LoadSubModule(pScrn, "fb") == NULL) { + vbeFree(cPtr->pVbe); + cPtr->pVbe = NULL; + CHIPSFreeRec(pScrn); + return FALSE; + } + xf86LoaderReqSymLists(fbSymbols, NULL); + break; + } + + if (cPtr->Flags & ChipsAccelSupport) { + if (!xf86LoadSubModule(pScrn, "xaa")) { + vbeFree(cPtr->pVbe); + cPtr->pVbe = NULL; + CHIPSFreeRec(pScrn); + return FALSE; + } + xf86LoaderReqSymLists(xaaSymbols, NULL); + } + + if (cPtr->Flags & ChipsShadowFB) { + if (!xf86LoadSubModule(pScrn, "shadowfb")) { + vbeFree(cPtr->pVbe); + cPtr->pVbe = NULL; + CHIPSFreeRec(pScrn); + return FALSE; + } + xf86LoaderReqSymLists(shadowSymbols, NULL); + } + + if (cPtr->Accel.UseHWCursor) { + if (!xf86LoadSubModule(pScrn, "ramdac")) { + vbeFree(cPtr->pVbe); + cPtr->pVbe = NULL; + CHIPSFreeRec(pScrn); + return FALSE; + } + xf86LoaderReqSymLists(ramdacSymbols, NULL); + } + + if (cPtr->Flags & ChipsLinearSupport) + xf86SetOperatingState(resVgaMem, cPtr->pEnt->index, ResDisableOpr); + + if (cPtr->MMIOBaseVGA) + xf86SetOperatingState(resVgaIo, cPtr->pEnt->index, ResDisableOpr); + vbeFree(cPtr->pVbe); + cPtr->pVbe = NULL; + return TRUE; +} + +static Bool +chipsPreInitHiQV(ScrnInfoPtr pScrn, int flags) +{ + int bytesPerPixel; + unsigned char tmp; + MessageType from; + int i; + unsigned int Probed[3], FPclkI, CRTclkI; + double real; + int val, indx; + const char *s; + pointer pVbeModule = NULL; + + vgaHWPtr hwp; + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSEntPtr cPtrEnt = NULL; + CHIPSPanelSizePtr Size = &cPtr->PanelSize; + CHIPSMemClockPtr MemClk = &cPtr->MemClock; + CHIPSClockPtr SaveClk = &(cPtr->SavedReg.Clock); + resRange linearRes[] = { {ResExcMemBlock|ResBios|ResBus,0,0},_END }; + + /* Set pScrn->monitor */ + pScrn->monitor = pScrn->confScreen->monitor; + + /* All HiQV chips support 16/24/32 bpp */ + if (!xf86SetDepthBpp(pScrn, 8, 8, 8, Support24bppFb | Support32bppFb | + SupportConvert32to24 | PreferConvert32to24)) + return FALSE; + else { + /* Check that the returned depth is one we support */ + switch (pScrn->depth) { + case 1: + case 4: + case 8: + case 15: + case 16: + case 24: + case 32: + /* OK */ + break; + default: + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Given depth (%d) is not supported by this driver\n", + pScrn->depth); + return FALSE; + } + } + xf86PrintDepthBpp(pScrn); + + /* Get the depth24 pixmap format */ + if (pScrn->depth == 24 && pix24bpp == 0) + pix24bpp = xf86GetBppFromDepth(pScrn, 24); + + /* + * Allocate a vgaHWRec, this must happen after xf86SetDepthBpp for 1bpp + */ + if (!vgaHWGetHWRec(pScrn)) + return FALSE; + + hwp = VGAHWPTR(pScrn); + vgaHWGetIOBase(hwp); + cPtr->PIOBase = hwp->PIOOffset; + + /* + * Must allow ensure that storage for the 2nd set of vga registers is + * allocated for dual channel cards + */ + if ((cPtr->Flags & ChipsDualChannelSupport) && + (! xf86IsEntityShared(pScrn->entityList[0]))) + vgaHWAllocDefaultRegs(&(cPtr->VgaSavedReg2)); + + /* + * This must happen after pScrn->display has been set because + * xf86SetWeight references it. + */ + if (pScrn->depth > 8) { + /* The defaults are OK for us */ + rgb zeros = {0, 0, 0}; + + if (!xf86SetWeight(pScrn, zeros, zeros)) { + return FALSE; + } else { + /* XXX check that weight returned is supported */ + ; + } + } + + if (!xf86SetDefaultVisual(pScrn, -1)) + return FALSE; + + /* The gamma fields must be initialised when using the new cmap code */ + if (pScrn->depth > 1) { + Gamma zeros = {0.0, 0.0, 0.0}; + + if (!xf86SetGamma(pScrn, zeros)) + return FALSE; + } + + bytesPerPixel = max(1, pScrn->bitsPerPixel >> 3); + + /* Collect all of the relevant option flags (fill in pScrn->options) */ + xf86CollectOptions(pScrn, NULL); + /* Process the options */ + if (!(cPtr->Options = xalloc(sizeof(ChipsHiQVOptions)))) + return FALSE; + memcpy(cPtr->Options, ChipsHiQVOptions, sizeof(ChipsHiQVOptions)); + xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, cPtr->Options); + + /* Set the bits per RGB */ + if (pScrn->depth > 1) { + /* Default to 6, is this right for HiQV?? */ + pScrn->rgbBits = 8; + if (xf86GetOptValInteger(cPtr->Options, OPTION_RGB_BITS, &val)) { + if (val == 6 || val == 8) { + pScrn->rgbBits = val; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Bits per RGB set to " + "%d\n", pScrn->rgbBits); + } else + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Invalid number of " + "rgb bits %d\n", val); + } + } + if ((cPtr->Flags & ChipsAccelSupport) && + (xf86ReturnOptValBool(cPtr->Options, OPTION_NOACCEL, FALSE))) { + cPtr->Flags &= ~ChipsAccelSupport; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n"); + } + + from = X_DEFAULT; + if (pScrn->bitsPerPixel < 8) { + /* Default to SW cursor for 1/4 bpp */ + cPtr->Accel.UseHWCursor = FALSE; + } else { + cPtr->Accel.UseHWCursor = TRUE; + } + if (xf86GetOptValBool(cPtr->Options, OPTION_HW_CURSOR, + &cPtr->Accel.UseHWCursor)) + from = X_CONFIG; + if (xf86GetOptValBool(cPtr->Options, OPTION_SW_CURSOR, + &cPtr->Accel.UseHWCursor)) { + from = X_CONFIG; + cPtr->Accel.UseHWCursor = !cPtr->Accel.UseHWCursor; + } + xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n", + (cPtr->Accel.UseHWCursor) ? "HW" : "SW"); + + /* Default to nonlinear for < 8bpp and linear for >= 8bpp. */ + if (pScrn->bitsPerPixel < 8) { + if (!xf86ReturnOptValBool(cPtr->Options, OPTION_LINEAR, FALSE)) { + cPtr->Flags &= ~ChipsLinearSupport; + from = X_CONFIG; + } + } else if (!xf86ReturnOptValBool(cPtr->Options, OPTION_LINEAR, TRUE)) { + cPtr->Flags &= ~ChipsLinearSupport; + from = X_CONFIG; + } + + /* linear base */ + if (cPtr->Flags & ChipsLinearSupport) { + if (cPtr->pEnt->location.type == BUS_PCI) { + /* Tack on 0x800000 to access the big-endian aperture? */ +#if X_BYTE_ORDER == X_BIG_ENDIAN + cPtr->FbAddress = (cPtr->PciInfo->memBase[0] & 0xff800000) + 0x800000L; +#else + cPtr->FbAddress = cPtr->PciInfo->memBase[0] & 0xff800000; +#endif + from = X_PROBED; + if (xf86RegisterResources(cPtr->pEnt->index,NULL,ResNone)) + cPtr->Flags &= ~ChipsLinearSupport; + } else { + if (cPtr->pEnt->device->MemBase) { + cPtr->FbAddress = cPtr->pEnt->device->MemBase; + from = X_CONFIG; + } else { + cPtr->FbAddress = ((unsigned int) + (cPtr->readXR(cPtr, 0x06))) << 24; + cPtr->FbAddress |= ((unsigned int) + (0x80 & (cPtr->readXR(cPtr, 0x05)))) << 16; + from = X_PROBED; + } + linearRes[0].rBegin = cPtr->FbAddress; + linearRes[0].rEnd = cPtr->FbAddress + 0x800000; + if (xf86RegisterResources(cPtr->pEnt->index,linearRes,ResNone)) { + cPtr->Flags &= ~ChipsLinearSupport; + from = X_PROBED; + } + } + } + if (cPtr->Flags & ChipsLinearSupport) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Enabling linear addressing\n"); + xf86DrvMsg(pScrn->scrnIndex, from, + "base address is set at 0x%X.\n", cPtr->FbAddress); + cPtr->IOAddress = cPtr->FbAddress + 0x400000L; + } else + xf86DrvMsg(pScrn->scrnIndex, from, + "Disabling linear addressing\n"); + + if ((s = xf86GetOptValString(cPtr->Options, OPTION_ROTATE)) + || xf86ReturnOptValBool(cPtr->Options, OPTION_SHADOW_FB, FALSE)) { + if (!(cPtr->Flags & ChipsLinearSupport)) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Option \"ShadowFB\" ignored. Not supported without linear addressing\n"); + } else if (pScrn->depth < 8) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Option \"ShadowFB\" ignored. Not supported at this depth.\n"); + } else { + cPtr->Rotate = 0; + if (s) { + if(!xf86NameCmp(s, "CW")) { + /* accel is disabled below for shadowFB */ + cPtr->Flags |= ChipsShadowFB; + cPtr->Rotate = 1; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Rotating screen clockwise\n"); + } else if(!xf86NameCmp(s, "CCW")) { + cPtr->Flags |= ChipsShadowFB; + cPtr->Rotate = -1; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Rotating screen" + "counter clockwise\n"); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"%s\" is not a valid" + "value for Option \"Rotate\"\n", s); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Valid options are \"CW\" or \"CCW\"\n"); + } + } else { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Using \"Shadow Framebuffer\"\n"); + cPtr->Flags |= ChipsShadowFB; + } + } + } + + if ((s = xf86GetOptValString(cPtr->Options, OPTION_OVERLAY))) { + if (!*s || !xf86NameCmp(s, "8,16") || !xf86NameCmp(s, "16,8")) { + if (pScrn->bitsPerPixel == 16) { + if (cPtr->Flags & ChipsLinearSupport) { + cPtr->Flags |= ChipsOverlay8plus16; + if(!xf86GetOptValInteger( + cPtr->Options, OPTION_COLOR_KEY, &(pScrn->colorKey))) + pScrn->colorKey = TRANSPARENCY_KEY; + pScrn->overlayFlags = OVERLAY_8_16_DUALFB; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "PseudoColor overlay enabled.\n"); + if (!xf86IsOptionSet(cPtr->Options, OPTION_LCD_STRETCH)) + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + " - Forcing option \"NoStretch\".\n"); + if (!xf86IsOptionSet(cPtr->Options, OPTION_LCD_CENTER)) + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + " - Forcing option \"LcdCenter\".\n"); + if (cPtr->Flags & ChipsShadowFB) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + " - Disabling \"Shadow Framebuffer\".\n"); + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + " Not support with option \"8Plus16\".\n"); + cPtr->Flags &= ~ChipsShadowFB; + cPtr->Rotate = 0; + } + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Option \"Overlay\" ignored. Not supported without linear addressing\n"); + } + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Option \"Overlay\" is not supported in this configuration\n"); + } + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "\"%s\" is not a valid value for Option \"Overlay\"\n", s); + } + } + + if (!(cPtr->Flags & ChipsOverlay8plus16)) { + if(xf86GetOptValInteger(cPtr->Options, OPTION_VIDEO_KEY, + &(cPtr->videoKey))) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video key set to 0x%x\n", + cPtr->videoKey); + } else { + cPtr->videoKey = (1 << pScrn->offset.red) | + (1 << pScrn->offset.green) | + (((pScrn->mask.blue >> pScrn->offset.blue) - 1) + << pScrn->offset.blue); + } + } + + if (cPtr->Flags & ChipsShadowFB) { + if (cPtr->Flags & ChipsAccelSupport) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "HW acceleration is not supported with shadow fb\n"); + cPtr->Flags &= ~ChipsAccelSupport; + } + if (cPtr->Rotate && cPtr->Accel.UseHWCursor) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "HW cursor is not supported with rotate\n"); + cPtr->Accel.UseHWCursor = FALSE; + } + } + + if (xf86ReturnOptValBool(cPtr->Options, OPTION_MMIO, TRUE)) { + cPtr->UseMMIO = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Using MMIO\n"); + + /* Are we using MMIO mapping of VGA registers */ + if (xf86ReturnOptValBool(cPtr->Options, OPTION_FULL_MMIO, FALSE)) { + if ((cPtr->Flags & ChipsLinearSupport) + && (cPtr->Flags & ChipsFullMMIOSupport) + && (cPtr->pEnt->location.type == BUS_PCI)) { + + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Enabling Full MMIO\n"); + cPtr->UseFullMMIO = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Using Full MMIO\n"); + + /* + * We need to map the framebuffer to read/write regs. + * but can't do that without the FbMapSize. So need to + * fake value for PreInit. This isn't a problem as + * framebuffer isn't actually used in PreInit + */ + cPtr->FbMapSize = 1024 * 1024; + + /* Map the linear framebuffer */ + if (!chipsMapMem(pScrn)) + return FALSE; + + /* Setup the MMIO register functions */ + if (cPtr->MMIOBaseVGA) { + CHIPSSetMmioExtFuncs(cPtr); + CHIPSHWSetMmioFuncs(pScrn, cPtr->MMIOBaseVGA, 0x0); + } + } else { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "FULL_MMIO option ignored\n"); + } + } + } else { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,"Disabling MMIO: " + "no acceleration, no hw_cursor\n"); + cPtr->UseMMIO = FALSE; + cPtr->Accel.UseHWCursor = FALSE; + cPtr->Flags &= ~ChipsAccelSupport; + } + + + if (cPtr->Flags & ChipsDualChannelSupport) { + + if (xf86IsEntityShared(pScrn->entityList[0])) { + cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0], + CHIPSEntityIndex)->ptr; +#if 1 + /* + * XXX This assumes that the lower number screen is always the + * "master" head, and that the "master" is the first CRTC. This + * can result in unexpected behaviour when the config file marks + * the primary CRTC as the second screen. + */ + if (xf86IsPrimInitDone(pScrn->entityList[0])) +#else + /* + * This is an alternative version that determines which is the + * secondary CRTC from the screen field in cPtr->pEnt->device. + * It doesn't currently work because there are things that assume + * the primary CRTC is initialised first. + */ + if (cPtr->pEnt->device->screen == 1) + +#endif + { + /* This is the second crtc */ + cPtr->SecondCrtc = TRUE; + cPtr->UseDualChannel = TRUE; + } else + cPtr->SecondCrtc = FALSE; + + } else { + if (xf86ReturnOptValBool(cPtr->Options, + OPTION_DUAL_REFRESH, FALSE)) { + cPtr->Flags |= ChipsDualRefresh; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Dual Refresh mode enabled\n"); + cPtr->UseDualChannel = TRUE; + } + } + + /* Store IOSS/MSS so that we can restore them */ + cPtr->storeIOSS = cPtr->readIOSS(cPtr); + cPtr->storeMSS = cPtr->readMSS(cPtr); + DUALOPEN; + } + + /* memory size */ + if (cPtr->pEnt->device->videoRam != 0) { + pScrn->videoRam = cPtr->pEnt->device->videoRam; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "VideoRAM: %d kByte\n", + pScrn->videoRam); + } else { + /* not given, probe it */ + switch (cPtr->Chipset) { + case CHIPS_CT69030: + /* The ct69030 has 4Mb of SGRAM integrated */ + pScrn->videoRam = 4096; + break; + case CHIPS_CT69000: + /* The ct69000 has 2Mb of SGRAM integrated */ + pScrn->videoRam = 2048; + break; + case CHIPS_CT65550: + /* XR43: DRAM interface */ + /* bit 2-1: memory size */ + /* 0: 1024 kB */ + /* 1: 2048 kB */ + /* 2: reserved */ + /* 3: reserved */ + switch (((cPtr->readXR(cPtr, 0x43)) & 0x06) >> 1) { + case 0: + pScrn->videoRam = 1024; + break; + case 1: + case 2: + case 3: + pScrn->videoRam = 2048; + break; + } + break; + default: + /* XRE0: Software reg */ + /* bit 3-0: memory size */ + /* 0: 512k */ + /* 1: 1024k */ + /* 2: 1536k(1.5M)*/ + /* 3: 2048k */ + /* 7: 4096k */ + tmp = (cPtr->readXR(cPtr, 0xE0)) & 0xF; + switch (tmp) { + case 0: + pScrn->videoRam = 512; + break; + case 1: + pScrn->videoRam = 1024; + break; + case 2: + pScrn->videoRam = 1536; + break; + case 3: + pScrn->videoRam = 2048; + break; + case 7: + pScrn->videoRam = 4096; + break; + default: + pScrn->videoRam = 1024; + break; + } + break; + } + } + + if ((cPtr->Flags & ChipsDualChannelSupport) && + (xf86IsEntityShared(pScrn->entityList[0]))) { + /* + * This takes gives either half or the amount of memory specified + * with the Crt2Memory option + */ + if(cPtr->SecondCrtc == FALSE) { + int crt2mem = -1, adjust; + + xf86GetOptValInteger(cPtr->Options, OPTION_CRT2_MEM, &crt2mem); + if (crt2mem > 0) { + adjust = crt2mem; + from = X_CONFIG; + } else { + adjust = pScrn->videoRam / 2; + from = X_DEFAULT; + } + xf86DrvMsg(pScrn->scrnIndex, from, + "CRT2 will use %dK of VideoRam\n", + adjust); + + cPtrEnt->mastervideoRam = pScrn->videoRam - adjust; + pScrn->videoRam = cPtrEnt->mastervideoRam; + cPtrEnt->slavevideoRam = adjust; + cPtrEnt->masterFbAddress = cPtr->FbAddress; + cPtr->FbMapSize = + cPtrEnt->masterFbMapSize = pScrn->videoRam * 1024; + cPtrEnt->slaveFbMapSize = cPtrEnt->slavevideoRam * 1024; + } else { + cPtrEnt->slaveFbAddress = cPtr->FbAddress + + cPtrEnt->masterFbAddress; + cPtr->FbMapSize = cPtrEnt->slaveFbMapSize; + pScrn->videoRam = cPtrEnt->slavevideoRam; + } + cPtrEnt->refCount++; + } else { + /* Normal Handling of video ram etc */ + cPtr->FbMapSize = pScrn->videoRam * 1024; + } + + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VideoRAM: %d kByte\n", + pScrn->videoRam); + + /* Store register values that might be messed up by a suspend resume */ + /* Do this early as some of the other code in PreInit relies on it */ + cPtr->SuspendHack.vgaIOBaseFlag = ((hwp->readMiscOut(hwp)) & 0x01); + cPtr->IOBase = (unsigned int)(cPtr->SuspendHack.vgaIOBaseFlag ? + 0x3D0 : 0x3B0); + + /* + * Do DDC here: if VESA BIOS detects an external monitor it + * might switch. SetPanelType() will detect this. + */ + if ((pVbeModule = xf86LoadSubModule(pScrn, "ddc"))) { + Bool ddc_done = FALSE; + xf86MonPtr pMon; + + xf86LoaderReqSymLists(ddcSymbols, NULL); + + if (cPtr->pVbe) { + if ((pMon + = xf86PrintEDID(vbeDoEDID(cPtr->pVbe, pVbeModule))) != NULL) { + ddc_done = TRUE; + xf86SetDDCproperties(pScrn,pMon); + } + } + + if (!ddc_done) + if (xf86LoadSubModule(pScrn, "i2c")) { + xf86LoaderReqSymLists(i2cSymbols,NULL); + + if (chips_i2cInit(pScrn)) { + if ((pMon = xf86PrintEDID(xf86DoEDID_DDC2(pScrn->scrnIndex, + cPtr->I2C))) != NULL) + ddc_done = TRUE; + xf86SetDDCproperties(pScrn,pMon); + } + } + if (!ddc_done) + chips_ddc1(pScrn); + } + + /*test STN / TFT */ + tmp = cPtr->readFR(cPtr, 0x10); + + /* XR51 or FR10: DISPLAY TYPE REGISTER */ + /* XR51[1-0] or FR10[1:0] for ct65550 : PanelType, */ + /* 0 = Single Panel Single Drive, 3 = Dual Panel Dual Drive */ + switch (tmp & 0x3) { + case 0: + if (xf86ReturnOptValBool(cPtr->Options, OPTION_STN, FALSE)) { + cPtr->PanelType |= ChipsSS; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "SS-STN probed\n"); + } else { + cPtr->PanelType |= ChipsTFT; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "TFT probed\n"); + } + break; + case 2: + cPtr->PanelType |= ChipsDS; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DS-STN probed\n"); + case 3: + cPtr->PanelType |= ChipsDD; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DD-STN probed\n"); + break; + default: + break; + } + + chipsSetPanelType(cPtr); + from = X_PROBED; + { + Bool fp_mode; + if (xf86GetOptValBool(cPtr->Options, OPTION_FP_MODE, &fp_mode)) { + if (fp_mode) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forcing FP Mode on\n"); + cPtr->PanelType |= ChipsLCD; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forcing FP Mode off\n"); + cPtr->PanelType = ~ChipsLCD; + } + from = X_CONFIG; + } + } + if ((cPtr->PanelType & ChipsLCD) && (cPtr->PanelType & ChipsCRT)) + xf86DrvMsg(pScrn->scrnIndex, from, "LCD/CRT\n"); + else if (cPtr->PanelType & ChipsLCD) + xf86DrvMsg(pScrn->scrnIndex, from, "LCD\n"); + else if (cPtr->PanelType & ChipsCRT) { + xf86DrvMsg(pScrn->scrnIndex, from, "CRT\n"); + /* monitor info */ +#if 1 + cPtr->Monitor = chipsSetMonitor(pScrn); +#endif + } + /* screen size */ + /* + * In LCD mode / dual mode we want to derive the timing values from + * the ones preset by bios + */ + if (cPtr->PanelType & ChipsLCD) { + + /* for 65550 we only need H/VDisplay values for screen size */ + unsigned char fr25, tmp1; +#ifdef DEBUG + unsigned char fr26; + char tmp2; +#endif + fr25 = cPtr->readFR(cPtr, 0x25); + tmp = cPtr->readFR(cPtr, 0x20); + Size->HDisplay = ((tmp + ((fr25 & 0x0F) << 8)) + 1) << 3; + tmp = cPtr->readFR(cPtr, 0x30); + tmp1 = cPtr->readFR(cPtr, 0x35); + Size->VDisplay = ((tmp1 & 0x0F) << 8) + tmp + 1; +#ifdef DEBUG + tmp = cPtr->readFR(cPtr, 0x21); + Size->HRetraceStart = ((tmp + ((fr25 & 0xF0) << 4)) + 1) << 3; + tmp1 = cPtr->readFR(cPtr, 0x22); + tmp2 = (tmp1 & 0x1F) - (tmp & 0x3F); + Size->HRetraceEnd = ((((tmp2 < 0) ? (tmp2 + 0x40) : tmp2) << 3) + + Size->HRetraceStart); + tmp = cPtr->readFR(cPtr, 0x23); + fr26 = cPtr->readFR(cPtr, 0x26); + Size->HTotal = ((tmp + ((fr26 & 0x0F) << 8)) + 5) << 3; + xf86ErrorF("x=%i, y=%i; xSync=%i, xSyncEnd=%i, xTotal=%i\n", + Size->HDisplay, Size->VDisplay, + Size->HRetraceStart,Size->HRetraceEnd, + Size->HTotal); +#endif + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Display Size: x=%i; y=%i\n", + Size->HDisplay, Size->VDisplay); + /* Warn the user if the panel size has been overridden by + * the modeline values + */ + if (xf86ReturnOptValBool(cPtr->Options, OPTION_PANEL_SIZE, FALSE)) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Display size overridden by modelines.\n"); + } + } + + /* Frame Buffer */ /* for LCDs */ + if (IS_STN(cPtr->PanelType)) { + tmp = cPtr->readFR(cPtr, 0x1A); /*Frame Buffer Ctrl. */ + if (tmp & 1) { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Frame Buffer used\n"); + if (!(tmp & 0x80)) { + /* Formula for calculating the size of the framebuffer. 3 + * bits per pixel 10 pixels per 32 bit dword. If frame + * acceleration is enabled the size can be halved. + */ + cPtr->FrameBufferSize = ( Size->HDisplay * + Size->VDisplay / 5 ) * ((tmp & 2) ? 1 : 2); + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Using embedded Frame Buffer, size %d bytes\n", + cPtr->FrameBufferSize); + } else + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Using external Frame Buffer used\n"); + } + if (tmp & 2) + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Frame accelerator enabled\n"); + } + + /* bus type */ + tmp = (cPtr->readXR(cPtr, 0x08)) & 1; + if (tmp == 1) { /*PCI */ + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "PCI Bus\n"); + cPtr->Bus = ChipsPCI; + } else { /* XR08: Linear addressing base, not for PCI */ + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VL Bus\n"); + cPtr->Bus = ChipsVLB; + } + + /* disable acceleration for 1 and 4 bpp */ + if (pScrn->bitsPerPixel < 8) { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Disabling acceleration for %d bpp\n", pScrn->bitsPerPixel); + cPtr->Flags &= ~ChipsAccelSupport; + } + + /* Set the flags for Colour transparency. This is dependent + * on the revision on the chip. Until exactly which chips + * have this bug are found, only allow 8bpp Colour transparency */ + if ((pScrn->bitsPerPixel == 8) || ((cPtr->Chipset >= CHIPS_CT65555) && + (pScrn->bitsPerPixel >= 8) && (pScrn->bitsPerPixel <= 24))) + cPtr->Flags |= ChipsColorTransparency; + else + cPtr->Flags &= ~ChipsColorTransparency; + + /* DAC info */ + if (!((cPtr->readXR(cPtr, 0xD0)) & 0x01)) + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Internal DAC disabled\n"); + + /* MMIO address offset */ + cPtr->Regs32 = ChipsReg32HiQV; + + /* sync reset ignored on this chipset */ + cPtr->SyncResetIgn = TRUE; /* !! */ + + /* We use a programmable clock */ + pScrn->numClocks = 26; /* Some number */ + pScrn->progClock = TRUE; + cPtr->ClockType = HiQV_STYLE | TYPE_PROGRAMMABLE; + + if (cPtr->pEnt->device->textClockFreq > 0) { + SaveClk->Clock = cPtr->pEnt->device->textClockFreq; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Using textclock freq: %7.3f.\n", + SaveClk->Clock/1000.0); + } else + SaveClk->Clock = 0; + + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Using programmable clocks\n"); + + /* Set the maximum memory clock. */ + switch (cPtr->Chipset) { + case CHIPS_CT65550: + if (((cPtr->readXR(cPtr, 0x04)) & 0xF) < 6) + MemClk->Max = 38000; /* Revision A chips */ + else + MemClk->Max = 50000; /* Revision B chips */ + break; + case CHIPS_CT65554: + case CHIPS_CT65555: + case CHIPS_CT68554: + MemClk->Max = 55000; + break; + case CHIPS_CT69000: + MemClk->Max = 83000; + break; + case CHIPS_CT69030: + MemClk->Max = 100000; + break; + } + + /* Probe the dot clocks */ + for (i = 0; i < 3; i++) { + unsigned int N,M,PSN,P,VCO_D; + int offset = i * 4; + + tmp = cPtr->readXR(cPtr,0xC2 + offset); + M = (cPtr->readXR(cPtr, 0xC0 + offset) + | (tmp & 0x03)) + 2; + N = (cPtr->readXR(cPtr, 0xC1 + offset) + | (( tmp >> 4) & 0x03)) + 2; + tmp = cPtr->readXR(cPtr, 0xC3 + offset); + PSN = (cPtr->Chipset == CHIPS_CT69000 || cPtr->Chipset == CHIPS_CT69030) + ? 1 : (((tmp & 0x1) ? 1 : 4) * ((tmp & 0x02) ? 5 : 1)); + VCO_D = ((tmp & 0x04) ? ((cPtr->Chipset == CHIPS_CT69000 || + cPtr->Chipset == CHIPS_CT69030) ? 1 : 16) : 4); + P = ((tmp & 0x70) >> 4); + Probed[i] = VCO_D * Fref / N; + Probed[i] = Probed[i] * M / (PSN * (1 << P)); + Probed[i] = Probed[i] / 1000; + } + CRTclkI = (hwp->readMiscOut(hwp) >> 2) & 0x03; + if (CRTclkI == 3) CRTclkI = 2; + if (cPtr->Chipset == CHIPS_CT69030) + FPclkI = (cPtr->readFR(cPtr, 0x01) >> 2) & 0x3; + else + FPclkI = (cPtr->readFR(cPtr, 0x03) >> 2) & 0x3; + if (FPclkI == 3) FPclkI = 2; + for (i = 0; i < 3; i++) { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Dot clock %i: %7.3f MHz",i, + (float)(Probed[i])/1000.); + if (FPclkI == i) xf86ErrorF(" FPclk"); + if (CRTclkI == i) xf86ErrorF(" CRTclk"); + xf86ErrorF("\n"); + } + cPtr->FPclock = Probed[FPclkI]; + cPtr->FPclkInx = FPclkI; + if (CRTclkI == FPclkI) { + if (FPclkI == 2) + CRTclkI = 1; + else + CRTclkI = 2; + } + cPtr->CRTclkInx = CRTclkI; + + + /* + * Some chips seem to dislike some clocks in one of the PLL's. Give + * the user the oppurtunity to change it + */ + if (xf86GetOptValInteger(cPtr->Options, OPTION_CRT_CLK_INDX, &indx)) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Force CRT Clock index to %d\n", + indx); + cPtr->CRTclkInx = indx; + + if (xf86GetOptValInteger(cPtr->Options, OPTION_FP_CLK_INDX, &indx)) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Force FP Clock index to %d\n", indx); + cPtr->FPclkInx = indx; + } else { + if (indx == cPtr->FPclkInx) { + if (indx == 2) + cPtr->FPclkInx = 1; + else + cPtr->FPclkInx = indx + 1; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "FP Clock index forced to %d\n", cPtr->FPclkInx); + } + } + } else if (xf86GetOptValInteger(cPtr->Options, OPTION_FP_CLK_INDX, + &indx)) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Force FP Clock index to %d\n", indx); + cPtr->FPclkInx = indx; + if (indx == cPtr->CRTclkInx) { + if (indx == 2) + cPtr->CRTclkInx = 1; + else + cPtr->CRTclkInx = indx + 1; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "CRT Clock index forced to %d\n", cPtr->CRTclkInx); + } + } + + + /* Probe the memory clock currently in use */ + MemClk->xrCC = cPtr->readXR(cPtr, 0xCC); + MemClk->M = (MemClk->xrCC & 0x7F) + 2; + MemClk->xrCD = cPtr->readXR(cPtr, 0xCD); + MemClk->N = (MemClk->xrCD & 0x7F) + 2; + MemClk->xrCE = cPtr->readXR(cPtr, 0xCE); + MemClk->PSN = (MemClk->xrCE & 0x1) ? 1 : 4; + MemClk->P = ((MemClk->xrCE & 0x70) >> 4); + /* Be careful with the calculation of ProbeClk as it can overflow */ + MemClk->ProbedClk = 4 * Fref / MemClk->N; + MemClk->ProbedClk = MemClk->ProbedClk * MemClk->M / (MemClk->PSN * + (1 << MemClk->P)); + MemClk->ProbedClk = MemClk->ProbedClk / 1000; + MemClk->Clk = MemClk->ProbedClk; + + if (xf86GetOptValFreq(cPtr->Options, OPTION_SET_MCLK, OPTUNITS_MHZ, &real)) { + int mclk = (int)(real * 1000.0); + if (mclk <= MemClk->Max) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Using memory clock of %7.3f MHz\n", + (float)(mclk/1000.)); + + /* Only alter the memory clock if the desired memory clock differs + * by 50kHz from the one currently being used. + */ + if (abs(mclk - MemClk->ProbedClk) > 50) { + unsigned char vclk[3]; + + MemClk->Clk = mclk; + chipsCalcClock(pScrn, MemClk->Clk, vclk); + MemClk->M = vclk[1] + 2; + MemClk->N = vclk[2] + 2; + MemClk->P = (vclk[0] & 0x70) >> 4; + MemClk->PSN = (vclk[0] & 0x1) ? 1 : 4; + MemClk->xrCC = vclk[1]; + MemClk->xrCD = vclk[2]; + MemClk->xrCE = 0x80 || vclk[0]; + } + } else + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Memory clock of %7.3f MHz exceeds limit of %7.3f MHz\n", + (float)(mclk/1000.), + (float)(MemClk->Max/1000.)); + } else + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Probed memory clock of %7.3f MHz\n", + (float)(MemClk->ProbedClk/1000.)); + + cPtr->ClockMulFactor = 1; + + /* Set the min pixel clock */ + cPtr->MinClock = 11000; /* XXX Guess, need to check this */ + xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock is %7.3f MHz\n", + (float)(cPtr->MinClock / 1000.)); + /* Set the max pixel clock */ + switch (cPtr->Chipset) { + case CHIPS_CT69030: + cPtr->MaxClock = 170000; + break; + case CHIPS_CT69000: + cPtr->MaxClock = 135000; + break; + case CHIPS_CT68554: + case CHIPS_CT65555: + cPtr->MaxClock = 110000; + break; + case CHIPS_CT65554: + cPtr->MaxClock = 95000; + break; + case CHIPS_CT65550: + if (((cPtr->readXR(cPtr, 0x04)) & 0xF) < 6) { + if ((cPtr->readFR(cPtr, 0x0A)) & 2) { + /*5V Vcc */ + cPtr->MaxClock = 100000; + } else { + /*3.3V Vcc */ + cPtr->MaxClock = 80000; + } + } else + cPtr->MaxClock = 95000; /* Revision B */ + break; + } + + /* Check if maxClock is limited by the MemClk. Only 70% to allow for */ + /* RAS/CAS. Extra byte per memory clock needed if framebuffer used */ + /* Extra byte if the overlay plane is activated */ + /* We have a 64bit wide memory bus on the 69030 and 69000, and 32bits */ + /* on the others. Thus multiply by a suitable factor */ + if ((cPtr->Chipset == CHIPS_CT69030) || (cPtr->Chipset == CHIPS_CT69000)) { + if (cPtr->FrameBufferSize && (cPtr->PanelType & ChipsLCD)) + if (cPtr->Flags & ChipsOverlay8plus16 ) + cPtr->MaxClock = min(cPtr->MaxClock, MemClk->Clk * 8 * 0.7 / 4); + else + cPtr->MaxClock = min(cPtr->MaxClock, + MemClk->Clk * 8 * 0.7 / (bytesPerPixel + 1)); + else + if (cPtr->Flags & ChipsOverlay8plus16) + cPtr->MaxClock = min(cPtr->MaxClock, MemClk->Clk * 8 * 0.7 / 3); + else + cPtr->MaxClock = min(cPtr->MaxClock, + MemClk->Clk * 8 * 0.7 / bytesPerPixel); + } else { + if (cPtr->FrameBufferSize && (cPtr->PanelType & ChipsLCD)) + if (cPtr->Flags & ChipsOverlay8plus16 ) + cPtr->MaxClock = min(cPtr->MaxClock, MemClk->Clk * 4 * 0.7 / 4); + else + cPtr->MaxClock = min(cPtr->MaxClock, + MemClk->Clk * 4 * 0.7 / (bytesPerPixel + 1)); + else + if (cPtr->Flags & ChipsOverlay8plus16) + cPtr->MaxClock = min(cPtr->MaxClock, MemClk->Clk * 4 * 0.7 / 3); + else + cPtr->MaxClock = min(cPtr->MaxClock, + MemClk->Clk * 4 * 0.7 / bytesPerPixel); + } + + + + if (cPtr->pEnt->device->dacSpeeds[0]) { + int speed = 0; + switch (pScrn->bitsPerPixel) { + case 1: + case 4: + case 8: + speed = cPtr->pEnt->device->dacSpeeds[DAC_BPP8]; + break; + case 16: + speed = cPtr->pEnt->device->dacSpeeds[DAC_BPP16]; + break; + case 24: + speed = cPtr->pEnt->device->dacSpeeds[DAC_BPP24]; + break; + case 32: + speed = cPtr->pEnt->device->dacSpeeds[DAC_BPP32]; + break; + } + + if (speed == 0) + speed = cPtr->pEnt->device->dacSpeeds[0]; + from = X_CONFIG; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "User max pixel clock of %7.3f MHz overrides %7.3f MHz limit\n", + (float)(speed / 1000.), (float)(cPtr->MaxClock / 1000.)); + cPtr->MaxClock = speed; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Max pixel clock is %7.3f MHz\n", + (float)(cPtr->MaxClock / 1000.)); + } + /* + * Prepare the FPclock: + * if FPclock <= MaxClock : don't modify the FP clock. + * else set FPclock to 90% of MaxClock. + */ + real = 0.; + switch(bytesPerPixel) { + case 1: + if (xf86GetOptValFreq(cPtr->Options, OPTION_FP_CLOCK_8, OPTUNITS_MHZ, &real)) + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "FP clock %7.3f MHz requested\n",real); + break; + case 2: + if (xf86GetOptValFreq(cPtr->Options, OPTION_FP_CLOCK_16, OPTUNITS_MHZ, &real)) + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "FP clock %7.3f MHz requested\n",real); + break; + case 3: + if (xf86GetOptValFreq(cPtr->Options, OPTION_FP_CLOCK_24, OPTUNITS_MHZ, &real)) + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "FP clock %7.3f MHz requested\n",real); + break; + case 4: + if (xf86GetOptValFreq(cPtr->Options, OPTION_FP_CLOCK_32, OPTUNITS_MHZ, &real)) + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "FP clock %7.3f MHz requested\n",real); + break; + } + val = (int) (real * 1000.); + if (val && val >= cPtr->MinClock && val <= cPtr->MaxClock) + cPtr->FPclock = val; + else if (cPtr->FPclock > cPtr->MaxClock) + cPtr->FPclock = (int)((float)cPtr->MaxClock * 0.9); + else + cPtr->FPclock = 0; /* special value */ + cPtr->FPClkModified = FALSE; + if (cPtr->FPclock) + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "FP clock set to %7.3f MHz\n", + (float)(cPtr->FPclock / 1000.)); + +#if defined(__arm32__) && defined(__NetBSD__) + ChipsPALMode.next = pScrn->monitor->Modes; + pScrn->monitor->Modes = &ChipsNTSCMode; +#endif + + + if (cPtr->Flags & ChipsDualChannelSupport) { + if (xf86IsEntityShared(pScrn->entityList[0])) { + if (cPtr->SecondCrtc == TRUE) { + cPtrEnt->slaveActive = FALSE; + } else { + cPtrEnt->masterActive = FALSE; + } + } + /* Put IOSS/MSS back to normal */ + cPtr->writeIOSS(cPtr, cPtr->storeIOSS); + cPtr->writeMSS(cPtr, hwp, cPtr->storeMSS); + + xf86SetPrimInitDone(pScrn->entityList[0]); + } + + return TRUE; +} + +static Bool +chipsPreInitWingine(ScrnInfoPtr pScrn, int flags) +{ + int i, bytesPerPixel, NoClocks = 0; + unsigned char tmp; + MessageType from; + vgaHWPtr hwp; + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSClockPtr SaveClk = &(cPtr->SavedReg.Clock); + Bool useLinear = FALSE; + char *s; + resRange linearRes[] = { {ResExcMemBlock|ResBios|ResBus,0,0},_END }; + + /* Set pScrn->monitor */ + pScrn->monitor = pScrn->confScreen->monitor; + + if (cPtr->Flags & ChipsHDepthSupport) + i = xf86SetDepthBpp(pScrn, 8, 8, 8, Support24bppFb | + SupportConvert32to24 | PreferConvert32to24); + else + i = xf86SetDepthBpp(pScrn, 8, 8, 8, NoDepth24Support); + + if (!i) + return FALSE; + else { + /* Check that the returned depth is one we support */ + switch (pScrn->depth) { + case 1: + case 4: + case 8: + /* OK */ + break; + case 15: + case 16: + case 24: + if (cPtr->Flags & ChipsHDepthSupport) + break; /* OK */ + /* fall through */ + default: + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Given depth (%d) is not supported by this driver\n", + pScrn->depth); + return FALSE; + } + } + + xf86PrintDepthBpp(pScrn); + + /* Get the depth24 pixmap format */ + if (pScrn->depth == 24 && pix24bpp == 0) + pix24bpp = xf86GetBppFromDepth(pScrn, 24); + + /* + * Allocate a vgaHWRec, this must happen after xf86SetDepthBpp for 1bpp + */ + if (!vgaHWGetHWRec(pScrn)) + return FALSE; + + hwp = VGAHWPTR(pScrn); + vgaHWGetIOBase(hwp); + + /* + * This must happen after pScrn->display has been set because + * xf86SetWeight references it. + */ + if (pScrn->depth > 8) { + /* The defaults are OK for us */ + rgb zeros = {0, 0, 0}; + + if (!xf86SetWeight(pScrn, zeros, zeros)) { + return FALSE; + } else { + /* XXX check that weight returned is supported */ + ; + } + } + + if (!xf86SetDefaultVisual(pScrn, -1)) + return FALSE; + + /* The gamma fields must be initialised when using the new cmap code */ + if (pScrn->depth > 1) { + Gamma zeros = {0.0, 0.0, 0.0}; + + if (!xf86SetGamma(pScrn, zeros)) + return FALSE; + } + + /* Store register values that might be messed up by a suspend resume */ + /* Do this early as some of the other code in PreInit relies on it */ + cPtr->SuspendHack.xr02 = (cPtr->readXR(cPtr, 0x02)) & 0x18; + cPtr->SuspendHack.xr03 = (cPtr->readXR(cPtr, 0x03)) & 0x0A; + cPtr->SuspendHack.xr14 = (cPtr->readXR(cPtr, 0x14)) & 0x20; + cPtr->SuspendHack.xr15 = cPtr->readXR(cPtr, 0x15); + + cPtr->SuspendHack.vgaIOBaseFlag = ((hwp->readMiscOut(hwp)) & 0x01); + cPtr->IOBase = (unsigned int)(cPtr->SuspendHack.vgaIOBaseFlag ? + 0x3D0 : 0x3B0); + + bytesPerPixel = max(1, pScrn->bitsPerPixel >> 3); + + /* Collect all of the relevant option flags (fill in pScrn->options) */ + xf86CollectOptions(pScrn, NULL); + + /* Process the options */ + if (!(cPtr->Options = xalloc(sizeof(ChipsWingineOptions)))) + return FALSE; + memcpy(cPtr->Options, ChipsWingineOptions, sizeof(ChipsWingineOptions)); + xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, cPtr->Options); + + /* Set the bits per RGB */ + if (pScrn->depth > 1) { + /* Default to 6, is this right?? */ + pScrn->rgbBits = 6; +#if 0 + if (xf86GetOptValInteger(cPtr->Options, OPTION_RGB_BITS, + &pScrn->rgbBits)) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Bits per RGB set to %d\n", + pScrn->rgbBits); + } +#endif + } + if ((cPtr->Flags & ChipsAccelSupport) && + (xf86ReturnOptValBool(cPtr->Options, OPTION_NOACCEL, FALSE))) { + cPtr->Flags &= ~ChipsAccelSupport; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n"); + } + + from = X_DEFAULT; + if (pScrn->bitsPerPixel < 8) { + /* Default to SW cursor for 1/4 bpp */ + cPtr->Accel.UseHWCursor = FALSE; + } else { + cPtr->Accel.UseHWCursor = TRUE; + } + if (xf86GetOptValBool(cPtr->Options, OPTION_HW_CURSOR, + &cPtr->Accel.UseHWCursor)) + from = X_CONFIG; + if (xf86GetOptValBool(cPtr->Options, OPTION_SW_CURSOR, + &cPtr->Accel.UseHWCursor)) { + from = X_CONFIG; + cPtr->Accel.UseHWCursor = !cPtr->Accel.UseHWCursor; + } + xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n", + (cPtr->Accel.UseHWCursor) ? "HW" : "SW"); + + /* memory size */ + if (cPtr->pEnt->device->videoRam != 0) { + pScrn->videoRam = cPtr->pEnt->device->videoRam; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "VideoRAM: %d kByte\n", + pScrn->videoRam); + } else { + /* not given, probe it */ + /* XR0F: Software flags 0 */ + /* bit 1-0: memory size */ + /* 0: 256 kB */ + /* 1: 512 kB */ + /* 2: 1024 kB */ + /* 3: 1024 kB */ + + switch ((cPtr->readXR(cPtr, 0x0F)) & 3) { + case 0: + pScrn->videoRam = 256; + break; + case 1: + pScrn->videoRam = 512; + break; + case 2: + pScrn->videoRam = 1024; + break; + case 3: + pScrn->videoRam = 2048; + break; + } + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VideoRAM: %d kByte\n", + pScrn->videoRam); + } + cPtr->FbMapSize = pScrn->videoRam * 1024; + + /* Default to nonlinear for < 8bpp and linear for >= 8bpp. */ + if (cPtr->Flags & ChipsLinearSupport) useLinear = TRUE; + if (pScrn->bitsPerPixel < 8) { + if (!xf86ReturnOptValBool(cPtr->Options, OPTION_LINEAR, FALSE)) { + useLinear = FALSE; + from = X_CONFIG; + } + } else if (!xf86ReturnOptValBool(cPtr->Options, OPTION_LINEAR, TRUE)) { + useLinear = FALSE; + from = X_CONFIG; + } + + /* linear base */ + if (useLinear) { + unsigned char mask = 0xF8; + if (pScrn->videoRam == 1024) + mask = 0xF0; + else if (pScrn->videoRam == 2048) + mask = 0xE0; + if (cPtr->pEnt->device->MemBase) { + cPtr->FbAddress = cPtr->pEnt->device->MemBase + & ((0xFF << 24) | (mask << 16)); + from = X_CONFIG; + } else { + cPtr->FbAddress = ((0xFF & (cPtr->readXR(cPtr, 0x09))) << 24); + cPtr->FbAddress |= ((mask & (cPtr->readXR(cPtr, 0x08))) << 16); + from = X_PROBED; + } + linearRes[0].rBegin = cPtr->FbAddress; + linearRes[0].rEnd = cPtr->FbAddress + 0x800000; + if (xf86RegisterResources(cPtr->pEnt->index,linearRes,ResNone)) { + useLinear = FALSE; + from = X_PROBED; + } + } + + if (useLinear) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Enabling linear addressing\n"); + xf86DrvMsg(pScrn->scrnIndex, from, + "base address is set at 0x%X.\n", cPtr->FbAddress); + if (xf86ReturnOptValBool(cPtr->Options, OPTION_MMIO, FALSE) && + (cPtr->Flags & ChipsMMIOSupport)) { + cPtr->UseMMIO = TRUE; + cPtr->IOAddress = cPtr->FbAddress + 0x200000L; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Enabling MMIO\n"); + } + } else { + if (cPtr->Flags & ChipsLinearSupport) + xf86DrvMsg(pScrn->scrnIndex, from, + "Disabling linear addressing\n"); + cPtr->Flags &= ~ChipsLinearSupport; + } + + if ((s = xf86GetOptValString(cPtr->Options, OPTION_ROTATE)) + || xf86ReturnOptValBool(cPtr->Options, OPTION_SHADOW_FB, FALSE)) { + if (!(cPtr->Flags & ChipsLinearSupport)) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Option \"ShadowFB\" ignored. Not supported without linear addressing\n"); + } else if (pScrn->depth < 8) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Option \"ShadowFB\" ignored. Not supported at this depth.\n"); + } else { + cPtr->Rotate = 0; + if (s) { + if(!xf86NameCmp(s, "CW")) { + /* accel is disabled below for shadowFB */ + cPtr->Flags |= ChipsShadowFB; + cPtr->Rotate = 1; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Rotating screen clockwise\n"); + } else if(!xf86NameCmp(s, "CCW")) { + cPtr->Flags |= ChipsShadowFB; + cPtr->Rotate = -1; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Rotating screen" + "counter clockwise\n"); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"%s\" is not a valid" + "value for Option \"Rotate\"\n", s); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Valid options are \"CW\" or \"CCW\"\n"); + } + } else { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Using \"Shadow Framebuffer\"\n"); + cPtr->Flags |= ChipsShadowFB; + } + } + } + if (cPtr->Flags & ChipsShadowFB) { + if (cPtr->Flags & ChipsAccelSupport) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "HW acceleration is not supported with shadow fb\n"); + cPtr->Flags &= ~ChipsAccelSupport; + } + if (cPtr->Rotate && cPtr->Accel.UseHWCursor) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "HW cursor is not supported with rotate\n"); + cPtr->Accel.UseHWCursor = FALSE; + } + } + + cPtr->PanelType |= ChipsCRT; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "CRT\n"); + + /* monitor info */ + cPtr->Monitor = chipsSetMonitor(pScrn); + + /* bus type */ + tmp = cPtr->readXR(cPtr, 0x01) & 3; + switch (tmp) { + case 0: + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "ISA Bus\n"); + cPtr->Bus = ChipsISA; + break; + case 3: + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VL Bus\n"); + cPtr->Bus = ChipsVLB; + break; + default: + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Unknown Bus\n"); + cPtr->Bus = ChipsUnknown; + break; + } + + /* disable acceleration for 1 and 4 bpp */ + if (pScrn->bitsPerPixel < 8) { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Disabling acceleration for %d bpp\n", pScrn->bitsPerPixel); + cPtr->Flags &= ~ChipsAccelSupport; + } + + /* 32bit register address offsets */ + if ((cPtr->Flags & ChipsAccelSupport) || + (cPtr->Accel.UseHWCursor)) { + cPtr->Regs32 = xnfalloc(sizeof(ChipsReg32)); + tmp = cPtr->readXR(cPtr, 0x07); + for( i = 0; i < (sizeof(ChipsReg32) / sizeof(ChipsReg32[0])); i++) { + cPtr->Regs32[i] = ((ChipsReg32[i] & 0x7E03)) | ((tmp & 0x80) + << 8)| ((tmp & 0x7F) << 2); +#ifdef DEBUG + ErrorF("DR[%X] = %X\n",i,cPtr->Regs32[i]); +#endif + } + linearRes[0].type = ResExcIoSparse | ResBios | ResBus; + linearRes[0].rBase = cPtr->Regs32[0]; + linearRes[0].rMask = 0x83FC; + if (xf86RegisterResources(cPtr->pEnt->index,linearRes,ResNone)) { + if (cPtr->Flags & ChipsAccelSupport) { + cPtr->Flags &= ~ChipsAccelSupport; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Cannot allocate IO registers: " + "Disabling acceleration\n"); + } + if (cPtr->Accel.UseHWCursor) { + cPtr->Accel.UseHWCursor = FALSE; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Cannot allocate IO registers: " + "Disabling HWCursor\n"); + } + } + } + + cPtr->ClockMulFactor = ((pScrn->bitsPerPixel >= 8) ? bytesPerPixel : 1); + if (cPtr->ClockMulFactor != 1) + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Clocks scaled by %d\n", cPtr->ClockMulFactor); + + /* Clock type */ + switch (cPtr->Chipset) { + case CHIPS_CT64200: + NoClocks = 4; + cPtr->ClockType = WINGINE_1_STYLE | TYPE_HW; + break; + default: + if (!((cPtr->readXR(cPtr, 0x01)) & 0x10)) { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Using external clock generator\n"); + NoClocks = 4; + cPtr->ClockType = WINGINE_1_STYLE | TYPE_HW; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Using internal clock generator\n"); + if (xf86ReturnOptValBool(cPtr->Options, OPTION_HW_CLKS, FALSE)) { + NoClocks = 3; + cPtr->ClockType = WINGINE_2_STYLE | TYPE_HW; + } else { + NoClocks = 26; /* some number */ + cPtr->ClockType = WINGINE_2_STYLE | TYPE_PROGRAMMABLE; + pScrn->progClock = TRUE; + } + } + } + + if (cPtr->ClockType & TYPE_PROGRAMMABLE) { + pScrn->numClocks = NoClocks; + if(cPtr->pEnt->device->textClockFreq > 0) { + SaveClk->Clock = cPtr->pEnt->device->textClockFreq; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Using textclock freq: %7.3f.\n", + SaveClk->Clock/1000.0); + } else + SaveClk->Clock = CRT_TEXT_CLK_FREQ; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Using programmable clocks\n"); + } else { /* TYPE_PROGRAMMABLE */ + SaveClk->Clock = chipsGetHWClock(pScrn); + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using textclock clock %i.\n", + SaveClk->Clock); + if (!cPtr->pEnt->device->numclocks) { + pScrn->numClocks = NoClocks; + xf86GetClocks(pScrn, NoClocks, chipsClockSelect, + chipsProtect, chipsBlankScreen, + cPtr->IOBase + 0x0A, 0x08, 1, 28322); + from = X_PROBED; + } else { + pScrn->numClocks = cPtr->pEnt->device->numclocks; + if (pScrn->numClocks > NoClocks) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Too many Clocks specified in configuration file.\n"); + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "\t\tAt most %d clocks may be specified\n", NoClocks); + pScrn->numClocks= NoClocks; + } + for (i = 0; i < pScrn->numClocks; i++) + pScrn->clock[i] = cPtr->pEnt->device->clock[i]; + from = X_CONFIG; + } + xf86ShowClocks(pScrn, from); + } + + /* Set the min pixel clock */ + /* XXX Guess, need to check this */ + cPtr->MinClock = 11000 / cPtr->ClockMulFactor; + xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock is %7.3f MHz\n", + (float)(cPtr->MinClock / 1000.)); + /* maximal clock */ + switch (cPtr->Chipset) { + case CHIPS_CT64200: + cPtr->MaxClock = 80000 / cPtr->ClockMulFactor; + break; + case CHIPS_CT64300: + cPtr->MaxClock = 85000 / cPtr->ClockMulFactor; + break; + } + + if (cPtr->pEnt->device->dacSpeeds[0]) { + int speed = 0; + switch (pScrn->bitsPerPixel) { + case 1: + case 4: + case 8: + speed = cPtr->pEnt->device->dacSpeeds[DAC_BPP8]; + break; + case 16: + speed = cPtr->pEnt->device->dacSpeeds[DAC_BPP16]; + break; + case 24: + speed = cPtr->pEnt->device->dacSpeeds[DAC_BPP24]; + break; + } + if (speed == 0) + cPtr->MaxClock = cPtr->pEnt->device->dacSpeeds[0]; + from = X_CONFIG; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "User max pixel clock of %7.3f MHz overrides %7.3f MHz limit\n", + (float)(cPtr->MaxClock / 1000.), (float)(speed / 1000.)); + cPtr->MaxClock = speed; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Max pixel clock is %7.3f MHz\n", + (float)(cPtr->MaxClock / 1000.)); + } + + if (xf86LoadSubModule(pScrn, "ddc")) { + xf86LoaderReqSymLists(ddcSymbols, NULL); + if (cPtr->pVbe) + xf86SetDDCproperties(pScrn,xf86PrintEDID(vbeDoEDID(cPtr->pVbe, NULL))); + } + return TRUE; +} + +static Bool +chipsPreInit655xx(ScrnInfoPtr pScrn, int flags) +{ + int i, bytesPerPixel, NoClocks = 0; + unsigned char tmp; + MessageType from; + vgaHWPtr hwp; + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSPanelSizePtr Size = &cPtr->PanelSize; + CHIPSClockPtr SaveClk = &(cPtr->SavedReg.Clock); + Bool useLinear = FALSE; + char *s; + resRange linearRes[] = { {ResExcMemBlock|ResBios|ResBus,0,0},_END }; + + /* Set pScrn->monitor */ + pScrn->monitor = pScrn->confScreen->monitor; + + if (cPtr->Flags & ChipsHDepthSupport) + i = xf86SetDepthBpp(pScrn, 8, 8, 8, Support24bppFb | + SupportConvert32to24 | PreferConvert32to24); + else + i = xf86SetDepthBpp(pScrn, 8, 8, 8, NoDepth24Support); + + if (!i) + return FALSE; + else { + /* Check that the returned depth is one we support */ + switch (pScrn->depth) { + case 1: + case 4: + case 8: + /* OK */ + break; + case 15: + case 16: + case 24: + if (cPtr->Flags & ChipsHDepthSupport) + break; /* OK */ + /* fall through */ + default: + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Given depth (%d) is not supported by this driver\n", + pScrn->depth); + return FALSE; + } + } + xf86PrintDepthBpp(pScrn); + + /* Get the depth24 pixmap format */ + if (pScrn->depth == 24 && pix24bpp == 0) + pix24bpp = xf86GetBppFromDepth(pScrn, 24); + + /* + * Allocate a vgaHWRec, this must happen after xf86SetDepthBpp for 1bpp + */ + if (!vgaHWGetHWRec(pScrn)) + return FALSE; + + hwp = VGAHWPTR(pScrn); + vgaHWGetIOBase(hwp); + + /* + * This must happen after pScrn->display has been set because + * xf86SetWeight references it. + */ + if (pScrn->depth > 8) { + /* The defaults are OK for us */ + rgb zeros = {0, 0, 0}; + + if (!xf86SetWeight(pScrn, zeros, zeros)) { + return FALSE; + } else { + /* XXX check that weight returned is supported */ + ; + } + } + + if (!xf86SetDefaultVisual(pScrn, -1)) + return FALSE; + + /* The gamma fields must be initialised when using the new cmap code */ + if (pScrn->depth > 1) { + Gamma zeros = {0.0, 0.0, 0.0}; + + if (!xf86SetGamma(pScrn, zeros)) + return FALSE; + } + + /* Store register values that might be messed up by a suspend resume */ + /* Do this early as some of the other code in PreInit relies on it */ + cPtr->SuspendHack.xr02 = (cPtr->readXR(cPtr, 0x02)) & 0x18; + cPtr->SuspendHack.xr03 = (cPtr->readXR(cPtr, 0x03)) & 0x0A; + cPtr->SuspendHack.xr14 = (cPtr->readXR(cPtr, 0x14)) & 0x20; + cPtr->SuspendHack.xr15 = cPtr->readXR(cPtr, 0x15); + + cPtr->SuspendHack.vgaIOBaseFlag = ((hwp->readMiscOut(hwp)) & 0x01); + cPtr->IOBase = cPtr->SuspendHack.vgaIOBaseFlag ? 0x3D0 : 0x3B0; + + bytesPerPixel = max(1, pScrn->bitsPerPixel >> 3); + + /* Collect all of the relevant option flags (fill in pScrn->options) */ + xf86CollectOptions(pScrn, NULL); + + /* Process the options */ + if (!(cPtr->Options = xalloc(sizeof(Chips655xxOptions)))) + return FALSE; + memcpy(cPtr->Options, Chips655xxOptions, sizeof(Chips655xxOptions)); + xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, cPtr->Options); + + /* Set the bits per RGB */ + if (pScrn->depth > 1) { + /* Default to 6, is this right */ + pScrn->rgbBits = 6; +#if 0 + if (xf86GetOptValInteger(cPtr->Options, OPTION_RGB_BITS, + &pScrn->rgbBits)) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Bits per RGB set to %d\n", + pScrn->rgbBits); + } +#endif + } + if ((cPtr->Flags & ChipsAccelSupport) && + (xf86ReturnOptValBool(cPtr->Options, OPTION_NOACCEL, FALSE))) { + cPtr->Flags &= ~ChipsAccelSupport; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n"); + } + + from = X_DEFAULT; + if (pScrn->bitsPerPixel < 8) { + /* Default to SW cursor for 1/4 bpp */ + cPtr->Accel.UseHWCursor = FALSE; + } else { + cPtr->Accel.UseHWCursor = TRUE; + } + if (xf86GetOptValBool(cPtr->Options, OPTION_HW_CURSOR, + &cPtr->Accel.UseHWCursor)) + from = X_CONFIG; + if (xf86GetOptValBool(cPtr->Options, OPTION_SW_CURSOR, + &cPtr->Accel.UseHWCursor)) { + from = X_CONFIG; + cPtr->Accel.UseHWCursor = !cPtr->Accel.UseHWCursor; + } + xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n", + (cPtr->Accel.UseHWCursor) ? "HW" : "SW"); + + /* memory size */ + if (cPtr->pEnt->device->videoRam != 0) { + pScrn->videoRam = cPtr->pEnt->device->videoRam; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "VideoRAM: %d kByte\n", + pScrn->videoRam); + } else { + /* not given, probe it */ + /* XR0F: Software flags 0 */ + /* bit 1-0: memory size */ + /* 0: 256 kB */ + /* 1: 512 kB */ + /* 2: 1024 kB */ + /* 3: 1024 kB */ + + switch ((cPtr->readXR(cPtr, 0x0F)) & 3) { + case 0: + pScrn->videoRam = 256; + break; + case 1: + pScrn->videoRam = 512; + break; + case 2: + case 3: + pScrn->videoRam = 1024; + break; + } + + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VideoRAM: %d kByte\n", + pScrn->videoRam); + } + cPtr->FbMapSize = pScrn->videoRam * 1024; + + /* Default to nonlinear for < 8bpp and linear for >= 8bpp. */ + if (cPtr->Flags & ChipsLinearSupport) useLinear = TRUE; + if (pScrn->bitsPerPixel < 8) { + if (!xf86ReturnOptValBool(cPtr->Options, OPTION_LINEAR, FALSE)) { + useLinear = FALSE; + from = X_CONFIG; + } + } else if (!xf86ReturnOptValBool(cPtr->Options, OPTION_LINEAR, TRUE)) { + useLinear = FALSE; + from = X_CONFIG; + } + + /* linear base */ + if (useLinear) { + unsigned char mask; + if (cPtr->Chipset == CHIPS_CT65535) { + mask = (pScrn->videoRam > 512) ? 0xF8 :0xFC; + if (cPtr->Bus == ChipsISA) + mask &= 0x7F; + } else if (cPtr->Bus == ChipsISA) { + mask = 0x0F; + } else { + mask = 0xFF; + tmp = cPtr->readXR(cPtr, 0x01); + if(tmp & 0x40) + mask &= 0x3F; + if(!(tmp & 0x80)) + mask &= 0xCF; + } + if (cPtr->pEnt->location.type == BUS_PCI) { + cPtr->FbAddress = cPtr->PciInfo->memBase[0] & 0xff800000; + if (xf86RegisterResources(cPtr->pEnt->index,NULL,ResNone)) + useLinear = FALSE; + from = X_PROBED; + } else { + if (cPtr->pEnt->device->MemBase) { + cPtr->FbAddress = cPtr->pEnt->device->MemBase; + if (cPtr->Chipset == CHIPS_CT65535) + cPtr->FbAddress &= (mask << 17); + else if (cPtr->Chipset > CHIPS_CT65535) + cPtr->FbAddress &= (mask << 20); + from = X_CONFIG; + } else { + if (cPtr->Chipset <= CHIPS_CT65530) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "base address assumed at 0xC00000!\n"); + cPtr->FbAddress = 0xC00000; + from = X_CONFIG; + } else if (cPtr->Chipset == CHIPS_CT65535) { + cPtr->FbAddress = + ((mask & (cPtr->readXR(cPtr, 0x08))) << 17); + } else { + cPtr->FbAddress = + ((mask & (cPtr->readXR(cPtr, 0x08))) << 20); + } + from = X_PROBED; + } + linearRes[0].rBegin = cPtr->FbAddress; + linearRes[0].rEnd = cPtr->FbAddress + 0x800000; + if (xf86RegisterResources(cPtr->pEnt->index,linearRes,ResNone)) { + useLinear = FALSE; + from = X_PROBED; + } + } + } + + if (useLinear) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Enabling linear addressing\n"); + xf86DrvMsg(pScrn->scrnIndex, from, + "base address is set at 0x%X.\n", cPtr->FbAddress); + if (xf86ReturnOptValBool(cPtr->Options, OPTION_MMIO, FALSE) && + (cPtr->Flags & ChipsMMIOSupport)) { + cPtr->UseMMIO = TRUE; + cPtr->IOAddress = cPtr->FbAddress + 0x200000L; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Enabling MMIO\n"); + } + } else { + if (cPtr->Flags & ChipsLinearSupport) + xf86DrvMsg(pScrn->scrnIndex, from, + "Disabling linear addressing\n"); + cPtr->Flags &= ~ChipsLinearSupport; + } + + if ((s = xf86GetOptValString(cPtr->Options, OPTION_ROTATE)) + || xf86ReturnOptValBool(cPtr->Options, OPTION_SHADOW_FB, FALSE)) { + if (!(cPtr->Flags & ChipsLinearSupport)) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Option \"ShadowFB\" ignored. Not supported without linear addressing\n"); + } else if (pScrn->depth < 8) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Option \"ShadowFB\" ignored. Not supported at this depth.\n"); + } else { + cPtr->Rotate = 0; + if (s) { + if(!xf86NameCmp(s, "CW")) { + /* accel is disabled below for shadowFB */ + cPtr->Flags |= ChipsShadowFB; + cPtr->Rotate = 1; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Rotating screen clockwise\n"); + } else if(!xf86NameCmp(s, "CCW")) { + cPtr->Flags |= ChipsShadowFB; + cPtr->Rotate = -1; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Rotating screen" + "counter clockwise\n"); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"%s\" is not a valid" + "value for Option \"Rotate\"\n", s); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Valid options are \"CW\" or \"CCW\"\n"); + } + } else { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Using \"Shadow Framebuffer\"\n"); + cPtr->Flags |= ChipsShadowFB; + } + } + } + if (cPtr->Flags & ChipsShadowFB) { + if (cPtr->Flags & ChipsAccelSupport) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "HW acceleration is not supported with shadow fb\n"); + cPtr->Flags &= ~ChipsAccelSupport; + } + if (cPtr->Rotate && cPtr->Accel.UseHWCursor) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "HW cursor is not supported with rotate\n"); + cPtr->Accel.UseHWCursor = FALSE; + } + } + + /*test STN / TFT */ + tmp = cPtr->readXR(cPtr, 0x51); + + /* XR51 or FR10: DISPLAY TYPE REGISTER */ + /* XR51[1-0] or FR10[1:0] for ct65550 : PanelType, */ + /* 0 = Single Panel Single Drive, 3 = Dual Panel Dual Drive */ + switch (tmp & 0x3) { + case 0: + if (xf86ReturnOptValBool(cPtr->Options, OPTION_STN, FALSE)) { + cPtr->PanelType |= ChipsSS; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "SS-STN probed\n"); + } else { + cPtr->PanelType |= ChipsTFT; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "TFT probed\n"); + } + break; + case 2: + cPtr->PanelType |= ChipsDS; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DS-STN probed\n"); + case 3: + cPtr->PanelType |= ChipsDD; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DD-STN probed\n"); + break; + default: + break; + } + + chipsSetPanelType(cPtr); + from = X_PROBED; + { + Bool fp_mode; + if (xf86GetOptValBool(cPtr->Options, OPTION_FP_MODE, &fp_mode)) { + if (fp_mode) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forcing FP Mode on\n"); + cPtr->PanelType |= ChipsLCD; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forcing FP Mode off\n"); + cPtr->PanelType = ~ChipsLCD; + } + from = X_CONFIG; + } + } + if ((cPtr->PanelType & ChipsLCD) && (cPtr->PanelType & ChipsCRT)) + xf86DrvMsg(pScrn->scrnIndex, from, "LCD/CRT\n"); + else if (cPtr->PanelType & ChipsLCD) + xf86DrvMsg(pScrn->scrnIndex, from, "LCD\n"); + else if (cPtr->PanelType & ChipsCRT) { + xf86DrvMsg(pScrn->scrnIndex, from, "CRT\n"); + /* monitor info */ + cPtr->Monitor = chipsSetMonitor(pScrn); + } + + /* screen size */ + /* + * In LCD mode / dual mode we want to derive the timing values from + * the ones preset by bios + */ + if (cPtr->PanelType & ChipsLCD) { + unsigned char xr17, tmp1; + char tmp2; + + xr17 = cPtr->readXR(cPtr, 0x17); + tmp = cPtr->readXR(cPtr, 0x1B); + Size->HTotal =((tmp + ((xr17 & 0x01) << 8)) + 5) << 3; + tmp = cPtr->readXR(cPtr, 0x1C); + Size->HDisplay = ((tmp + ((xr17 & 0x02) << 7)) + 1) << 3; + tmp = cPtr->readXR(cPtr, 0x19); + Size->HRetraceStart = ((tmp + ((xr17 & 0x04) << 9)) + 1) << 3; + tmp1 = cPtr->readXR(cPtr, 0x1A); + tmp2 = (tmp1 & 0x1F) + ((xr17 & 0x08) << 2) - (tmp & 0x3F); + Size->HRetraceEnd = ((((tmp2 < 0) ? (tmp2 + 0x40) : tmp2) << 3) + + Size->HRetraceStart); + tmp1 = cPtr->readXR(cPtr, 0x65); + tmp = cPtr->readXR(cPtr, 0x68); + Size->VDisplay = ((tmp1 & 0x02) << 7) + + ((tmp1 & 0x40) << 3) + tmp + 1; + tmp = cPtr->readXR(cPtr, 0x66); + Size->VRetraceStart = ((tmp1 & 0x04) << 6) + + ((tmp1 & 0x80) << 2) + tmp + 1; + tmp = cPtr->readXR(cPtr, 0x64); + Size->VTotal = ((tmp1 & 0x01) << 8) + + ((tmp1 & 0x20) << 4) + tmp + 2; +#ifdef DEBUG + ErrorF("x=%i, y=%i; xSync=%i, xSyncEnd=%i, xTotal=%i\n", + Size->HDisplay, Size->VDisplay, + Size->HRetraceStart, Size->HRetraceEnd, + Size->HTotal); +#endif + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Display Size: x=%i; y=%i\n", + Size->HDisplay, Size->VDisplay); + /* Warn the user if the panel size has been overridden by + * the modeline values + */ + if (xf86ReturnOptValBool(cPtr->Options, OPTION_PANEL_SIZE, FALSE)) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Display size overridden by modelines.\n"); + } + } + + /* Frame Buffer */ /* for LCDs */ + if (IS_STN(cPtr->PanelType)) { + tmp = cPtr->readXR(cPtr, 0x6F); /*Frame Buffer Ctrl. */ + if (tmp & 1) { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Frame Buffer used\n"); + if ((cPtr->Chipset > CHIPS_CT65530) && !(tmp & 0x80)) { + /* Formula for calculating the size of the framebuffer. 3 + * bits per pixel 10 pixels per 32 bit dword. If frame + * acceleration is enabled the size can be halved. + */ + cPtr->FrameBufferSize = ( Size->HDisplay * + Size->VDisplay / 5 ) * ((tmp & 2) ? 1 : 2); + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Using embedded Frame Buffer, size %d bytes\n", + cPtr->FrameBufferSize); + } else + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Using external Frame Buffer used\n"); + } + if (tmp & 2) + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Frame accelerator enabled\n"); + } + + /* bus type */ + if (cPtr->Chipset > CHIPS_CT65535) { + tmp = (cPtr->readXR(cPtr, 0x01)) & 7; + if (tmp == 6) { /*PCI */ + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "PCI Bus\n"); + cPtr->Bus = ChipsPCI; + if ((cPtr->Chipset == CHIPS_CT65545) || + (cPtr->Chipset == CHIPS_CT65546)) { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "32Bit IO not supported on 65545 PCI\n"); + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "\tenabling MMIO\n"); + cPtr->UseMMIO = TRUE; + cPtr->IOAddress = cPtr->FbAddress + 0x200000L; + } + + } else { /* XR08: Linear addressing base, not for PCI */ + switch (tmp) { + case 3: + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "CPU Direct\n"); + cPtr->Bus = ChipsCPUDirect; + break; + case 5: + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "ISA Bus\n"); + cPtr->Bus = ChipsISA; + break; + case 7: + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VL Bus\n"); + cPtr->Bus = ChipsVLB; + break; + default: + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Unknown Bus\n"); + } + } + } else { + tmp = (cPtr->readXR(cPtr, 0x01)) & 3; + switch (tmp) { + case 0: + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "PI Bus\n"); + cPtr->Bus = ChipsPIB; + break; + case 1: + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "MC Bus\n"); + cPtr->Bus = ChipsMCB; + break; + case 2: + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VL Bus\n"); + cPtr->Bus = ChipsVLB; + break; + case 3: + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "ISA Bus\n"); + cPtr->Bus = ChipsISA; + break; + } + } + + if (!(cPtr->Bus == ChipsPCI) && (cPtr->UseMMIO)) { + cPtr->UseMMIO = FALSE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "MMIO only supported on PCI Bus. Disabling MMIO\n"); + } + + /* disable acceleration for 1 and 4 bpp */ + if (pScrn->bitsPerPixel < 8) { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Disabling acceleration for %d bpp\n", pScrn->bitsPerPixel); + cPtr->Flags &= ~ChipsAccelSupport; + } + + if ((cPtr->Chipset == CHIPS_CT65530) && + (cPtr->Flags & ChipsLinearSupport)) { + /* linear mode is no longer default on ct65530 since it */ + /* requires additional hardware which some manufacturers*/ + /* might not provide. */ + if (!xf86ReturnOptValBool(cPtr->Options, OPTION_LINEAR, FALSE)) + cPtr->Flags &= ~ChipsLinearSupport; + + /* Test wether linear addressing is possible on 65530 */ + /* on the 65530 only the A19 select scheme can be used*/ + /* for linear addressing since MEMW is used on ISA bus*/ + /* systems. */ + /* A19 however is used if video memory is > 512 Mb */ + if ((cPtr->Bus == ChipsISA) && (pScrn->videoRam > 512)) { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "User selected linear fb not supported by HW!\n"); + cPtr->Flags &= ~ChipsLinearSupport; + } + } + + /* DAC info */ + if ((cPtr->readXR(cPtr, 0x06)) & 0x02) + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Internal DAC disabled\n"); + + /* MMIO address offset */ + if (cPtr->UseMMIO) + cPtr->Regs32 = ChipsReg32; + else if ((cPtr->Flags & ChipsAccelSupport) || + (cPtr->Accel.UseHWCursor)) { + cPtr->Regs32 = xnfalloc(sizeof(ChipsReg32)); + tmp = cPtr->readXR(cPtr, 0x07); + for (i = 0; i < (sizeof(ChipsReg32)/sizeof(ChipsReg32[0])); i++) { + cPtr->Regs32[i] = + ((ChipsReg32[i] & 0x7E03)) | ((tmp & 0x80)<< 8) + | ((tmp & 0x7F) << 2); +#ifdef DEBUG + ErrorF("DR[%X] = %X\n",i,cPtr->Regs32[i]); +#endif + } + linearRes[0].type = ResExcIoSparse | ResBios | ResBus; + linearRes[0].rBase = cPtr->Regs32[0]; + linearRes[0].rMask = 0x83FC; + if (xf86RegisterResources(cPtr->pEnt->index,linearRes,ResNone)) { + if (cPtr->Flags & ChipsAccelSupport) { + cPtr->Flags &= ~ChipsAccelSupport; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Cannot allocate IO registers: " + "Disabling acceleration\n"); + } + if (cPtr->Accel.UseHWCursor) { + cPtr->Accel.UseHWCursor = FALSE; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Cannot allocate IO registers: " + "Disabling HWCursor\n"); + } + } + } + + /* sync reset ignored on this chipset */ + if (cPtr->Chipset > CHIPS_CT65530) { + tmp = cPtr->readXR(cPtr, 0x0E); + if (tmp & 0x80) + cPtr->SyncResetIgn = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Synchronous reset %signored.\n", + (cPtr->SyncResetIgn ? "" : "not ")); + } + + cPtr->ClockMulFactor = ((pScrn->bitsPerPixel >= 8) ? bytesPerPixel : 1); + if (cPtr->ClockMulFactor != 1) + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Clocks scaled by %d\n", cPtr->ClockMulFactor); + /* We use a programmable clock */ + switch (cPtr->Chipset) { + case CHIPS_CT65520: + case CHIPS_CT65525: + case CHIPS_CT65530: + NoClocks = 4; /* Some number */ + cPtr->ClockType = OLD_STYLE | TYPE_HW; + break; + default: + if (xf86ReturnOptValBool(cPtr->Options, OPTION_HW_CLKS, FALSE)) { + NoClocks = 5; /* Some number */ + cPtr->ClockType = NEW_STYLE | TYPE_HW; + } else { + NoClocks = 26; /* Some number */ + cPtr->ClockType = NEW_STYLE | TYPE_PROGRAMMABLE; + pScrn->progClock = TRUE; + } + } + + if (cPtr->ClockType & TYPE_PROGRAMMABLE) { + pScrn->numClocks = NoClocks; + if (cPtr->pEnt->device->textClockFreq > 0) { + SaveClk->Clock = cPtr->pEnt->device->textClockFreq; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Using textclock freq: %7.3f.\n", + SaveClk->Clock/1000.0); + } else + SaveClk->Clock = ((cPtr->PanelType & ChipsLCDProbed) ? + LCD_TEXT_CLK_FREQ : CRT_TEXT_CLK_FREQ); + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Using programmable clocks\n"); + } else { /* TYPE_PROGRAMMABLE */ + SaveClk->Clock = chipsGetHWClock(pScrn); + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using textclock clock %i.\n", + SaveClk->Clock); + if (!cPtr->pEnt->device->numclocks) { + pScrn->numClocks = NoClocks; + xf86GetClocks(pScrn, NoClocks, chipsClockSelect, + chipsProtect, chipsBlankScreen, + cPtr->IOBase + 0x0A, 0x08, 1, 28322); + from = X_PROBED; + } else { + pScrn->numClocks = cPtr->pEnt->device->numclocks; + if (pScrn->numClocks > NoClocks) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Too many Clocks specified in configuration file.\n"); + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "\t\tAt most %d clocks may be specified\n", NoClocks); + pScrn->numClocks = NoClocks; + } + for (i = 0; i < pScrn->numClocks; i++) + pScrn->clock[i] = cPtr->pEnt->device->clock[i]; + from = X_CONFIG; + } + xf86ShowClocks(pScrn, from); + } + /* Set the min pixel clock */ + /* XXX Guess, need to check this */ + cPtr->MinClock = 11000 / cPtr->ClockMulFactor; + xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock is %7.3f MHz\n", + (float)(cPtr->MinClock / 1000.)); + /* Set the max pixel clock */ + switch (cPtr->Chipset) { + case CHIPS_CT65546: + case CHIPS_CT65548: + /* max VCLK is 80 MHz, max MCLK is 75 MHz for CT65548 */ + /* It is not sure for CT65546, but it works with 60 nsec EDODRAM */ + cPtr->MaxClock = 80000 / cPtr->ClockMulFactor; + break; + default: + if ((cPtr->readXR(cPtr, 0x6C)) & 2) { + /*5V Vcc */ + cPtr->MaxClock = 68000 / cPtr->ClockMulFactor; + } else { + /*3.3V Vcc */ + cPtr->MaxClock = 56000 / cPtr->ClockMulFactor; + } + } + + if (cPtr->pEnt->device->dacSpeeds[0]) { + int speed = 0; + switch (pScrn->bitsPerPixel) { + case 1: + case 4: + case 8: + speed = cPtr->pEnt->device->dacSpeeds[DAC_BPP8]; + break; + case 16: + speed = cPtr->pEnt->device->dacSpeeds[DAC_BPP16]; + break; + case 24: + speed = cPtr->pEnt->device->dacSpeeds[DAC_BPP24]; + break; + } + if (speed == 0) + cPtr->MaxClock = cPtr->pEnt->device->dacSpeeds[0]; + from = X_CONFIG; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "User max pixel clock of %7.3f MHz overrides %7.3f MHz limit\n", + (float)(cPtr->MaxClock / 1000.), (float)(speed / 1000.)); + cPtr->MaxClock = speed; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Max pixel clock is %7.3f MHz\n", + (float)(cPtr->MaxClock / 1000.)); + } + + /* FP clock */ + if (cPtr->ClockType & TYPE_PROGRAMMABLE) { + double real = 0; + + switch(bytesPerPixel) { + case 1: + xf86GetOptValFreq(cPtr->Options, OPTION_FP_CLOCK_8, + OPTUNITS_MHZ, &real); + break; + case 2: + xf86GetOptValFreq(cPtr->Options, OPTION_FP_CLOCK_16, + OPTUNITS_MHZ, &real); + break; + case 3: + xf86GetOptValFreq(cPtr->Options, OPTION_FP_CLOCK_24, + OPTUNITS_MHZ, &real); + break; + } + + if (real > 0) { + int val; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "FP clock %7.3f MHz requested\n",real); + val = (int) (real * 1000.); + if (val && (val >= cPtr->MinClock) + && (val <= cPtr->MaxClock)) + cPtr->FPclock = val * cPtr->ClockMulFactor; + else if (val > cPtr->MaxClock) + cPtr->FPclock = (int)((float)cPtr->MaxClock + * cPtr->ClockMulFactor * 0.9); + else + cPtr->FPclock = 0; /* special value */ + } else + cPtr->FPclock = 0; /* special value */ + + if (cPtr->FPclock) + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "FP clock set to %7.3f MHz\n", + (float)(cPtr->FPclock / 1000.)); + } else { + if (xf86IsOptionSet(cPtr->Options, OPTION_SET_MCLK)) + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "FP clock option not supported for this chipset\n"); + } + + /* Memory Clock */ + if (cPtr->ClockType & TYPE_PROGRAMMABLE) { + double real; + + switch (cPtr->Chipset) { + case CHIPS_CT65546: + case CHIPS_CT65548: + /* max MCLK is 75 MHz for CT65548 */ + cPtr->MemClock.Max = 75000; + break; + default: + if ((cPtr->readXR(cPtr, 0x6C)) & 2) { + /*5V Vcc */ + cPtr->MemClock.Max = 68000; + } else { + /*3.3V Vcc */ + cPtr->MemClock.Max = 56000; + } + } + + if (xf86GetOptValFreq(cPtr->Options, OPTION_SET_MCLK, + OPTUNITS_MHZ, &real)) { + int mclk = (int)(real * 1000.0); + if (mclk <= cPtr->MemClock.Max) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Using memory clock of %7.3f MHz\n", + (float)(mclk/1000.)); + cPtr->MemClock.Clk = mclk; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Memory clock of %7.3f MHz exceeds limit of " + "%7.3f MHz\n",(float)(mclk/1000.), + (float)(cPtr->MemClock.Max/1000.)); + cPtr->MemClock.Clk = cPtr->MemClock.Max * 0.9; + } + } else + cPtr->MemClock.Clk = 0; + } else + if (xf86IsOptionSet(cPtr->Options, OPTION_SET_MCLK)) + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Memory clock option not supported for this chipset\n"); + + if (xf86LoadSubModule(pScrn, "ddc")) { + xf86LoaderReqSymLists(ddcSymbols, NULL); + if (cPtr->pVbe) + xf86SetDDCproperties(pScrn,xf86PrintEDID(vbeDoEDID(cPtr->pVbe, NULL))); + } + return TRUE; +} + + +/* Mandatory */ +static Bool +CHIPSEnterVT(int scrnIndex, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSEntPtr cPtrEnt; + + if (cPtr->Flags & ChipsDualChannelSupport) { + cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0], + CHIPSEntityIndex)->ptr; + DUALOPEN; + } + /* Should we re-save the text mode on each VT enter? */ + if(!chipsModeInit(pScrn, pScrn->currentMode)) + return FALSE; + if ((!(cPtr->Flags & ChipsOverlay8plus16)) + && (cPtr->Flags & ChipsVideoSupport) + && (cPtr->Flags & ChipsLinearSupport)) + CHIPSResetVideo(pScrn); + + /*xf86UDelay(50000);*/ + chipsHWCursorOn(cPtr, pScrn); + /* cursor settle delay */ + xf86UDelay(50000); + CHIPSAdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); + xf86UDelay(50000); + return TRUE; +} + +/* Mandatory */ +static void +CHIPSLeaveVT(int scrnIndex, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSACLPtr cAcl = CHIPSACLPTR(pScrn); + CHIPSEntPtr cPtrEnt; + + /* Invalidate the cached acceleration registers */ + cAcl->planemask = -1; + cAcl->fgColor = -1; + cAcl->bgColor = -1; + + if (cPtr->Flags & ChipsDualChannelSupport) { + cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0], + CHIPSEntityIndex)->ptr; + if (cPtr->UseDualChannel) + DUALREOPEN; + DUALCLOSE; + } else { + chipsHWCursorOff(cPtr, pScrn); + chipsRestore(pScrn, &(VGAHWPTR(pScrn))->SavedReg, &cPtr->SavedReg, + TRUE); + chipsLock(pScrn); + } +} + + +static void +chipsLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors, + VisualPtr pVisual) +{ + vgaHWPtr hwp = VGAHWPTR(pScrn); + CHIPSPtr cPtr = CHIPSPTR(pScrn); + int i, index, shift ; + CHIPSEntPtr cPtrEnt; + + shift = ((pScrn->depth == 15) && + (!(cPtr->Flags & ChipsOverlay8plus16))) ? 3 : 0; + + if (cPtr->UseDualChannel) { + cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0], + CHIPSEntityIndex)->ptr; + DUALREOPEN; + } + + for (i = 0; i < numColors; i++) { + index = indices[i]; + hwp->writeDacWriteAddr(hwp,index << shift); + DACDelay(hwp); + hwp->writeDacData(hwp, colors[index].red); + DACDelay(hwp); + hwp->writeDacData(hwp, colors[index].green); + DACDelay(hwp); + hwp->writeDacData(hwp, colors[index].blue); + DACDelay(hwp); + } + + if (cPtr->UseDualChannel && + (! xf86IsEntityShared(pScrn->entityList[0]))) { + unsigned int IOSS, MSS; + IOSS = cPtr->readIOSS(cPtr); + MSS = cPtr->readMSS(cPtr); + cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) | + IOSS_PIPE_B)); + cPtr->writeMSS(cPtr, hwp, ((cPtr->storeMSS & MSS_MASK) | MSS_PIPE_B)); + + for (i = 0; i < numColors; i++) { + index = indices[i]; + hwp->writeDacWriteAddr(hwp,index << shift); + DACDelay(hwp); + hwp->writeDacData(hwp, colors[index].red); + DACDelay(hwp); + hwp->writeDacData(hwp, colors[index].green); + DACDelay(hwp); + hwp->writeDacData(hwp, colors[index].blue); + DACDelay(hwp); + } + cPtr->writeIOSS(cPtr, IOSS); + cPtr->writeMSS(cPtr, hwp, MSS); + } + + /* This shouldn't be necessary, but we'll play safe. */ + hwp->disablePalette(hwp); +} + +static void +chipsLoadPalette16(ScrnInfoPtr pScrn, int numColors, int *indices, + LOCO *colors, VisualPtr pVisual) +{ + vgaHWPtr hwp = VGAHWPTR(pScrn); + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSEntPtr cPtrEnt; + + int i, index; + + if (cPtr->UseDualChannel) { + cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0], + CHIPSEntityIndex)->ptr; + DUALREOPEN; + } + + for (i = 0; i < numColors; i++) { + index = indices[i]; + hwp->writeDacWriteAddr(hwp, index << 2); + DACDelay(hwp); + hwp->writeDacData(hwp, colors[index >> 1].red); + DACDelay(hwp); + hwp->writeDacData(hwp, colors[index].green); + DACDelay(hwp); + hwp->writeDacData(hwp, colors[index >> 1].blue); + DACDelay(hwp); + } + + + if (cPtr->UseDualChannel && + (! xf86IsEntityShared(pScrn->entityList[0]))) { + unsigned int IOSS, MSS; + IOSS = cPtr->readIOSS(cPtr); + MSS = cPtr->readMSS(cPtr); + cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) | + IOSS_PIPE_B)); + cPtr->writeMSS(cPtr, hwp, ((cPtr->storeMSS & MSS_MASK) | MSS_PIPE_B)); + + for (i = 0; i < numColors; i++) { + index = indices[i]; + hwp->writeDacWriteAddr(hwp, index << 2); + DACDelay(hwp); + hwp->writeDacData(hwp, colors[index >> 1].red); + DACDelay(hwp); + hwp->writeDacData(hwp, colors[index].green); + DACDelay(hwp); + hwp->writeDacData(hwp, colors[index >> 1].blue); + DACDelay(hwp); + } + + cPtr->writeIOSS(cPtr, IOSS); + cPtr->writeMSS(cPtr, hwp, MSS); + } + + /* This shouldn't be necessary, but we'll play safe. */ + hwp->disablePalette(hwp); +} + +/* Mandatory */ +static Bool +CHIPSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + vgaHWPtr hwp; + CHIPSPtr cPtr; + CHIPSACLPtr cAcl; + int ret; + int init_picture = 0; + VisualPtr visual; + int allocatebase, freespace, currentaddr; + unsigned int racflag = 0; + unsigned char *FBStart; + int height, width, displayWidth; + CHIPSEntPtr cPtrEnt = NULL; +#ifdef DEBUG + ErrorF("CHIPSScreenInit\n"); +#endif + + /* + * we need to get the ScrnInfoRec for this screen, so let's allocate + * one first thing + */ + cPtr = CHIPSPTR(pScrn); + cAcl = CHIPSACLPTR(pScrn); + + hwp = VGAHWPTR(pScrn); + hwp->MapSize = 0x10000; /* Standard 64k VGA window */ + + /* Map the VGA memory */ + if (!vgaHWMapMem(pScrn)) + return FALSE; + + /* Map the Chips memory and possible MMIO areas */ + if (!chipsMapMem(pScrn)) + return FALSE; + + /* Setup a pointer to the overlay if needed */ + if (cPtr->Flags & ChipsOverlay8plus16) { + cPtr->FbOffset16 = pScrn->displayWidth * pScrn->virtualY; + cPtr->FbSize16 = (pScrn->displayWidth << 1) * pScrn->virtualY; + if (cPtr->FbSize16 > (cPtr->FbMapSize - cPtr->FrameBufferSize)) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Too little memory for overlay. Disabling.\n"); + cPtr->Flags &= ~ChipsOverlay8plus16; + } + if ((pScrn->displayWidth > 1024) || (pScrn->virtualY > 1024)) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Max overlay Width/Height 1024 pixels. Disabling.\n"); + cPtr->Flags &= ~ChipsOverlay8plus16; + } + } + + /* Setup the MMIO register access functions if need */ + if (cPtr->UseFullMMIO && cPtr->MMIOBaseVGA) { + CHIPSSetMmioExtFuncs(cPtr); + CHIPSHWSetMmioFuncs(pScrn, cPtr->MMIOBaseVGA, 0x0); + } + + if (cPtr->Flags & ChipsDualChannelSupport) { + cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0], + CHIPSEntityIndex)->ptr; + DUALOPEN; + } + +#if defined(__arm32__) && defined(__NetBSD__) + if (strcmp(pScrn->currentMode->name,"PAL") == 0) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using built-in PAL TV mode\n"); + cPtr->TVMode = XMODE_PAL; + } else if (strcmp(pScrn->currentMode->name,"SECAM") == 0){ + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Using built-in SECAM TV mode\n"); + cPtr->TVMode = XMODE_SECAM; + } else if (strcmp(pScrn->currentMode->name,"NTSC") == 0) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Using built-in NTSC TV mode\n"); + cPtr->TVMode = XMODE_NTSC; + } else + cPtr->TVMode = XMODE_RGB; +#endif + + /* + * next we save the current state and setup the first mode + */ + if ((cPtr->Flags & ChipsDualChannelSupport) && + (! xf86IsEntityShared(pScrn->entityList[0]))) { + unsigned int IOSS, MSS; + IOSS = cPtr->readIOSS(cPtr); + MSS = cPtr->readMSS(cPtr); + cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) | + IOSS_PIPE_A)); + cPtr->writeMSS(cPtr, hwp, ((cPtr->storeMSS & MSS_MASK) | MSS_PIPE_A)); + chipsSave(pScrn, &hwp->SavedReg, &cPtr->SavedReg); + cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) | + IOSS_PIPE_B)); + cPtr->writeMSS(cPtr, hwp, ((cPtr->storeMSS & MSS_MASK) | MSS_PIPE_B)); + chipsSave(pScrn, &cPtr->VgaSavedReg2, &cPtr->SavedReg2); + cPtr->writeIOSS(cPtr, IOSS); + cPtr->writeMSS(cPtr, hwp, MSS); + } else + chipsSave(pScrn, &hwp->SavedReg, &cPtr->SavedReg); + + if (!chipsModeInit(pScrn,pScrn->currentMode)) + return FALSE; + CHIPSSaveScreen(pScreen,SCREEN_SAVER_ON); + CHIPSAdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); + + /* + * The next step is to setup the screen's visuals, and initialise the + * framebuffer code. In cases where the framebuffer's default + * choices for things like visual layouts and bits per RGB are OK, + * this may be as simple as calling the framebuffer's ScreenInit() + * function. If not, the visuals will need to be setup before calling + * a fb ScreenInit() function and fixed up after. + * + * For most PC hardware at depths >= 8, the defaults that cfb uses + * are not appropriate. In this driver, we fixup the visuals after. + */ + + /* + * Reset visual list. + */ + miClearVisualTypes(); + + /* Setup the visuals we support. */ + if ((pScrn->bitsPerPixel == 16) && (cPtr->Flags & ChipsOverlay8plus16)){ + if (!miSetVisualTypes(8, PseudoColorMask | GrayScaleMask, + pScrn->rgbBits, PseudoColor)) + return FALSE; + if (!miSetVisualTypes(16, TrueColorMask, pScrn->rgbBits, TrueColor)) + return FALSE; + } else { + if (!miSetVisualTypes(pScrn->depth, + miGetDefaultVisualMask(pScrn->depth), + pScrn->rgbBits, pScrn->defaultVisual)) + return FALSE; + } + miSetPixmapDepths (); + + /* + * Call the framebuffer layer's ScreenInit function, and fill in other + * pScreen fields. + */ + if ((cPtr->Flags & ChipsShadowFB) && cPtr->Rotate) { + height = pScrn->virtualX; + width = pScrn->virtualY; + } else { + width = pScrn->virtualX; + height = pScrn->virtualY; + } + + if(cPtr->Flags & ChipsShadowFB) { + cPtr->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width); + cPtr->ShadowPtr = xalloc(cPtr->ShadowPitch * height); + displayWidth = cPtr->ShadowPitch / (pScrn->bitsPerPixel >> 3); + FBStart = cPtr->ShadowPtr; + } else { + cPtr->ShadowPtr = NULL; + displayWidth = pScrn->displayWidth; + FBStart = cPtr->FbBase; + } + + switch (pScrn->bitsPerPixel) { + case 1: + ret = xf1bppScreenInit(pScreen, FBStart, + width,height, + pScrn->xDpi, pScrn->yDpi, + displayWidth); + break; + case 4: + ret = xf4bppScreenInit(pScreen, FBStart, + width,height, + pScrn->xDpi, pScrn->yDpi, + displayWidth); + break; + case 16: + if (cPtr->Flags & ChipsOverlay8plus16) { + ret = cfb8_16ScreenInit(pScreen, (unsigned char *)FBStart + + cPtr->FbOffset16, FBStart, width, + height, pScrn->xDpi, pScrn->yDpi, + displayWidth, displayWidth); + break; + } + default: + ret = fbScreenInit(pScreen, FBStart, + width,height, + pScrn->xDpi, pScrn->yDpi, + displayWidth,pScrn->bitsPerPixel); + init_picture = 1; + break; + } + + if (!ret) + return FALSE; + + if (pScrn->depth > 8) { + /* Fixup RGB ordering */ + visual = pScreen->visuals + pScreen->numVisuals; + while (--visual >= pScreen->visuals) { + if ((visual->class | DynamicClass) == DirectColor) { + visual->offsetRed = pScrn->offset.red; + visual->offsetGreen = pScrn->offset.green; + visual->offsetBlue = pScrn->offset.blue; + visual->redMask = pScrn->mask.red; + visual->greenMask = pScrn->mask.green; + visual->blueMask = pScrn->mask.blue; + } + } + } + + /* must be after RGB ordering fixed */ + if (init_picture) + fbPictureInit (pScreen, 0, 0); + + xf86SetBlackWhitePixels(pScreen); + + cPtr->BlockHandler = pScreen->BlockHandler; + pScreen->BlockHandler = chipsBlockHandler; + + if ( (pScrn->depth >= 8)) + CHIPSDGAInit(pScreen); + + cPtr->HWCursorShown = FALSE; + + if (!(cPtr->Flags & ChipsLinearSupport)) { + miBankInfoPtr pBankInfo; + + /* Setup the vga banking variables */ + pBankInfo = (miBankInfoPtr)xnfcalloc(sizeof(miBankInfoRec),1); + if (pBankInfo == NULL) + return FALSE; + +#if defined(__arm32__) + cPtr->Bank = -1; +#endif + pBankInfo->pBankA = hwp->Base; + pBankInfo->pBankB = (unsigned char *)hwp->Base + 0x08000; + pBankInfo->BankSize = 0x08000; + pBankInfo->nBankDepth = (pScrn->depth == 4) ? 1 : pScrn->depth; + + if (IS_HiQV(cPtr)) { + pBankInfo->pBankB = hwp->Base; + pBankInfo->BankSize = 0x10000; + if (pScrn->bitsPerPixel < 8) { + pBankInfo->SetSourceBank = + (miBankProcPtr)CHIPSHiQVSetReadWritePlanar; + pBankInfo->SetDestinationBank = + (miBankProcPtr)CHIPSHiQVSetReadWritePlanar; + pBankInfo->SetSourceAndDestinationBanks = + (miBankProcPtr)CHIPSHiQVSetReadWritePlanar; + } else { + pBankInfo->SetSourceBank = + (miBankProcPtr)CHIPSHiQVSetReadWrite; + pBankInfo->SetDestinationBank = + (miBankProcPtr)CHIPSHiQVSetReadWrite; + pBankInfo->SetSourceAndDestinationBanks = + (miBankProcPtr)CHIPSHiQVSetReadWrite; + } + } else { + if (IS_Wingine(cPtr)) { + if (pScrn->bitsPerPixel < 8) { + pBankInfo->SetSourceBank = + (miBankProcPtr)CHIPSWINSetReadPlanar; + pBankInfo->SetDestinationBank = + (miBankProcPtr)CHIPSWINSetWritePlanar; + pBankInfo->SetSourceAndDestinationBanks = + (miBankProcPtr)CHIPSWINSetReadWritePlanar; + } else { + pBankInfo->SetSourceBank = (miBankProcPtr)CHIPSWINSetRead; + pBankInfo->SetDestinationBank = + (miBankProcPtr)CHIPSWINSetWrite; + pBankInfo->SetSourceAndDestinationBanks = + (miBankProcPtr)CHIPSWINSetReadWrite; + } + } else { + if (pScrn->bitsPerPixel < 8) { + pBankInfo->SetSourceBank = + (miBankProcPtr)CHIPSSetReadPlanar; + pBankInfo->SetDestinationBank = + (miBankProcPtr)CHIPSSetWritePlanar; + pBankInfo->SetSourceAndDestinationBanks = + (miBankProcPtr)CHIPSSetReadWritePlanar; + } else { + pBankInfo->SetSourceBank = (miBankProcPtr)CHIPSSetRead; + pBankInfo->SetDestinationBank = + (miBankProcPtr)CHIPSSetWrite; + pBankInfo->SetSourceAndDestinationBanks = + (miBankProcPtr)CHIPSSetReadWrite; + } + } + } + if (!miInitializeBanking(pScreen, pScrn->virtualX, pScrn->virtualY, + pScrn->displayWidth, pBankInfo)) { + xfree(pBankInfo); + pBankInfo = NULL; + return FALSE; + } + miInitializeBackingStore(pScreen); + xf86SetBackingStore(pScreen); + + /* Initialise cursor functions */ + miDCInitialize (pScreen, xf86GetPointerScreenFuncs()); + + } else { + /* !!! Only support linear addressing for now. This might change */ + /* Setup pointers to free space in video ram */ +#define CHIPSALIGN(size, align) (currentaddr - ((currentaddr - size) & ~align)) + allocatebase = (pScrn->videoRam<<10) - cPtr->FrameBufferSize; + + if (pScrn->bitsPerPixel < 8) + freespace = allocatebase - pScrn->displayWidth * + pScrn->virtualY / 2; + else if ((pScrn->bitsPerPixel == 16) && (cPtr->Flags & ChipsOverlay8plus16)) + freespace = allocatebase - pScrn->displayWidth * + pScrn->virtualY - cPtr->FbSize16; + else + freespace = allocatebase - pScrn->displayWidth * + pScrn->virtualY * (pScrn->bitsPerPixel >> 3); + + if ((cPtr->Flags & ChipsDualChannelSupport) && + (cPtr->SecondCrtc == TRUE)) { + currentaddr = allocatebase + cPtrEnt->masterFbMapSize; + } else + currentaddr = allocatebase; + if (serverGeneration == 1) + xf86DrvMsg(scrnIndex, X_PROBED, + "%d bytes off-screen memory available\n", freespace); + + /* + * Allocate video memory to store the hardware cursor. Allocate 1kB + * vram to the cursor, with 1kB alignment for 6554x's and 4kb alignment + * for 65550's. Wingine cursor is stored in registers and so no memory + * is needed. + */ + if (cAcl->UseHWCursor) { + cAcl->CursorAddress = -1; + if (IS_HiQV(cPtr)) { + if (CHIPSALIGN(1024, 0xFFF) <= freespace) { + currentaddr -= CHIPSALIGN(1024, 0xFFF); + freespace -= CHIPSALIGN(1024, 0xFFF); + cAcl->CursorAddress = currentaddr; + } + } else if (IS_Wingine(cPtr)) { + cAcl->CursorAddress = 0; + } else if (CHIPSALIGN(1024, 0x3FF) <= freespace) { + currentaddr -= CHIPSALIGN(1024, 0x3FF); + freespace -= CHIPSALIGN(1024, 0x3FF); + cAcl->CursorAddress = currentaddr; + } + if (cAcl->CursorAddress == -1) + xf86DrvMsg(scrnIndex, X_ERROR, + "Too little space for H/W cursor.\n"); + } + + cAcl->CacheEnd = currentaddr; + + /* Setup the acceleration primitives */ + /* Calculate space needed of offscreen pixmaps etc. */ + if (cPtr->Flags & ChipsAccelSupport) { + /* + * A scratch area is now allocated in the video ram. This is used + * at 8 and 16 bpp to simulate a planemask with a complex ROP, and + * at 24 and 32 bpp to aid in accelerating solid fills + */ + cAcl->ScratchAddress = -1; + switch (pScrn->bitsPerPixel) { + case 8: + if (CHIPSALIGN(64, 0x3F) <= freespace) { + currentaddr -= CHIPSALIGN(64, 0x3F); + freespace -= CHIPSALIGN(64, 0x3F); + cAcl->ScratchAddress = currentaddr; + } + break; + case 16: + if (CHIPSALIGN(128, 0x7F) <= freespace) { + currentaddr -= CHIPSALIGN(128, 0x7F); + freespace -= CHIPSALIGN(128, 0x7F); + cAcl->ScratchAddress = currentaddr; + } + break; + case 24: + /* One scanline of data used for solid fill */ + if (!IS_HiQV(cPtr)) { + if (CHIPSALIGN(3 * (pScrn->displayWidth + 4), 0x3) + <= freespace) { + currentaddr -= CHIPSALIGN(3 * (pScrn->displayWidth + + 4), 0x3); + freespace -= CHIPSALIGN(3 * (pScrn->displayWidth + 4), + 0x3); + cAcl->ScratchAddress = currentaddr; + } + } + break; + case 32: + /* 16bpp 8x8 mono pattern fill for solid fill. QWORD aligned */ + if (IS_HiQV(cPtr)) { + if (CHIPSALIGN(8, 0x7) <= freespace) { + currentaddr -= CHIPSALIGN(8, 0x7); + freespace -= CHIPSALIGN(8, 0x7); + cAcl->ScratchAddress = currentaddr; + } + } + break; + } + + /* Setup the boundaries of the pixmap cache */ + cAcl->CacheStart = currentaddr - freespace; + cAcl->CacheEnd = currentaddr; + + if (cAcl->CacheStart >= cAcl->CacheEnd) { + xf86DrvMsg(scrnIndex, X_ERROR, + "Too little space for pixmap cache.\n"); + cAcl->CacheStart = 0; + cAcl->CacheEnd = 0; + } + + if (IS_HiQV(cPtr)) + cAcl->BltDataWindow = (unsigned char *)cPtr->MMIOBase + + 0x10000L; + else + cAcl->BltDataWindow = cPtr->FbBase; + + } + /* + * Initialize FBManager: + * we do even with no acceleration enabled + * so that video support can allocate space. + */ + + { + BoxRec AvailFBArea; + AvailFBArea.x1 = 0; + AvailFBArea.y1 = 0; + AvailFBArea.x2 = pScrn->displayWidth; + AvailFBArea.y2 = cAcl->CacheEnd / + (pScrn->displayWidth * (pScrn->bitsPerPixel >> 3)); + + if (!(cPtr->Flags & ChipsOverlay8plus16)) { + xf86InitFBManager(pScreen, &AvailFBArea); + } + } + if (cPtr->Flags & ChipsAccelSupport) { + if (IS_HiQV(cPtr)) { + CHIPSHiQVAccelInit(pScreen); + } else if (cPtr->UseMMIO) { + CHIPSMMIOAccelInit(pScreen); + } else { + CHIPSAccelInit(pScreen); + } + } + + miInitializeBackingStore(pScreen); + xf86SetBackingStore(pScreen); +#ifdef ENABLE_SILKEN_MOUSE + xf86SetSilkenMouse(pScreen); +#endif + + /* Initialise cursor functions */ + miDCInitialize (pScreen, xf86GetPointerScreenFuncs()); + + if ((cAcl->UseHWCursor) && (cAcl->CursorAddress != -1)) { + /* HW cursor functions */ + if (!CHIPSCursorInit(pScreen)) { + xf86DrvMsg(scrnIndex, X_ERROR, + "Hardware cursor initialization failed\n"); + return FALSE; + } + } + } + + if (cPtr->Flags & ChipsShadowFB) { + RefreshAreaFuncPtr refreshArea = chipsRefreshArea; + + if(cPtr->Rotate) { + if (!cPtr->PointerMoved) { + cPtr->PointerMoved = pScrn->PointerMoved; + pScrn->PointerMoved = chipsPointerMoved; + } + + switch(pScrn->bitsPerPixel) { + case 8: refreshArea = chipsRefreshArea8; break; + case 16: refreshArea = chipsRefreshArea16; break; + case 24: refreshArea = chipsRefreshArea24; break; + case 32: refreshArea = chipsRefreshArea32; break; + } + } + ShadowFBInit(pScreen, refreshArea); + } + + /* Initialise default colourmap */ + if (!miCreateDefColormap(pScreen)) + return FALSE; + + if ((cPtr->Flags & ChipsOverlay8plus16) && (pScrn->bitsPerPixel == 16)) { + if(!xf86HandleColormaps(pScreen, 256, pScrn->rgbBits, chipsLoadPalette, + NULL, CMAP_RELOAD_ON_MODE_SWITCH)) + return FALSE; + } else { + if(!xf86HandleColormaps(pScreen, 256, pScrn->rgbBits, + (pScrn->depth == 16 ? chipsLoadPalette16 : chipsLoadPalette), + NULL, CMAP_RELOAD_ON_MODE_SWITCH | CMAP_PALETTED_TRUECOLOR)) + return FALSE; + } + + racflag = RAC_COLORMAP; + if (cAcl->UseHWCursor) + racflag |= RAC_CURSOR; + racflag |= (RAC_FB | RAC_VIEWPORT); + /* XXX Check if I/O and Mem flags need to be the same. */ + pScrn->racIoFlags = pScrn->racMemFlags = racflag; +#ifdef ENABLE_SILKEN_MOUSE + xf86SetSilkenMouse(pScreen); +#endif + + if ((!(cPtr->Flags & ChipsOverlay8plus16)) + && (cPtr->Flags & ChipsVideoSupport) + && (cPtr->Flags & ChipsLinearSupport)) { + CHIPSInitVideo(pScreen); + } + + pScreen->SaveScreen = CHIPSSaveScreen; + + /* Setup DPMS mode */ + if (cPtr->Flags & ChipsDPMSSupport) + xf86DPMSInit(pScreen, (DPMSSetProcPtr)chipsDisplayPowerManagementSet, + 0); + +#if 0 /* #### Shouldn't be needed */ + /* Dual head, needs to fix framebuffer memory address */ + if ((cPtr->Flags & ChipsDualChannelSupport) && + (cPtr->SecondCrtc == TRUE)) + pScrn->memPhysBase = cPtr->FbAddress + cPtrEnt->masterFbMapSize; +#endif + + /* Wrap the current CloseScreen function */ + cPtr->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = CHIPSCloseScreen; + + /* Report any unused options (only for the first generation) */ + if (serverGeneration == 1) { + xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); + } + + return TRUE; +} + +/* Mandatory */ +Bool +CHIPSSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSEntPtr cPtrEnt; + +#ifdef DEBUG + ErrorF("CHIPSSwitchMode\n"); +#endif + if (cPtr->UseDualChannel) { + cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0], + CHIPSEntityIndex)->ptr; + DUALREOPEN; + } + + return chipsModeInit(xf86Screens[scrnIndex], mode); +} + +/* Mandatory */ +void +CHIPSAdjustFrame(int scrnIndex, int x, int y, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSEntPtr cPtrEnt; + + int Base; + vgaHWPtr hwp = VGAHWPTR(pScrn); + unsigned char tmp; + + if (xf86ReturnOptValBool(cPtr->Options, OPTION_SHOWCACHE, FALSE) && y) { + int lastline = cPtr->FbMapSize / + ((pScrn->displayWidth * pScrn->bitsPerPixel) / 8); + lastline -= pScrn->currentMode->VDisplay; + y += pScrn->virtualY - 1; + if (y > lastline) y = lastline; + } + + Base = y * pScrn->displayWidth + x; + + /* calculate base bpp dep. */ + switch (pScrn->bitsPerPixel) { + case 1: + case 4: + Base >>= 3; + break; + case 16: + if (!(cPtr->Flags & ChipsOverlay8plus16)) + Base >>= 1; + else + Base >>= 2; + break; + case 24: + if (!IS_HiQV(cPtr)) + Base = (Base >> 2) * 3; + else + Base = (Base >> 3) * 6; /* 65550 seems to need 64bit alignment */ + break; + case 32: + break; + default: /* 8bpp */ + Base >>= 2; + break; + } + + if (cPtr->UseDualChannel) { + cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0], + CHIPSEntityIndex)->ptr; + DUALREOPEN; + } + + /* write base to chip */ + /* + * These are the generic starting address registers. + */ + chipsFixResume(pScrn); + hwp->writeCrtc(hwp, 0x0C, (Base & 0xFF00) >> 8); + hwp->writeCrtc(hwp, 0x0D, Base & 0xFF); + if (IS_HiQV(cPtr)) { + if (((cPtr->readXR(cPtr, 0x09)) & 0x1) == 0x1) + hwp->writeCrtc(hwp, 0x40, ((Base & 0x0F0000) >> 16) | 0x80); + } else { + tmp = cPtr->readXR(cPtr, 0x0C); + cPtr->writeXR(cPtr, 0x0C, ((Base & (IS_Wingine(cPtr) ? 0x0F0000 : + 0x030000)) >> 16) | (tmp & 0xF8)); + } + + if (cPtr->UseDualChannel && + (! xf86IsEntityShared(pScrn->entityList[0]))) { + unsigned int IOSS, MSS; + IOSS = cPtr->readIOSS(cPtr); + MSS = cPtr->readMSS(cPtr); + cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) | + IOSS_PIPE_B)); + cPtr->writeMSS(cPtr, hwp, ((cPtr->storeMSS & MSS_MASK) | MSS_PIPE_B)); + + chipsFixResume(pScrn); + hwp->writeCrtc(hwp, 0x0C, (Base & 0xFF00) >> 8); + hwp->writeCrtc(hwp, 0x0D, Base & 0xFF); + if (((cPtr->readXR(cPtr, 0x09)) & 0x1) == 0x1) + hwp->writeCrtc(hwp, 0x40, ((Base & 0x0F0000) >> 16) | 0x80); + + cPtr->writeIOSS(cPtr, IOSS); + cPtr->writeMSS(cPtr, hwp, MSS); + } + + if (cPtr->Flags & ChipsOverlay8plus16) { + Base = (Base << 3) & ~(unsigned long)0xF; + + cPtr->writeMR(cPtr, 0x22, (cPtr->FbOffset16 + Base) & 0xF8); + cPtr->writeMR(cPtr, 0x23, ((cPtr->FbOffset16 + Base) >> 8) & 0xFF); + cPtr->writeMR(cPtr, 0x24, ((cPtr->FbOffset16 + Base) >> 16) & 0xFF); + } + +} + +/* Mandatory */ +static Bool +CHIPSCloseScreen(int scrnIndex, ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSEntPtr cPtrEnt; + + if(pScrn->vtSema){ /*§§§*/ + if (cPtr->Flags & ChipsDualChannelSupport) { + cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0], + CHIPSEntityIndex)->ptr; + if (cPtr->UseDualChannel) + DUALREOPEN; + DUALCLOSE; + } else { + chipsHWCursorOff(cPtr, pScrn); + chipsRestore(pScrn, &(VGAHWPTR(pScrn))->SavedReg, &cPtr->SavedReg, + TRUE); + chipsLock(pScrn); + } + chipsUnmapMem(pScrn); + } + + if (xf86IsEntityShared(pScrn->entityList[0])) { + DevUnion *pPriv; + pPriv = xf86GetEntityPrivate(pScrn->entityList[0], CHIPSEntityIndex); + cPtrEnt = pPriv->ptr; + cPtrEnt->refCount--; + } + if (cPtr->AccelInfoRec) + XAADestroyInfoRec(cPtr->AccelInfoRec); + if (cPtr->CursorInfoRec) + xf86DestroyCursorInfoRec(cPtr->CursorInfoRec); + if (cPtr->ShadowPtr) + xfree(cPtr->ShadowPtr); + if (cPtr->DGAModes) + xfree(cPtr->DGAModes); + pScrn->vtSema = FALSE; + if(cPtr->BlockHandler) + pScreen->BlockHandler = cPtr->BlockHandler; + + pScreen->CloseScreen = cPtr->CloseScreen; /*§§§*/ + xf86ClearPrimInitDone(pScrn->entityList[0]); + return (*pScreen->CloseScreen)(scrnIndex, pScreen);/*§§§*/ +} + +/* Optional */ +static void +CHIPSFreeScreen(int scrnIndex, int flags) +{ + if (xf86LoaderCheckSymbol("vgaHWFreeHWRec")) + vgaHWFreeHWRec(xf86Screens[scrnIndex]); + CHIPSFreeRec(xf86Screens[scrnIndex]); +} + +/* Optional */ +static int +CHIPSValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + CHIPSPtr cPtr = CHIPSPTR(pScrn); + + if (flags & MODECHECK_FINAL) { + /* Don't subtract FrambufferSize here as it should be subtracted already */ + if ((cPtr->Flags & ChipsOverlay8plus16) + && ((pScrn->videoRam<<10) - pScrn->displayWidth * 3 * pScrn->virtualY + < 0)) + return MODE_MEM; + } + /* The tests here need to be expanded */ + if ((mode->Flags & V_INTERLACE) && (cPtr->PanelType & ChipsLCD)) + return MODE_NO_INTERLACE; + if ((cPtr->PanelType & ChipsLCD) + && ((cPtr->PanelSize.HDisplay < mode->HDisplay) + || (cPtr->PanelSize.VDisplay < mode->VDisplay))) + return MODE_PANEL; + + return MODE_OK; +} + +/* + * DPMS Control registers + * + * XR73 6554x and 64300 (what about 65535?) + * XR61 6555x + * 0 HSync Powerdown data + * 1 HSync Select 1=Powerdown + * 2 VSync Powerdown data + * 3 VSync Select 1=Powerdown + */ + +static void +chipsDisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, + int flags) +{ + vgaHWPtr hwp = VGAHWPTR(pScrn); + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSEntPtr cPtrEnt; + + unsigned char dpmsreg, seqreg, lcdoff, tmp; + + if (!pScrn->vtSema) + return; + + xf86EnableAccess(pScrn); + switch (PowerManagementMode) { + case DPMSModeOn: + /* Screen: On; HSync: On, VSync: On */ + dpmsreg = 0x00; + seqreg = 0x00; + lcdoff = 0x0; + break; + case DPMSModeStandby: + /* Screen: Off; HSync: Off, VSync: On */ + dpmsreg = 0x02; + seqreg = 0x20; + lcdoff = 0x0; + break; + case DPMSModeSuspend: + /* Screen: Off; HSync: On, VSync: Off */ + dpmsreg = 0x08; + seqreg = 0x20; + lcdoff = 0x1; + break; + case DPMSModeOff: + /* Screen: Off; HSync: Off, VSync: Off */ + dpmsreg = 0x0A; + seqreg = 0x20; + lcdoff = 0x1; + break; + default: + return; + } + + if (cPtr->UseDualChannel) { + cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0], + CHIPSEntityIndex)->ptr; + DUALREOPEN; + } + + seqreg |= hwp->readSeq(hwp, 0x01) & ~0x20; + hwp->writeSeq(hwp, 0x01, seqreg); + if (IS_HiQV(cPtr)) { + tmp = cPtr->readXR(cPtr, 0x61); + cPtr->writeXR(cPtr, 0x61, (tmp & 0xF0) | dpmsreg); + } else { + tmp = cPtr->readXR(cPtr, 0x73); + cPtr->writeXR(cPtr, 0x73, (tmp & 0xF0) | dpmsreg); + } + + /* Turn off the flat panel */ + if (cPtr->PanelType & ChipsLCDProbed) { + if (IS_HiQV(cPtr)) { + if (cPtr->Chipset == CHIPS_CT69030) { +#if 0 + /* Where is this for the 69030?? */ + tmp = cPtr->readFR(cPtr, 0x05); + if (lcdoff) + cPtr->writeFR(cPtr, 0x05, tmp | 0x08); + else + cPtr->writeFR(cPtr, 0x05, tmp & 0xF7); +#endif + } else { + tmp = cPtr->readFR(cPtr, 0x05); + if (lcdoff) + cPtr->writeFR(cPtr, 0x05, tmp | 0x08); + else + cPtr->writeFR(cPtr, 0x05, tmp & 0xF7); + } + } else { + tmp = cPtr->readXR(cPtr, 0x52); + if (lcdoff) + cPtr->writeXR(cPtr, 0x52, tmp | 0x08); + else + cPtr->writeXR(cPtr, 0x52, tmp & 0xF7); + } + } +} + +static Bool +CHIPSSaveScreen(ScreenPtr pScreen, int mode) +{ + ScrnInfoPtr pScrn = NULL; /* §§§ */ + Bool unblank; + + unblank = xf86IsUnblank(mode); + + if (pScreen != NULL) + pScrn = xf86Screens[pScreen->myNum]; + + if (unblank) + SetTimeSinceLastInputEvent(); + + if ((pScrn != NULL) && pScrn->vtSema) { /* §§§ */ + chipsBlankScreen(pScrn, unblank); + } + return (TRUE); +} + +static Bool +chipsClockSelect(ScrnInfoPtr pScrn, int no) +{ + CHIPSClockReg TmpClock; + CHIPSPtr cPtr = CHIPSPTR(pScrn); + + switch (no) { + case CLK_REG_SAVE: + chipsClockSave(pScrn, &cPtr->SaveClock); + break; + + case CLK_REG_RESTORE: + chipsClockLoad(pScrn, &cPtr->SaveClock); + break; + + default: + if (!chipsClockFind(pScrn, no, &TmpClock)) + return (FALSE); + chipsClockLoad(pScrn, &TmpClock); + } + return (TRUE); +} + +/* + * + * Fout = (Fref * 4 * M) / (PSN * N * (1 << P) ) + * Fvco = (Fref * 4 * M) / (PSN * N) + * where + * M = XR31+2 + * N = XR32+2 + * P = XR30[3:1] + * PSN = XR30[0]? 1:4 + * + * constraints: + * 4 MHz <= Fref <= 20 MHz (typ. 14.31818 MHz) + * 150 kHz <= Fref/(PSN * N) <= 2 MHz + * 48 MHz <= Fvco <= 220 MHz + * 2 < M < 128 + * 2 < N < 128 + */ + +static void +chipsClockSave(ScrnInfoPtr pScrn, CHIPSClockPtr Clock) +{ + unsigned char tmp; + vgaHWPtr hwp = VGAHWPTR(pScrn); + CHIPSPtr cPtr = CHIPSPTR(pScrn); + unsigned char Type = cPtr->ClockType; + CHIPSEntPtr cPtrEnt; + + Clock->msr = hwp->readMiscOut(hwp)&0xFE; /* save standard VGA clock reg */ + switch (Type & GET_STYLE) { + case HiQV_STYLE: + /* save alternate clock select reg.*/ + /* The 69030 FP clock select is at FR01 instead */ + if (cPtr->UseDualChannel) { + cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0], + CHIPSEntityIndex)->ptr; + DUALREOPEN; + } + + if (cPtr->Flags & ChipsDualChannelSupport) + Clock->fr03 = cPtr->readFR(cPtr, 0x01); + else + Clock->fr03 = cPtr->readFR(cPtr, 0x03); + if (!Clock->Clock) { /* save HiQV console clock */ + tmp = cPtr->CRTclkInx << 2; + cPtr->CRTClk[0] = cPtr->readXR(cPtr, 0xC0 + tmp); + cPtr->CRTClk[1] = cPtr->readXR(cPtr, 0xC1 + tmp); + cPtr->CRTClk[2] = cPtr->readXR(cPtr, 0xC2 + tmp); + cPtr->CRTClk[3] = cPtr->readXR(cPtr, 0xC3 + tmp); + tmp = cPtr->FPclkInx << 2; + cPtr->FPClk[0] = cPtr->readXR(cPtr, 0xC0 + tmp); + cPtr->FPClk[1] = cPtr->readXR(cPtr, 0xC1 + tmp); + cPtr->FPClk[2] = cPtr->readXR(cPtr, 0xC2 + tmp); + cPtr->FPClk[3] = cPtr->readXR(cPtr, 0xC3 + tmp); + } + break; + case OLD_STYLE: + Clock->fcr = hwp->readFCR(hwp); + Clock->xr02 = cPtr->readXR(cPtr, 0x02); + Clock->xr54 = cPtr->readXR(cPtr, 0x54); /* save alternate clock select reg.*/ + break; + case WINGINE_1_STYLE: + case WINGINE_2_STYLE: + break; + case NEW_STYLE: + Clock->xr54 = cPtr->readXR(cPtr, 0x54); /* save alternate clock select reg.*/ + Clock->xr33 = cPtr->readXR(cPtr, 0x33); /* get status of MCLK/VCLK sel reg.*/ + break; + } +#ifdef DEBUG + ErrorF("saved \n"); +#endif +} + +static Bool +chipsClockFind(ScrnInfoPtr pScrn, int no, CHIPSClockPtr Clock) +{ + vgaHWPtr hwp = VGAHWPTR(pScrn); + CHIPSPtr cPtr = CHIPSPTR(pScrn); + unsigned char Type = cPtr->ClockType; + CHIPSEntPtr cPtrEnt; + + if (no > (pScrn->numClocks - 1)) + return (FALSE); + + if (cPtr->UseDualChannel) { + cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0], + CHIPSEntityIndex)->ptr; + DUALREOPEN; + } + + switch (Type & GET_STYLE) { + case HiQV_STYLE: + Clock->msr = cPtr->CRTclkInx << 2; + Clock->fr03 = cPtr->FPclkInx << 2; + Clock->Clock = pScrn->currentMode->Clock; + if (xf86ReturnOptValBool(cPtr->Options, OPTION_USE_MODELINE, FALSE)) { + Clock->FPClock = pScrn->currentMode->Clock; + } else + Clock->FPClock = cPtr->FPclock; + break; + case NEW_STYLE: + if (Type & TYPE_HW) { + Clock->msr = (no == 4 ? 3 << 2: (no & 0x01) << 2); + Clock->xr54 = Clock->msr; + Clock->xr33 = no > 1 ? 0x80 : 0; + } else { + Clock->msr = 3 << 2; + Clock->xr33 = 0; + Clock->xr54 = Clock->msr; + /* update panel type in case somebody switched. + * This should be handled more generally: + * On mode switch DDC should be reread, all + * display dependent data should be reevaluated. + * This will be built in when we start Display + * HotPlug support. + * Until then we have to do it here as somebody + * might have switched displays on us and we only + * have one programmable clock which needs to + * be shared for CRT and LCD. + */ + chipsSetPanelType(cPtr); + { + Bool fp_m; + if (cPtr->Options + && xf86GetOptValBool(cPtr->Options, OPTION_FP_MODE, &fp_m)) { + if (fp_m) + cPtr->PanelType |= ChipsLCD; + else + cPtr->PanelType = ~ChipsLCD; + } + } + + if ((cPtr->PanelType & ChipsLCD) && cPtr->FPclock) + Clock->Clock = cPtr->FPclock; + else + Clock->Clock = pScrn->currentMode->SynthClock; + } + break; + case OLD_STYLE: + if (no > 3) { + Clock->msr = 3 << 2; + Clock->fcr = no & 0x03; + Clock->xr02 = 0; + Clock->xr54 = Clock->msr & (Clock->fcr << 4); + } else { + Clock->msr = (no << 2) & 0x4; + Clock->fcr = 0; + Clock->xr02 = no & 0x02; + Clock->xr54 = Clock->msr; + } + break; + case WINGINE_1_STYLE: + Clock->msr = no << 2; + case WINGINE_2_STYLE: + if (Type & TYPE_HW) { + Clock->msr = (no == 2 ? 3 << 2: (no & 0x01) << 2); + Clock->xr33 = 0; + } else { + Clock->msr = 3 << 2; + Clock->xr33 = 0; + Clock->Clock = pScrn->currentMode->SynthClock; + } + break; + } + Clock->msr |= (hwp->readMiscOut(hwp) & 0xF2); + +#ifdef DEBUG + ErrorF("found\n"); +#endif + return (TRUE); +} + + +static int +chipsGetHWClock(ScrnInfoPtr pScrn) +{ + vgaHWPtr hwp = VGAHWPTR(pScrn); + CHIPSPtr cPtr = CHIPSPTR(pScrn); + unsigned char Type = cPtr->ClockType; + unsigned char tmp, tmp1; + + if (!(Type & TYPE_HW)) + return 0; /* shouldn't happen */ + + switch (Type & GET_STYLE) { + case WINGINE_1_STYLE: + return ((hwp->readMiscOut(hwp) & 0x0C) >> 2); + case WINGINE_2_STYLE: + tmp = ((hwp->readMiscOut(hwp) & 0x04) >> 2); + return (tmp > 2) ? 2 : tmp; + case OLD_STYLE: + if (!(cPtr->PanelType & ChipsLCDProbed)) + tmp = hwp->readMiscOut(hwp); + else + tmp = cPtr->readXR(cPtr, 0x54); + if (tmp & 0x08) { + if (!(cPtr->PanelType & ChipsLCDProbed)) + tmp = hwp->readFCR(hwp) & 0x03; + else + tmp = (tmp >> 4) & 0x03; + return (tmp + 4); + } else { + tmp = (tmp >> 2) & 0x01; + tmp1 = cPtr->readXR(cPtr, 0x02); + return (tmp + (tmp1 & 0x02)); + } + case NEW_STYLE: + if (cPtr->PanelType & ChipsLCDProbed) { + tmp = cPtr->readXR(cPtr, 0x54); + } else + tmp = hwp->readMiscOut(hwp); + tmp = (tmp & 0x0C) >> 2; + if (tmp > 1) return 4; + tmp1 = cPtr->readXR(cPtr, 0x33); + tmp1 = (tmp1 & 0x80) >> 6; /* iso mode 25.175/28.322 or 32/36 MHz */ + return (tmp + tmp1); /* ^=0 ^=1 ^=4 ^=5 */ + default: /* we should never get here */ + return (0); + } +} + +static void +chipsClockLoad(ScrnInfoPtr pScrn, CHIPSClockPtr Clock) +{ + vgaHWPtr hwp = VGAHWPTR(pScrn); + CHIPSPtr cPtr = CHIPSPTR(pScrn); + unsigned char Type = cPtr->ClockType; + volatile unsigned char tmp, tmpmsr, tmpfcr, tmp02; + volatile unsigned char tmp33, tmp54, tmpf03; + unsigned char vclk[3]; + + tmpmsr = hwp->readMiscOut(hwp); /* read msr, needed for all styles */ + + switch (Type & GET_STYLE) { + case HiQV_STYLE: + /* save alternate clock select reg. */ + /* The 69030 FP clock select is at FR01 instead */ + if (cPtr->Flags & ChipsDualChannelSupport) { + tmpf03 = cPtr->readFR(cPtr, 0x01); + } else + tmpf03 = cPtr->readFR(cPtr, 0x03); + /* select fixed clock 0 before tampering with VCLK select */ + hwp->writeMiscOut(hwp, (tmpmsr & ~0x0D) | + cPtr->SuspendHack.vgaIOBaseFlag); + /* The 69030 FP clock select is at FR01 instead */ + if (cPtr->Flags & ChipsDualChannelSupport) { + cPtr->writeFR(cPtr, 0x01, (tmpf03 & ~0x0C) | 0x04); + } else + cPtr->writeFR(cPtr, 0x03, (tmpf03 & ~0x0C) | 0x04); + if (!Clock->Clock) { /* Hack to load saved console clock */ + tmp = cPtr->CRTclkInx << 2; + cPtr->writeXR(cPtr, 0xC0 + tmp, (cPtr->CRTClk[0] & 0xFF)); + cPtr->writeXR(cPtr, 0xC1 + tmp, (cPtr->CRTClk[1] & 0xFF)); + cPtr->writeXR(cPtr, 0xC2 + tmp, (cPtr->CRTClk[2] & 0xFF)); + cPtr->writeXR(cPtr, 0xC3 + tmp, (cPtr->CRTClk[3] & 0xFF)); + + if (cPtr->FPClkModified) { + usleep(10000); /* let VCO stabilize */ + tmp = cPtr->FPclkInx << 2; + cPtr->writeXR(cPtr, 0xC0 + tmp, (cPtr->FPClk[0] & 0xFF)); + cPtr->writeXR(cPtr, 0xC1 + tmp, (cPtr->FPClk[1] & 0xFF)); + cPtr->writeXR(cPtr, 0xC2 + tmp, (cPtr->FPClk[2] & 0xFF)); + cPtr->writeXR(cPtr, 0xC3 + tmp, (cPtr->FPClk[3] & 0xFF)); + } + } else { + /* + * Don't use the extra 2 bits in the M, N registers available + * on the HiQV, so write zero to 0xCA + */ + chipsCalcClock(pScrn, Clock->Clock, vclk); + tmp = cPtr->CRTclkInx << 2; + cPtr->writeXR(cPtr, 0xC0 + tmp, (vclk[1] & 0xFF)); + cPtr->writeXR(cPtr, 0xC1 + tmp, (vclk[2] & 0xFF)); + cPtr->writeXR(cPtr, 0xC2 + tmp, 0x0); + cPtr->writeXR(cPtr, 0xC3 + tmp, (vclk[0] & 0xFF)); + if (Clock->FPClock) { + usleep(10000); /* let VCO stabilize */ + chipsCalcClock(pScrn, Clock->FPClock, vclk); + tmp = cPtr->FPclkInx << 2; + cPtr->writeXR(cPtr, 0xC0 + tmp, (vclk[1] & 0xFF)); + cPtr->writeXR(cPtr, 0xC1 + tmp, (vclk[2] & 0xFF)); + cPtr->writeXR(cPtr, 0xC2 + tmp, 0x0); + cPtr->writeXR(cPtr, 0xC3 + tmp, (vclk[0] & 0xFF)); + cPtr->FPClkModified = TRUE; + } + } + usleep(10000); /* Let VCO stabilise */ + /* The 69030 FP clock select is at FR01 instead */ + if (cPtr->Flags & ChipsDualChannelSupport) { + cPtr->writeFR(cPtr, 0x01, ((tmpf03 & ~0x0C) | + (Clock->fr03 & 0x0C))); + } else + cPtr->writeFR(cPtr, 0x03, ((tmpf03 & ~0x0C) | + (Clock->fr03 & 0x0C))); + break; + case WINGINE_1_STYLE: + break; + case WINGINE_2_STYLE: + /* Only write to soft clock registers if we really need to */ + if ((Type & GET_TYPE) == TYPE_PROGRAMMABLE) { + /* select fixed clock 0 before tampering with VCLK select */ + hwp->writeMiscOut(hwp, (tmpmsr & ~0x0D) | + cPtr->SuspendHack.vgaIOBaseFlag); + chipsCalcClock(pScrn, Clock->Clock, vclk); + tmp33 = cPtr->readXR(cPtr, 0x33); /* get status of MCLK/VCLK select reg */ + cPtr->writeXR(cPtr, 0x33, tmp33 & ~0x20); + cPtr->writeXR(cPtr, 0x30, vclk[0]); + cPtr->writeXR(cPtr, 0x31, vclk[1]); /* restore VCLK regs. */ + cPtr->writeXR(cPtr, 0x32, vclk[2]); + /* cPtr->writeXR(cPtr, 0x33, tmp33 & ~0x20);*/ + usleep(10000); /* Let VCO stabilise */ + } + break; + case OLD_STYLE: + tmp02 = cPtr->readXR(cPtr, 0x02); + tmp54 = cPtr->readXR(cPtr, 0x54); + tmpfcr = hwp->readFCR(hwp); + cPtr->writeXR(cPtr, 0x02, ((tmp02 & ~0x02) | (Clock->xr02 & 0x02))); + cPtr->writeXR(cPtr, 0x54, ((tmp54 & 0xF0) | (Clock->xr54 & ~0xF0))); + hwp->writeFCR(hwp, (tmpfcr & ~0x03) & Clock->fcr); + break; + case NEW_STYLE: + tmp33 = cPtr->readXR(cPtr, 0x33); /* get status of MCLK/VCLK select reg */ + tmp54 = cPtr->readXR(cPtr, 0x54); + /* Only write to soft clock registers if we really need to */ + if ((Type & GET_TYPE) == TYPE_PROGRAMMABLE) { + /* select fixed clock 0 before tampering with VCLK select */ + hwp->writeMiscOut(hwp, (tmpmsr & ~0x0D) | + cPtr->SuspendHack.vgaIOBaseFlag); + cPtr->writeXR(cPtr, 0x54, (tmp54 & 0xF3)); + /* if user wants to set the memory clock, do it first */ + if (cPtr->MemClock.Clk) { + chipsCalcClock(pScrn, cPtr->MemClock.Clk, vclk); + /* close eyes, hold breath ....*/ + cPtr->writeXR(cPtr, 0x33, tmp33 | 0x20); + cPtr->writeXR(cPtr, 0x30, vclk[0]); + cPtr->writeXR(cPtr, 0x31, vclk[1]); + cPtr->writeXR(cPtr, 0x32, vclk[2]); + usleep(10000); + } + chipsCalcClock(pScrn, Clock->Clock, vclk); + cPtr->writeXR(cPtr, 0x33, tmp33 & ~0x20); + cPtr->writeXR(cPtr, 0x30, vclk[0]); + cPtr->writeXR(cPtr, 0x31, vclk[1]); /* restore VCLK regs. */ + cPtr->writeXR(cPtr, 0x32, vclk[2]); + /* cPtr->writeXR(cPtr, 0x33, tmp33 & ~0x20);*/ + usleep(10000); /* Let VCO stabilise */ + } + cPtr->writeXR(cPtr, 0x33, ((tmp33 & ~0x80) | (Clock->xr33 & 0x80))); + cPtr->writeXR(cPtr, 0x54, ((tmp54 & 0xF3) | (Clock->xr54 & ~0xF3))); + break; + } + hwp->writeMiscOut(hwp, (Clock->msr & 0xFE) | + cPtr->SuspendHack.vgaIOBaseFlag); +#ifdef DEBUG + ErrorF("restored\n"); +#endif +} + +/* + * This is Ken Raeburn's <raeburn@raeburn.org> clock + * calculation code just modified a little bit to fit in here. + */ + +static void +chipsCalcClock(ScrnInfoPtr pScrn, int Clock, unsigned char *vclk) +{ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + int M, N, P = 0, PSN = 0, PSNx = 0; + + int bestM = 0, bestN = 0, bestP = 0, bestPSN = 0; + double bestError, abest = 42, bestFout = 0; + double target; + + double Fvco, Fout; + double error, aerror; + + int M_min = 3; + + /* Hack to deal with problem of Toshiba 720CDT clock */ + int M_max = (IS_HiQV(cPtr) && cPtr->Chipset != CHIPS_CT69000 && + cPtr->Chipset != CHIPS_CT69030) ? 63 : 127; + + /* @@@ < CHIPS_CT690x0 ?? */ + + /* Other parameters available on the 65548 but not the 65545, and + * not documented in the Clock Synthesizer doc in rev 1.0 of the + * 65548 datasheet: + * + * + XR30[4] = 0, VCO divider loop uses divide by 4 (same as 65545) + * 1, VCO divider loop uses divide by 16 + * + * + XR30[5] = 1, reference clock is divided by 5 + * + * Other parameters available on the 65550 and not on the 65545 + * + * + XRCB[2] = 0, VCO divider loop uses divide by 4 (same as 65545) + * 1, VCO divider loop uses divide by 16 + * + * + XRCB[1] = 1, reference clock is divided by 5 + * + * + XRCB[7] = Vclk = Mclk + * + * + XRCA[0:1] = 2 MSB of a 10 bit M-Divisor + * + * + XRCA[4:5] = 2 MSB of a 10 bit N-Divisor + * + * I haven't put in any support for those here. For simplicity, + * they should be set to 0 on the 65548, and left untouched on + * earlier chips. + * + * Other parameters available on the 690x0 + * + * + The 690x0 has no reference clock divider, so PSN must + * always be 1. + * XRCB[0:1] are reserved according to the data book + */ + + + target = Clock * 1000; + + /* @@@ >= CHIPS_CT690x0 ?? */ + for (PSNx = ((cPtr->Chipset == CHIPS_CT69000) || + (cPtr->Chipset == CHIPS_CT69030)) ? 1 : 0; PSNx <= 1; PSNx++) { + int low_N, high_N; + double Fref4PSN; + + PSN = PSNx ? 1 : 4; + + low_N = 3; + high_N = 127; + + while (Fref / (PSN * low_N) > (((cPtr->Chipset == CHIPS_CT69000) || + (cPtr->Chipset == CHIPS_CT69030)) ? 5.0e6 : 2.0e6)) + low_N++; + while (Fref / (PSN * high_N) < 150.0e3) + high_N--; + + Fref4PSN = Fref * 4 / PSN; + for (N = low_N; N <= high_N; N++) { + double tmp = Fref4PSN / N; + + /* @@@ < CHIPS_CT690x0 ?? */ + for (P = (IS_HiQV(cPtr) && (cPtr->Chipset != CHIPS_CT69000) && + (cPtr->Chipset != CHIPS_CT69030)) ? 1 : 0; + P <= 5; P++) { + /* to force post divisor on Toshiba 720CDT */ + double Fvco_desired = target * (1 << P); + double M_desired = Fvco_desired / tmp; + + /* Which way will M_desired be rounded? Do all three just to + * be safe. */ + int M_low = M_desired - 1; + int M_hi = M_desired + 1; + + if (M_hi < M_min || M_low > M_max) + continue; + + if (M_low < M_min) + M_low = M_min; + if (M_hi > M_max) + M_hi = M_max; + + for (M = M_low; M <= M_hi; M++) { + Fvco = tmp * M; + /* @@@ >= CHIPS_CT690x0 ?? */ + if (Fvco <= ((cPtr->Chipset == CHIPS_CT69000 || + cPtr->Chipset == CHIPS_CT69030) ? 100.0e6 : 48.0e6)) + continue; + if (Fvco > 220.0e6) + break; + + Fout = Fvco / (1 << P); + + error = (target - Fout) / target; + + aerror = (error < 0) ? -error : error; + if (aerror < abest) { + abest = aerror; + bestError = error; + bestM = M; + bestN = N; + bestP = P; + bestPSN = PSN; + bestFout = Fout; + } + } + } + } + } + /* @@@ >= CHIPS_CT690x0 ?? */ + vclk[0] = (bestP << (IS_HiQV(cPtr) ? 4 : 1)) + + (((cPtr->Chipset == CHIPS_CT69000) || (cPtr->Chipset == CHIPS_CT69030)) + ? 0 : (bestPSN == 1)); + vclk[1] = bestM - 2; + vclk[2] = bestN - 2; +#ifdef DEBUG + ErrorF("Freq. selected: %.2f MHz, vclk[0]=%X, vclk[1]=%X, vclk[2]=%X\n", + (float)(Clock / 1000.), vclk[0], vclk[1], vclk[2]); + ErrorF("Freq. set: %.2f MHz\n", bestFout / 1.0e6); +#endif +} + +static void +chipsSave(ScrnInfoPtr pScrn, vgaRegPtr VgaSave, CHIPSRegPtr ChipsSave) +{ + vgaHWPtr hwp = VGAHWPTR(pScrn); + CHIPSPtr cPtr = CHIPSPTR(pScrn); + int i; + unsigned char tmp; +#ifdef DEBUG + ErrorF("chipsSave\n"); +#endif + + /* set registers that we can program the controller */ + /* bank 0 */ + if (IS_HiQV(cPtr)) { + cPtr->writeXR(cPtr, 0x0E, 0x00); + } else { + cPtr->writeXR(cPtr, 0x10, 0x00); + cPtr->writeXR(cPtr, 0x11, 0x00); + tmp = cPtr->readXR(cPtr, 0x0C) & ~0x50; /* WINgine stores MSB here */ + cPtr->writeXR(cPtr, 0x0C, tmp); + } + chipsFixResume(pScrn); + tmp = cPtr->readXR(cPtr, 0x02); + cPtr->writeXR(cPtr, 0x02, tmp & ~0x18); + /* get generic registers */ + vgaHWSave(pScrn, VgaSave, VGA_SR_ALL); + + /* save clock */ + chipsClockSave(pScrn, &ChipsSave->Clock); + + /* save extended registers */ + if (IS_HiQV(cPtr)) { + for (i = 0; i < 0xFF; i++) { +#ifdef SAR04 + /* Save SAR04 multimedia register correctly */ + if (i == 0x4F) + cPtr->writeXR(cPtr, 0x4E, 0x04); +#endif + ChipsSave->XR[i] = cPtr->readXR(cPtr,i); +#ifdef DEBUG + ErrorF("XS%X - %X\n", i, ChipsSave->XR[i]); +#endif + } + for (i = 0; i < 0x80; i++) { + ChipsSave->FR[i] = cPtr->readFR(cPtr, i); +#ifdef DEBUG + ErrorF("FS%X - %X\n", i, ChipsSave->FR[i]); +#endif + } + for (i = 0; i < 0x80; i++) { + ChipsSave->MR[i] = cPtr->readMR(cPtr, i); +#ifdef DEBUG + ErrorF("MS%X - %X\n", i, ChipsSave->FR[i]); +#endif + } + /* Save CR0-CR40 even though we don't use them, so they can be + * printed */ + for (i = 0x0; i < 0x80; i++) { + ChipsSave->CR[i] = hwp->readCrtc(hwp, i); +#ifdef DEBUG + ErrorF("CS%X - %X\n", i, ChipsSave->CR[i]); +#endif + } + } else { + for (i = 0; i < 0x7D; i++) { /* don't touch XR7D and XR7F on WINGINE */ + ChipsSave->XR[i] = cPtr->readXR(cPtr, i); +#ifdef DEBUG + ErrorF("XS%X - %X\n", i, ChipsSave->XR[i]); +#endif + } + } +} + +Bool +chipsModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) +{ + CHIPSPtr cPtr = CHIPSPTR(pScrn); +#ifdef DEBUG + ErrorF("chipsModeInit\n"); +#endif +#if 0 + *(int*)0xFFFFFF0 = 0; + ErrorF("done\n"); +#endif + + chipsUnlock(pScrn); + chipsFixResume(pScrn); + + if (cPtr->Accel.UseHWCursor) + cPtr->Flags |= ChipsHWCursor; + else + cPtr->Flags &= ~ChipsHWCursor; + /* + * We need to delay cursor loading after resetting the video mode + * to give the engine a chance to recover. + */ + cPtr->cursorDelay = TRUE; + + if (IS_HiQV(cPtr)) + return chipsModeInitHiQV(pScrn, mode); + else if (IS_Wingine(cPtr)) + return chipsModeInitWingine(pScrn, mode); + else + return chipsModeInit655xx(pScrn, mode); +} + +/* + * The timing register of the C&T FP chipsets are organized + * as follows: + * The chipsets have two sets of timing registers: + * the standard horizontal and vertical timing registers for + * display size, blank start, sync start, sync end, blank end + * and total size at their default VGA locations and extensions + * and the alternate horizontal and vertical timing registers for + * display size, sync start, sync end and total size. + * In LCD and mixed (LCD+CRT) mode the alternate timing registers + * control the timing. The alternate horizontal and vertical display + * size registers are set to the physical pixel size of the display. + * Normally the alternalte registers are set by the BIOS to optimized + * values. + * While the horizontal an vertical refresh rates are fixed independent + * of the visible display size to ensure optimal performace of both + * displays they can be adapted to the screen resolution and CRT + * requirements in CRT mode by programming the standard timing registers + * in the VGA fashion. + * In LCD and mixed mode the _standard_ horizontal and vertical display + * size registers control the size of the _visible_ part of the display + * in contast to the _physical_ size of the display which is specified + * by the _alternate_ horizontal and vertical display size registers. + * The size of the visible should always be equal or less than the + * physical size. + * For the 69030 chipsets, the CRT and LCD display channels are seperate + * and so can be driven independently. + */ +static Bool +chipsModeInitHiQV(ScrnInfoPtr pScrn, DisplayModePtr mode) +{ + int i; + int lcdHTotal, lcdHDisplay; + int lcdVTotal, lcdVDisplay; + int lcdHRetraceStart, lcdHRetraceEnd; + int lcdVRetraceStart, lcdVRetraceEnd; + int lcdHSyncStart; + vgaHWPtr hwp = VGAHWPTR(pScrn); + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSRegPtr ChipsNew; + vgaRegPtr ChipsStd; + unsigned int tmp; + + ChipsNew = &cPtr->ModeReg; + ChipsStd = &hwp->ModeReg; + + + /* + * Possibly fix up the panel size, if the manufacture is stupid + * enough to set it incorrectly in text modes + */ + if (xf86ReturnOptValBool(cPtr->Options, OPTION_PANEL_SIZE, FALSE)) { + cPtr->PanelSize.HDisplay = mode->CrtcHDisplay; + cPtr->PanelSize.VDisplay = mode->CrtcVDisplay; + } + + /* generic init */ + if (!vgaHWInit(pScrn, mode)) { + ErrorF("bomb 1\n"); + return (FALSE); + } + pScrn->vtSema = TRUE; + + /* init clock */ + if (!chipsClockFind(pScrn, mode->ClockIndex, &ChipsNew->Clock)) { + ErrorF("bomb 2\n"); + return (FALSE); + } + + /* Give Warning if the dual display mode will cause problems */ + /* Note 64bit wide memory bus assumed (as in 69000 and 69030 */ + if (cPtr->UseDualChannel && ((cPtr->SecondCrtc == TRUE) || + (cPtr->Flags & ChipsDualRefresh))) { + if (((ChipsNew->Clock.FPClock + ChipsNew->Clock.Clock) * + (max(1, pScrn->bitsPerPixel >> 3) + + ((cPtr->FrameBufferSize && (cPtr->PanelType & ChipsLCD)) ? + 1 : 0)) / (8 * 0.7)) > cPtr->MemClock.Max) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Memory bandwidth requirements exceeded by dual-channel\n"); + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + " mode. Display might be corrupted!!!\n"); + } + } + + /* get C&T Specific Registers */ + for (i = 0; i < 0xFF; i++) { +#ifdef SAR04 + /* Save SAR04 multimedia register correctly */ + if (i == 0x4F) + cPtr->writeXR(cPtr, 0x4E, 0x04); +#endif + ChipsNew->XR[i] = cPtr->readXR(cPtr, i); + } + for (i = 0; i < 0x80; i++) { + ChipsNew->FR[i] = cPtr->readFR(cPtr, i); + } + for (i = 0; i < 0x80; i++) { + ChipsNew->MR[i] = cPtr->readMR(cPtr, i); + } + for (i = 0x30; i < 0x80; i++) { /* These are the CT extended CRT regs */ + ChipsNew->CR[i] = hwp->readCrtc(hwp, i); + } + + /* + * Here all of the other fields of 'ChipsNew' get filled in, to + * handle the SVGA extended registers. It is also allowable + * to override generic registers whenever necessary. + */ + + /* some generic settings */ + if (pScrn->depth == 1) { + ChipsStd->Attribute[0x10] = 0x03; /* mode */ + } else { + ChipsStd->Attribute[0x10] = 0x01; /* mode */ + } + if ((pScrn->bitsPerPixel == 16) && (cPtr->Flags & ChipsOverlay8plus16)) { + /* Make sure that the overlay isn't visible in the overscan region */ + if (ChipsStd->Attribute[0x11] == pScrn->colorKey) + ChipsStd->Attribute[0x11] = pScrn->colorKey - 1; + } else + ChipsStd->Attribute[0x11] = 0x00; /* overscan (border) color */ + ChipsStd->Attribute[0x12] = 0x0F; /* enable all color planes */ + ChipsStd->Attribute[0x13] = 0x00; /* horiz pixel panning 0 */ + + ChipsStd->Graphics[0x05] = 0x00; /* normal read/write mode */ + + /* set virtual screen width */ + tmp = pScrn->displayWidth >> 3; + if (pScrn->bitsPerPixel == 16) { + if (!(cPtr->Flags & ChipsOverlay8plus16)) + tmp <<= 1; /* double the width of the buffer */ + } else if (pScrn->bitsPerPixel == 24) { + tmp += tmp << 1; + } else if (pScrn->bitsPerPixel == 32) { + tmp <<= 2; + } else if (pScrn->bitsPerPixel < 8) { + tmp >>= 1; + } + ChipsStd->CRTC[0x13] = tmp & 0xFF; + ChipsNew->CR[0x41] = (tmp >> 8) & 0x0F; + + /* Set paging mode on the HiQV32 architecture, if required */ + if (!(cPtr->Flags & ChipsLinearSupport) || (pScrn->bitsPerPixel < 8)) + ChipsNew->XR[0x0A] |= 0x1; + + ChipsNew->XR[0x09] |= 0x1; /* Enable extended CRT registers */ + ChipsNew->XR[0x0E] = 0; /* Single map */ + ChipsNew->XR[0x40] |= 0x2; /* Don't wrap at 256kb */ + ChipsNew->XR[0x81] &= 0xF8; + if (pScrn->bitsPerPixel >= 8) { + ChipsNew->XR[0x40] |= 0x1; /* High Resolution. XR40[1] reserved? */ + ChipsNew->XR[0x81] |= 0x2; /* 256 Color Video */ + } + ChipsNew->XR[0x80] |= 0x10; /* Enable cursor output on P0 and P1 */ + if (pScrn->depth > 1) { + if (pScrn->rgbBits == 8) + ChipsNew->XR[0x80] |= 0x80; + else + ChipsNew->XR[0x80] &= ~0x80; + } + + if (abs(cPtr->MemClock.Clk - cPtr->MemClock.ProbedClk) > 50) { + /* set mem clk */ + ChipsNew->XR[0xCC] = cPtr->MemClock.xrCC; + ChipsNew->XR[0xCD] = cPtr->MemClock.xrCD; + ChipsNew->XR[0xCE] = cPtr->MemClock.xrCE; + } + + /* Set the 69030 dual channel settings */ + if (cPtr->Flags & ChipsDualChannelSupport) { + ChipsNew->FR[0x01] &= 0xFC; + if ((cPtr->SecondCrtc == FALSE) && (cPtr->PanelType & ChipsLCD)) + ChipsNew->FR[0x01] |= 0x02; + else + ChipsNew->FR[0x01] |= 0x01; + ChipsNew->FR[0x02] &= 0xCC; + if ((cPtr->SecondCrtc == TRUE) || (cPtr->Flags & ChipsDualRefresh)) + ChipsNew->FR[0x02] |= 0x01; /* Set DAC to pipe B */ + else + ChipsNew->FR[0x02] &= 0xFE; /* Set DAC to pipe A */ + + if (cPtr->PanelType & ChipsLCD) + ChipsNew->FR[0x02] |= 0x20; /* Enable the LCD output */ + if (cPtr->PanelType & ChipsCRT) + ChipsNew->FR[0x02] |= 0x10; /* Enable the CRT output */ + } + + /* linear specific */ + if (cPtr->Flags & ChipsLinearSupport) { + ChipsNew->XR[0x0A] |= 0x02; /* Linear Addressing Mode */ + ChipsNew->XR[0x20] = 0x0; /*BitBLT Draw Mode for 8 */ + ChipsNew->XR[0x05] = + (unsigned char)((cPtr->FbAddress >> 16) & 0xFF); + ChipsNew->XR[0x06] = + (unsigned char)((cPtr->FbAddress >> 24) & 0xFF); + } + + /* panel timing */ + /* By default don't set panel timings, but allow it as an option */ + if (xf86ReturnOptValBool(cPtr->Options, OPTION_USE_MODELINE, FALSE)) { + lcdHTotal = (mode->CrtcHTotal >> 3) - 5; + lcdHDisplay = (cPtr->PanelSize.HDisplay >> 3) - 1; + lcdHRetraceStart = (mode->CrtcHSyncStart >> 3); + lcdHRetraceEnd = (mode->CrtcHSyncEnd >> 3); + lcdHSyncStart = lcdHRetraceStart - 2; + + lcdVTotal = mode->CrtcVTotal - 2; + lcdVDisplay = cPtr->PanelSize.VDisplay - 1; + lcdVRetraceStart = mode->CrtcVSyncStart; + lcdVRetraceEnd = mode->CrtcVSyncEnd; + + ChipsNew->FR[0x20] = lcdHDisplay & 0xFF; + ChipsNew->FR[0x21] = lcdHRetraceStart & 0xFF; + ChipsNew->FR[0x25] = ((lcdHRetraceStart & 0xF00) >> 4) | + ((lcdHDisplay & 0xF00) >> 8); + ChipsNew->FR[0x22] = lcdHRetraceEnd & 0x1F; + ChipsNew->FR[0x23] = lcdHTotal & 0xFF; + ChipsNew->FR[0x24] = (lcdHSyncStart >> 3) & 0xFF; + ChipsNew->FR[0x26] = (ChipsNew->FR[0x26] & ~0x1F) + | ((lcdHTotal & 0xF00) >> 8) + | (((lcdHSyncStart >> 3) & 0x100) >> 4); + ChipsNew->FR[0x27] &= 0x7F; + + ChipsNew->FR[0x30] = lcdVDisplay & 0xFF; + ChipsNew->FR[0x31] = lcdVRetraceStart & 0xFF; + ChipsNew->FR[0x35] = ((lcdVRetraceStart & 0xF00) >> 4) + | ((lcdVDisplay & 0xF00) >> 8); + ChipsNew->FR[0x32] = lcdVRetraceEnd & 0x0F; + ChipsNew->FR[0x33] = lcdVTotal & 0xFF; + ChipsNew->FR[0x34] = (lcdVTotal - lcdVRetraceStart) & 0xFF; + ChipsNew->FR[0x36] = ((lcdVTotal & 0xF00) >> 8) | + (((lcdVTotal - lcdVRetraceStart) & 0x700) >> 4); + ChipsNew->FR[0x37] |= 0x80; + } + + /* Set up the extended CRT registers of the HiQV32 chips */ + ChipsNew->CR[0x30] = ((mode->CrtcVTotal - 2) & 0xF00) >> 8; + ChipsNew->CR[0x31] = ((mode->CrtcVDisplay - 1) & 0xF00) >> 8; + ChipsNew->CR[0x32] = (mode->CrtcVSyncStart & 0xF00) >> 8; + ChipsNew->CR[0x33] = (mode->CrtcVBlankStart & 0xF00) >> 8; + if ((cPtr->Chipset == CHIPS_CT69000) || (cPtr->Chipset == CHIPS_CT69030)) { + /* The 690xx has overflow bits for the horizontal values as well */ + ChipsNew->CR[0x38] = (((mode->CrtcHTotal >> 3) - 5) & 0x100) >> 8; +#if 0 + /* We need to redo the overscan voodoo from vgaHW.c */ + ChipsStd->CRTC[3] = (ChipsStd->CRTC[3] & ~0x1F) + | (((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F); + ChipsStd->CRTC[5] = (ChipsStd->CRTC[5] & ~0x80) + | ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2); + ChipsNew->CR[0x3C] = ((mode->CrtcHBlankEnd >> 3) - 1) & 0xC0; + if ((mode->CrtcHBlankEnd >> 3) == (mode->CrtcHTotal >> 3)) { + int i = (ChipsStd->CRTC[3] & 0x1F) + | ((ChipsStd->CRTC[5] & 0x80) >> 2) + | (ChipsNew->CR[0x3C] & 0xC0); + if ((i-- > (ChipsStd->CRTC[2])) && + (mode->CrtcHBlankEnd == mode->CrtcHTotal)) + i = 0; + ChipsStd->CRTC[3] = (ChipsStd->CRTC[3] & ~0x1F) | (i & 0x1F); + ChipsStd->CRTC[5] = (ChipsStd->CRTC[5] & ~0x80) | ((i << 2) &0x80); + ChipsNew->CR[0x3C] = (i & 0xC0); + } +#else + ChipsNew->CR[0x3C] = vgaHWHBlankKGA(mode, ChipsStd, 8, 0) << 6; +#endif + } else + vgaHWHBlankKGA(mode, ChipsStd, 6, 0); + vgaHWVBlankKGA(mode, ChipsStd, 8, 0); + + ChipsNew->CR[0x40] |= 0x80; + + /* centering/stretching */ + if (!xf86ReturnOptValBool(cPtr->Options, OPTION_SUSPEND_HACK, FALSE)) { + if (xf86ReturnOptValBool(cPtr->Options, OPTION_LCD_STRETCH, FALSE) || + (cPtr->Flags & ChipsOverlay8plus16)) { + ChipsNew->FR[0x40] &= 0xDF; /* Disable Horizontal stretching */ + ChipsNew->FR[0x48] &= 0xFB; /* Disable vertical stretching */ + ChipsNew->XR[0xA0] = 0x10; /* Disable cursor stretching */ + } else { + ChipsNew->FR[0x40] |= 0x21; /* Enable Horizontal stretching */ + ChipsNew->FR[0x48] |= 0x05; /* Enable vertical stretching */ + ChipsNew->XR[0xA0] = 0x70; /* Enable cursor stretching */ + if (cPtr->Accel.UseHWCursor + && cPtr->PanelSize.HDisplay && cPtr->PanelSize.VDisplay + && (cPtr->PanelSize.HDisplay != mode->CrtcHDisplay) + && (cPtr->PanelSize.VDisplay != mode->CrtcVDisplay)) { + if(cPtr->Accel.UseHWCursor) + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Disabling HW Cursor on stretched LCD\n"); + cPtr->Flags &= ~ChipsHWCursor; + } + } + } + + if ((xf86ReturnOptValBool(cPtr->Options, OPTION_LCD_CENTER, FALSE)) + || (cPtr->Flags & ChipsOverlay8plus16)) { + ChipsNew->FR[0x40] |= 0x3; /* Enable Horizontal centering */ + ChipsNew->FR[0x48] |= 0x3; /* Enable Vertical centering */ + } else { + ChipsNew->FR[0x40] &= 0xFD; /* Disable Horizontal centering */ + ChipsNew->FR[0x48] &= 0xFD; /* Disable Vertical centering */ + } + + /* sync on green */ + if (xf86ReturnOptValBool(cPtr->Options, OPTION_SYNC_ON_GREEN, FALSE)) + ChipsNew->XR[0x82] |=0x02; + + /* software mode flag */ + ChipsNew->XR[0xE2] = chipsVideoMode(((cPtr->Flags & ChipsOverlay8plus16) ? + 8 : pScrn->depth), (cPtr->PanelType & ChipsLCD) ? + min(mode->CrtcHDisplay, cPtr->PanelSize.HDisplay) : + mode->CrtcHDisplay, mode->CrtcVDisplay); +#ifdef DEBUG + ErrorF("VESA Mode: %Xh\n", ChipsNew->XR[0xE2]); +#endif + + /* sync. polarities */ + if ((mode->Flags & (V_PHSYNC | V_NHSYNC)) + && (mode->Flags & (V_PVSYNC | V_NVSYNC))) { + if (mode->Flags & (V_PHSYNC | V_NHSYNC)) { + if (mode->Flags & V_PHSYNC) + ChipsNew->FR[0x08] &= 0xBF; /* Alt. CRT Hsync positive */ + else + ChipsNew->FR[0x08] |= 0x40; /* Alt. CRT Hsync negative */ + } + if (mode->Flags & (V_PVSYNC | V_NVSYNC)) { + if (mode->Flags & V_PVSYNC) + ChipsNew->FR[0x08] &= 0x7F; /* Alt. CRT Vsync positive */ + else + ChipsNew->FR[0x08] |= 0x80; /* Alt. CRT Vsync negative */ + } + } + if (mode->Flags & (V_PCSYNC | V_NCSYNC)) { + ChipsNew->FR[0x0B] |= 0x20; + if (mode->Flags & V_PCSYNC) { + ChipsNew->FR[0x08] &= 0x7F; /* Alt. CRT Vsync positive */ + ChipsNew->FR[0x08] &= 0xBF; /* Alt. CRT Hsync positive */ + ChipsStd->MiscOutReg &= 0x7F; + ChipsStd->MiscOutReg &= 0xBF; + } else { + ChipsNew->FR[0x08] |= 0x80; /* Alt. CRT Vsync negative */ + ChipsNew->FR[0x08] |= 0x40; /* Alt. CRT Hsync negative */ + ChipsStd->MiscOutReg |= 0x40; + ChipsStd->MiscOutReg |= 0x80; + } + } + /* bpp depend */ + if ((pScrn->bitsPerPixel == 16) && (!(cPtr->Flags & ChipsOverlay8plus16))) { + ChipsNew->XR[0x81] = (ChipsNew->XR[0x81] & 0xF0) | 0x4; + if (cPtr->Flags & ChipsGammaSupport) + ChipsNew->XR[0x82] |= 0x0C; + /* 16bpp = 5-5-5 */ + ChipsNew->FR[0x10] |= 0x0C; /*Colour Panel */ + ChipsNew->XR[0x20] = 0x10; /*BitBLT Draw Mode for 16 bpp */ + if (pScrn->weight.green != 5) + ChipsNew->XR[0x81] |= 0x01; /*16bpp */ + } else if (pScrn->bitsPerPixel == 24) { + ChipsNew->XR[0x81] = (ChipsNew->XR[0x81] & 0xF0) | 0x6; + if (cPtr->Flags & ChipsGammaSupport) + ChipsNew->XR[0x82] |= 0x0C; + /* 24bpp colour */ + ChipsNew->XR[0x20] = 0x20; /*BitBLT Draw Mode for 24 bpp */ + } else if (pScrn->bitsPerPixel == 32) { + ChipsNew->XR[0x81] = (ChipsNew->XR[0x81] & 0xF0) | 0x7; + if (cPtr->Flags & ChipsGammaSupport) + ChipsNew->XR[0x82] |= 0x0C; + /* 32bpp colour */ + ChipsNew->XR[0x20] = 0x10; /*BitBLT Mode for 16bpp used at 32bpp */ + } + + /*CRT only */ + if (!(cPtr->PanelType & ChipsLCD)) { + if (mode->Flags & V_INTERLACE) { + ChipsNew->CR[0x70] = 0x80 /* set interlace */ + | (((((mode->CrtcHDisplay >> 3) - 1) >> 1) - 6) & 0x7F); + /* + ** Double VDisplay to get back the full screen value, otherwise + ** you only see half the picture. + */ + mode->CrtcVDisplay = mode->VDisplay; + tmp = ChipsStd->CRTC[7] & ~0x42; + ChipsStd->CRTC[7] = (tmp | + ((((mode->CrtcVDisplay -1) & 0x100) >> 7 ) | + (((mode->CrtcVDisplay -1) & 0x200) >> 3 ))); + ChipsStd->CRTC[0x12] = (mode->CrtcVDisplay -1) & 0xFF; + ChipsNew->CR[0x31] = ((mode->CrtcVDisplay - 1) & 0xF00) >> 8; + } else { + ChipsNew->CR[0x70] &= ~0x80; /* unset interlace */ + } + } + +#if defined(__arm32__) && defined(__NetBSD__) + if (cPtr->TVMode != XMODE_RGB) { + /* + * Put the console into TV Out mode. + */ + xf86SetTVOut(cPtr->TVMode); + + ChipsNew->CR[0x72] = (mode->CrtcHTotal >> 1) >> 3;/* First horizontal + * serration pulse */ + ChipsNew->CR[0x73] = mode->CrtcHTotal >> 3; /* Second pulse */ + ChipsNew->CR[0x74] = (((mode->HSyncEnd - mode->HSyncStart) >> 3) - 1) + & 0x1F; /* equalization pulse */ + + if (cPtr->TVMode == XMODE_PAL || cPtr->TVMode == XMODE_SECAM) { + ChipsNew->CR[0x71] = 0xA0; /* PAL support with blanking delay */ + } else { + ChipsNew->CR[0x71] = 0x20; /* NTSC support with blanking delay */ + } + } else { /* XMODE_RGB */ + /* + * Put the console into RGB Out mode. + */ + xf86SetRGBOut(); + } +#endif + + /* STN specific */ + if (IS_STN(cPtr->PanelType)) { + ChipsNew->FR[0x11] &= ~0x03; /* FRC clear */ + ChipsNew->FR[0x11] &= ~0x8C; /* Dither clear */ + ChipsNew->FR[0x11] |= 0x01; /* 16 frame FRC */ + ChipsNew->FR[0x11] |= 0x84; /* Dither */ + if ((cPtr->Flags & ChipsTMEDSupport) && + !xf86ReturnOptValBool(cPtr->Options, OPTION_NO_TMED, FALSE)) { + ChipsNew->FR[0x73] &= 0x4F; /* Clear TMED */ + ChipsNew->FR[0x73] |= 0x80; /* Enable TMED */ + ChipsNew->FR[0x73] |= 0x30; /* TMED 256 Shades of RGB */ + } + if (cPtr->PanelType & ChipsDD) /* Shift Clock Mask. Use to get */ + ChipsNew->FR[0x12] |= 0x4; /* rid of line in DSTN screens */ + } + + /* + * The zero position of the overlay does not align with the zero + * position of the display. The skew is dependent on the depth, + * display type and refresh rate. Calculate the skew before setting + * the X and Y dimensions of the overlay. These values are needed + * both by the overlay and XvImages. So calculate and store them + */ + if (cPtr->PanelType & ChipsLCD) { + cPtr->OverlaySkewX = (((ChipsNew->FR[0x23] & 0xFF) + - (ChipsNew->FR[0x20] & 0xFF) + 3) << 3) + - 1; + cPtr->OverlaySkewY = (ChipsNew->FR[0x33] + + ((ChipsNew->FR[0x36] & 0xF) << 8) + - (ChipsNew->FR[0x31] & 0xF0) + - (ChipsNew->FR[0x32] & 0x0F) + - ((ChipsNew->FR[0x35] & 0xF0) << 4)); + if (cPtr->PanelSize.HDisplay > mode->CrtcHDisplay) + cPtr->OverlaySkewX += (cPtr->PanelSize.HDisplay - + mode->CrtcHDisplay) / 2; + if (cPtr->PanelSize.VDisplay > mode->CrtcVDisplay) + cPtr->OverlaySkewY += (cPtr->PanelSize.VDisplay - + mode->CrtcVDisplay) / 2; + } else { + cPtr->OverlaySkewX = mode->CrtcHTotal - mode->CrtcHBlankStart - 9; + cPtr->OverlaySkewY = mode->CrtcVTotal - mode->CrtcVSyncEnd - 1; + + if (mode->Flags & V_INTERLACE) { + /* + * This handles 1024 and 1280 interlaced modes only. Its + * pretty arbitrary, but its what C&T recommends + */ + if (mode->CrtcHDisplay == 1024) + cPtr->OverlaySkewY += 5; + if (mode->CrtcHDisplay == 1280) + cPtr->OverlaySkewY *= 2; + + } + } + + /* mask for viewport granularity */ + + switch (pScrn->bitsPerPixel) { + case 8: + cPtr->viewportMask = ~7U; + break; + case 16: + cPtr->viewportMask = ~3U; + break; + case 24: + cPtr->viewportMask = ~7U; + break; + case 32: + cPtr->viewportMask = ~0U; + break; + default: + cPtr->viewportMask = ~7U; + } + + /* Turn off multimedia by default as it degrades performance */ + ChipsNew->XR[0xD0] &= 0x0f; + + /* Setup the video/overlay */ + if (cPtr->Flags & ChipsOverlay8plus16) { + ChipsNew->XR[0xD0] |= 0x10; /* Force the Multimedia engine on */ +#ifdef SAR04 + ChipsNew->XR[0x4F] = 0x2A; /* SAR04 >352 pixel overlay width */ +#endif + ChipsNew->MR[0x1E] &= 0xE0; /* Set Zoom and Direction */ + if ((!(cPtr->PanelType & ChipsLCD)) && (mode->Flags & V_INTERLACE)) + ChipsNew->MR[0x1E] |= 0x10; /* Interlace */ + ChipsNew->MR[0x1F] &= 0x14; /* Mask reserved bits */ + ChipsNew->MR[0x1F] |= 0x08; /* RGB 16bpp */ + if (pScrn->weight.green == 5) + ChipsNew->MR[0x1F] |= 0x01; /* RGB 15bpp */ + + ChipsNew->MR[0x20] &= 0x03; /* Mask reserved bits */ + ChipsNew->MR[0x20] |= 0x80; /* Auto Centre, Use mem ptr1 */ + ChipsNew->MR[0x22] = cPtr->FbOffset16 & 0xF8; /* Setup Pointer 1 */ + ChipsNew->MR[0x23] = (cPtr->FbOffset16 >> 8) & 0xFF; + ChipsNew->MR[0x24] = (cPtr->FbOffset16 >> 16) & 0xFF; + ChipsNew->MR[0x25] = cPtr->FbOffset16 & 0xF8; /* Setup Pointer 2 */ + ChipsNew->MR[0x26] = (cPtr->FbOffset16 >> 8) & 0xFF; + ChipsNew->MR[0x27] = (cPtr->FbOffset16 >> 16) & 0xFF; + ChipsNew->MR[0x28] = (pScrn->displayWidth >> 2) - 1; /* Width */ + ChipsNew->MR[0x34] = (pScrn->displayWidth >> 2) - 1; + + /* Left Edge of Overlay */ + ChipsNew->MR[0x2A] = cPtr->OverlaySkewX; + ChipsNew->MR[0x2B] &= 0xF8; /* Mask reserved bits */ + ChipsNew->MR[0x2B] |= ((cPtr->OverlaySkewX >> 8) & 0x7); + /* Right Edge of Overlay */ + ChipsNew->MR[0x2C] = (cPtr->OverlaySkewX + pScrn->displayWidth - + 1) & 0xFF; + ChipsNew->MR[0x2D] &= 0xF8; /* Mask reserved bits */ + ChipsNew->MR[0x2D] |= ((cPtr->OverlaySkewX + pScrn->displayWidth - + 1) >> 8) & 0x07; + /* Top Edge of Overlay */ + ChipsNew->MR[0x2E] = cPtr->OverlaySkewY; + ChipsNew->MR[0x2F] &= 0xF8; + ChipsNew->MR[0x2F] |= ((cPtr->OverlaySkewY >> 8) & 0x7); + /* Bottom Edge of Overlay*/ + ChipsNew->MR[0x30] = (cPtr->OverlaySkewY + pScrn->virtualY - 1 )& 0xFF; + ChipsNew->MR[0x31] &= 0xF8; /* Mask reserved bits */ + ChipsNew->MR[0x31] |= ((cPtr->OverlaySkewY + pScrn->virtualY - + 1 ) >> 8) & 0x07; + + ChipsNew->MR[0x3C] &= 0x18; /* Mask reserved bits */ + ChipsNew->MR[0x3C] |= 0x07; /* Enable keyed overlay window */ + ChipsNew->MR[0x3D] = 0x00; + ChipsNew->MR[0x3E] = 0x00; + ChipsNew->MR[0x3F] = pScrn->colorKey; /* 8bpp transparency key */ + ChipsNew->MR[0x40] = 0xFF; + ChipsNew->MR[0x41] = 0xFF; + ChipsNew->MR[0x42] = 0x00; + } else if (cPtr->Flags & ChipsVideoSupport) { +#if 0 /* if we do this even though video isn't playing we kill performance */ + ChipsNew->XR[0xD0] |= 0x10; /* Force the Multimedia engine on */ +#endif +#ifdef SAR04 + ChipsNew->XR[0x4F] = 0x2A; /* SAR04 >352 pixel overlay width */ +#endif + ChipsNew->MR[0x3C] &= 0x18; /* Ensure that the overlay is off */ + cPtr->VideoZoomMax = 0x100; + + if (cPtr->Chipset == CHIPS_CT65550) { + tmp = cPtr->readXR(cPtr, 0x04); + if (tmp < 0x02) /* 65550 ES0 has */ + cPtr->VideoZoomMax = 0x40; /* 0x40 max zoom */ + } + } + + /* Program the registers */ + /*vgaHWProtect(pScrn, TRUE);*/ + + if (cPtr->Chipset <= CHIPS_CT69000) { + ChipsNew->FR[0x01] &= ~0x03; + if (cPtr->PanelType & ChipsLCD) + ChipsNew->FR[0x01] |= 0x02; + else + ChipsNew->FR[0x01] |= 0x01; + } + if ((cPtr->Flags & ChipsDualChannelSupport) && + (!xf86IsEntityShared(pScrn->entityList[0]))) { + unsigned char IOSS, MSS, tmpfr01; + + + IOSS = cPtr->readIOSS(cPtr); + MSS = cPtr->readMSS(cPtr); + cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) | + IOSS_PIPE_A)); + cPtr->writeMSS(cPtr, hwp, ((cPtr->storeMSS & MSS_MASK) | + MSS_PIPE_A)); + chipsRestore(pScrn, ChipsStd, ChipsNew, FALSE); + cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) | + IOSS_PIPE_B)); + cPtr->writeMSS(cPtr, hwp, ((cPtr->storeMSS & MSS_MASK) | + MSS_PIPE_B)); + /* + * Hack:: Force Pipe-B on for dual refresh, and off elsewise + */ + tmpfr01 = ChipsNew->FR[0x01]; + ChipsNew->FR[0x01] &= 0xFC; + if (cPtr->UseDualChannel) + ChipsNew->FR[0x01] |= 0x01; + chipsRestore(pScrn, ChipsStd, ChipsNew, FALSE); + ChipsNew->FR[0x01] = tmpfr01; + cPtr->writeIOSS(cPtr, IOSS); + cPtr->writeMSS(cPtr, hwp, MSS); + } else { + chipsRestore(pScrn, ChipsStd, ChipsNew, FALSE); + } + + /*vgaHWProtect(pScrn, FALSE);*/ + usleep(100000); /* prevents cursor corruption seen on a TECRA 510 */ + + return(TRUE); +} + +static Bool +chipsModeInitWingine(ScrnInfoPtr pScrn, DisplayModePtr mode) +{ + int i, bytesPerPixel; + vgaHWPtr hwp = VGAHWPTR(pScrn); + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSRegPtr ChipsNew; + vgaRegPtr ChipsStd; + unsigned int tmp; + + ChipsNew = &cPtr->ModeReg; + ChipsStd = &hwp->ModeReg; + + bytesPerPixel = pScrn->bitsPerPixel >> 3; + + /* + * This chipset seems to have problems if + * HBlankEnd is choosen equals HTotal + */ + if (!mode->CrtcHAdjusted) + mode->CrtcHBlankEnd = min(mode->CrtcHSyncEnd, mode->CrtcHTotal - 2); + + /* correct the timings for 16/24 bpp */ + if (pScrn->bitsPerPixel == 16) { + if (!mode->CrtcHAdjusted) { + mode->CrtcHDisplay++; + mode->CrtcHDisplay <<= 1; + mode->CrtcHDisplay--; + mode->CrtcHSyncStart <<= 1; + mode->CrtcHSyncEnd <<= 1; + mode->CrtcHBlankStart <<= 1; + mode->CrtcHBlankEnd <<= 1; + mode->CrtcHTotal <<= 1; + mode->CrtcHAdjusted = TRUE; + } + } else if (pScrn->bitsPerPixel == 24) { + if (!mode->CrtcHAdjusted) { + mode->CrtcHDisplay++; + mode->CrtcHDisplay += ((mode->CrtcHDisplay) << 1); + mode->CrtcHDisplay--; + mode->CrtcHSyncStart += ((mode->CrtcHSyncStart) << 1); + mode->CrtcHSyncEnd += ((mode->CrtcHSyncEnd) << 1); + mode->CrtcHBlankStart += ((mode->CrtcHBlankStart) << 1); + mode->CrtcHBlankEnd += ((mode->CrtcHBlankEnd) << 1); + mode->CrtcHTotal += ((mode->CrtcHTotal) << 1); + mode->CrtcHAdjusted = TRUE; + } + } + + /* generic init */ + if (!vgaHWInit(pScrn, mode)) { + ErrorF("bomb 3\n"); + return (FALSE); + } + pScrn->vtSema = TRUE; + + /* init clock */ + if (!chipsClockFind(pScrn, mode->ClockIndex, &ChipsNew->Clock)) { + ErrorF("bomb 4\n"); + return (FALSE); + } + + /* get C&T Specific Registers */ + for (i = 0; i < 0x7D; i++) { /* don't touch XR7D and XR7F on WINGINE */ + ChipsNew->XR[i] = cPtr->readXR(cPtr, i); + } + + /* some generic settings */ + if (pScrn->bitsPerPixel == 1) { + ChipsStd->Attribute[0x10] = 0x03; /* mode */ + } else { + ChipsStd->Attribute[0x10] = 0x01; /* mode */ + } + ChipsStd->Attribute[0x11] = 0x00; /* overscan (border) color */ + ChipsStd->Attribute[0x12] = 0x0F; /* enable all color planes */ + ChipsStd->Attribute[0x13] = 0x00; /* horiz pixel panning 0 */ + + ChipsStd->Graphics[0x05] = 0x00; /* normal read/write mode */ + + + /* set virtual screen width */ + if (pScrn->bitsPerPixel >= 8) + ChipsStd->CRTC[0x13] = (pScrn->displayWidth * bytesPerPixel) >> 3; + else + ChipsStd->CRTC[0x13] = pScrn->displayWidth >> 4; + + + /* set C&T Specific Registers */ + /* set virtual screen width */ + if (pScrn->bitsPerPixel >= 8) + tmp = (pScrn->displayWidth >> 4) * bytesPerPixel; + else + tmp = (pScrn->displayWidth >> 5); + ChipsNew->XR[0x0D] = (tmp & 0x80) >> 5; + + ChipsNew->XR[0x04] |= 4; /* enable addr counter bits 16-17 */ + /* XR04: Memory control 1 */ + /* bit 2: Memory Wraparound */ + /* Enable CRTC addr counter bits 16-17 if set */ + + ChipsNew->XR[0x0B] |= 0x07; /* extended mode, dual pages enabled */ + ChipsNew->XR[0x0B] &= ~0x10; /* linear mode off */ + /* XR0B: CPU paging */ + /* bit 0: Memory mapping mode */ + /* VGA compatible if 0 (default) */ + /* Extended mode (mapping for > 256 kB mem) if 1 */ + /* bit 1: CPU single/dual mapping */ + /* 0, CPU uses only a single map to access (default) */ + /* 1, CPU uses two maps to access */ + /* bit 2: CPU address divide by 4 */ + + ChipsNew->XR[0x10] = 0; /* XR10: Single/low map */ + ChipsNew->XR[0x11] = 0; /* XR11: High map */ + ChipsNew->XR[0x0C] &= ~0x50; /* MSB for XR10 & XR11 */ + if (pScrn->bitsPerPixel >= 8) { + ChipsNew->XR[0x28] |= 0x10; /* 256-color video */ + } else { + ChipsNew->XR[0x28] &= 0xEF; /* 16-color video */ + } + /* set up extended display timings */ + /* in CRTonly mode this is simple: only set overflow for CR00-CR06 */ + ChipsNew->XR[0x17] = ((((mode->CrtcHTotal >> 3) - 5) & 0x100) >> 8) + | ((((mode->CrtcHDisplay >> 3) - 1) & 0x100) >> 7) + | ((((mode->CrtcHSyncStart >> 3) - 1) & 0x100) >> 6) + | ((((mode->CrtcHSyncEnd >> 3)) & 0x20) >> 2) + | ((((mode->CrtcHBlankStart >> 3) - 1) & 0x100) >> 4) + | ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x40) >> 1); + + + ChipsNew->XR[0x16] = (((mode->CrtcVTotal -2) & 0x400) >> 10 ) + | (((mode->CrtcVDisplay -1) & 0x400) >> 9 ) + | ((mode->CrtcVSyncStart & 0x400) >> 8 ) + | (((mode->CrtcVBlankStart) & 0x400) >> 6 ); + + /* set video mode */ + ChipsNew->XR[0x2B] = chipsVideoMode(pScrn->depth, mode->CrtcHDisplay, mode->CrtcVDisplay); +#ifdef DEBUG + ErrorF("VESA Mode: %Xh\n", ChipsNew->XR[0x2B]); +#endif + + /* set some linear specific registers */ + if (cPtr->Flags & ChipsLinearSupport) { + /* enable linear addressing */ + ChipsNew->XR[0x0B] &= 0xFD; /* dual page clear */ + ChipsNew->XR[0x0B] |= 0x10; /* linear mode on */ + + ChipsNew->XR[0x08] = + (unsigned char)((cPtr->FbAddress >> 16) & 0xFF); + ChipsNew->XR[0x09] = + (unsigned char)((cPtr->FbAddress >> 24) & 0xFF); + + /* general setup */ + ChipsNew->XR[0x40] = 0x01; /*BitBLT Draw Mode for 8 and 24 bpp */ + } + + /* common general setup */ + ChipsNew->XR[0x52] |= 0x01; /* Refresh count */ + ChipsNew->XR[0x0F] &= 0xEF; /* not Hi-/True-Colour */ + ChipsNew->XR[0x02] &= 0xE7; /* Attr. Cont. default access */ + /* use ext. regs. for hor. in dual */ + ChipsNew->XR[0x06] &= 0xF3; /* bpp clear */ + + /* bpp depend */ + /*XR06: Palette control */ + /* bit 0: Pixel Data Pin Diag, 0 for flat panel pix. data (def) */ + /* bit 1: Internal DAC disable */ + /* bit 3-2: Colour depth, 0 for 4 or 8 bpp, 1 for 16(5-5-5) bpp, */ + /* 2 for 24 bpp, 3 for 16(5-6-5)bpp */ + /* bit 4: Enable PC Video Overlay on colour key */ + /* bit 5: Bypass Internal VGA palette */ + /* bit 7-6: Colour reduction select, 0 for NTSC (default), */ + /* 1 for Equivalent weighting, 2 for green only, */ + /* 3 for Colour w/o reduction */ + /* XR50 Panel Format Register 1 */ + /* bit 1-0: Frame Rate Control; 00, No FRC; */ + /* 01, 16-frame FRC for colour STN and monochrome */ + /* 10, 2-frame FRC for colour TFT or monochrome; */ + /* 11, reserved */ + /* bit 3-2: Dither Enable */ + /* 00, disable dithering; 01, enable dithering */ + /* for 256 mode */ + /* 10, enable dithering for all modes; 11, reserved */ + /* bit6-4: Clock Divide (CD) */ + /* 000, Shift Clock Freq = Dot Clock Freq; */ + /* 001, SClk = DClk/2; 010 SClk = DClk/4; */ + /* 011, SClk = DClk/8; 100 SClk = DClk/16; */ + /* bit 7: TFT data width */ + /* 0, 16 bit(565RGB); 1, 24bit (888RGB) */ + if (pScrn->bitsPerPixel == 16) { + ChipsNew->XR[0x06] |= 0xC4; /*15 or 16 bpp colour */ + ChipsNew->XR[0x0F] |= 0x10; /*Hi-/True-Colour */ + ChipsNew->XR[0x40] = 0x02; /*BitBLT Draw Mode for 16 bpp */ + if (pScrn->weight.green != 5) + ChipsNew->XR[0x06] |= 0x08; /*16bpp */ + } else if (pScrn->bitsPerPixel == 24) { + ChipsNew->XR[0x06] |= 0xC8; /*24 bpp colour */ + ChipsNew->XR[0x0F] |= 0x10; /*Hi-/True-Colour */ + } + + /*CRT only: interlaced mode */ + if (mode->Flags & V_INTERLACE) { + ChipsNew->XR[0x28] |= 0x20; /* set interlace */ + /* empirical value */ + tmp = ((((mode->CrtcHDisplay >> 3) - 1) >> 1) + - 6 * (pScrn->bitsPerPixel >= 8 ? bytesPerPixel : 1 )); + ChipsNew->XR[0x19] = tmp & 0xFF; + ChipsNew->XR[0x17] |= ((tmp & 0x100) >> 1); /* overflow */ + ChipsNew->XR[0x0F] &= ~0x40; /* set SW-Flag */ + } else { + ChipsNew->XR[0x28] &= ~0x20; /* unset interlace */ + ChipsNew->XR[0x0F] |= 0x40; /* set SW-Flag */ + } + + /* Program the registers */ + /*vgaHWProtect(pScrn, TRUE);*/ + chipsRestore(pScrn, ChipsStd, ChipsNew, FALSE); + /*vgaHWProtect(pScrn, FALSE);*/ + + return (TRUE); +} + +static Bool +chipsModeInit655xx(ScrnInfoPtr pScrn, DisplayModePtr mode) +{ + int i, bytesPerPixel; + int lcdHTotal, lcdHDisplay; + int lcdVTotal, lcdVDisplay; + int lcdHRetraceStart, lcdHRetraceEnd; + int lcdVRetraceStart, lcdVRetraceEnd; + int HSyncStart, HDisplay; + int CrtcHDisplay; + vgaHWPtr hwp = VGAHWPTR(pScrn); + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSRegPtr ChipsNew; + vgaRegPtr ChipsStd; + unsigned int tmp; + + ChipsNew = &cPtr->ModeReg; + ChipsStd = &hwp->ModeReg; + + bytesPerPixel = pScrn->bitsPerPixel >> 3; + + /* + * Possibly fix up the panel size, if the manufacture is stupid + * enough to set it incorrectly in text modes + */ + if (xf86ReturnOptValBool(cPtr->Options, OPTION_PANEL_SIZE, FALSE)) { + cPtr->PanelSize.HDisplay = mode->CrtcHDisplay; + cPtr->PanelSize.VDisplay = mode->CrtcVDisplay; + } + + /* + * This chipset seems to have problems if + * HBlankEnd is choosen equals HTotal + */ + if (!mode->CrtcHAdjusted) + mode->CrtcHBlankEnd = min(mode->CrtcHSyncEnd, mode->CrtcHTotal - 2); + + /* correct the timings for 16/24 bpp */ + if (pScrn->bitsPerPixel == 16) { + if (!mode->CrtcHAdjusted) { + mode->CrtcHDisplay++; + mode->CrtcHDisplay <<= 1; + mode->CrtcHDisplay--; + mode->CrtcHSyncStart <<= 1; + mode->CrtcHSyncEnd <<= 1; + mode->CrtcHBlankStart <<= 1; + mode->CrtcHBlankEnd <<= 1; + mode->CrtcHTotal <<= 1; + mode->CrtcHAdjusted = TRUE; + } + } else if (pScrn->bitsPerPixel == 24) { + if (!mode->CrtcHAdjusted) { + mode->CrtcHDisplay++; + mode->CrtcHDisplay += ((mode->CrtcHDisplay) << 1); + mode->CrtcHDisplay--; + mode->CrtcHSyncStart += ((mode->CrtcHSyncStart) << 1); + mode->CrtcHSyncEnd += ((mode->CrtcHSyncEnd) << 1); + mode->CrtcHBlankStart += ((mode->CrtcHBlankStart) << 1); + mode->CrtcHBlankEnd += ((mode->CrtcHBlankEnd) << 1); + mode->CrtcHTotal += ((mode->CrtcHTotal) << 1); + mode->CrtcHAdjusted = TRUE; + } + } + + /* store orig. HSyncStart needed for flat panel mode */ + HSyncStart = mode->CrtcHSyncStart / (pScrn->bitsPerPixel >= 8 ? + bytesPerPixel : 1 ) - 16; + HDisplay = (mode->CrtcHDisplay + 1) / (pScrn->bitsPerPixel >= 8 ? + bytesPerPixel : 1 ); + + /* generic init */ + if (!vgaHWInit(pScrn, mode)) { + ErrorF("bomb 5\n"); + return (FALSE); + } + pScrn->vtSema = TRUE; + + /* init clock */ + if (!chipsClockFind(pScrn, mode->ClockIndex, &ChipsNew->Clock)) { + ErrorF("bomb 6\n"); + return (FALSE); + } + + /* get C&T Specific Registers */ + for (i = 0; i < 0x80; i++) { + ChipsNew->XR[i] = cPtr->readXR(cPtr, i); + } + + /* some generic settings */ + if (pScrn->bitsPerPixel == 1) { + ChipsStd->Attribute[0x10] = 0x03; /* mode */ + } else { + ChipsStd->Attribute[0x10] = 0x01; /* mode */ + } + ChipsStd->Attribute[0x11] = 0x00; /* overscan (border) color */ + ChipsStd->Attribute[0x12] = 0x0F; /* enable all color planes */ + ChipsStd->Attribute[0x13] = 0x00; /* horiz pixel panning 0 */ + + ChipsStd->Graphics[0x05] = 0x00; /* normal read/write mode */ + + /* set virtual screen width */ + if (pScrn->bitsPerPixel >= 8) + ChipsStd->CRTC[0x13] = (pScrn->displayWidth * bytesPerPixel) >> 3; + else + ChipsStd->CRTC[0x13] = pScrn->displayWidth >> 4; + + + /* set C&T Specific Registers */ + /* set virtual screen width */ + ChipsNew->XR[0x1E] = ChipsStd->CRTC[0x13]; /* alternate offset */ + /*databook is not clear about 0x1E might be needed for 65520/30 */ + if (pScrn->bitsPerPixel >= 8) + tmp = (pScrn->displayWidth * bytesPerPixel) >> 2; + else + tmp = pScrn->displayWidth >> 3; + ChipsNew->XR[0x0D] = (tmp & 0x01) | ((tmp << 1) & 0x02) ; + + ChipsNew->XR[0x04] |= 4; /* enable addr counter bits 16-17 */ + /* XR04: Memory control 1 */ + /* bit 2: Memory Wraparound */ + /* Enable CRTC addr counter bits 16-17 if set */ + + ChipsNew->XR[0x0B] |= 0x07; /* extended mode, dual pages enabled */ + ChipsNew->XR[0x0B] &= ~0x10; /* linear mode off */ + /* XR0B: CPU paging */ + /* bit 0: Memory mapping mode */ + /* VGA compatible if 0 (default) */ + /* Extended mode (mapping for > 256 kB mem) if 1 */ + /* bit 1: CPU single/dual mapping */ + /* 0, CPU uses only a single map to access (default) */ + /* 1, CPU uses two maps to access */ + /* bit 2: CPU address divide by 4 */ + + ChipsNew->XR[0x10] = 0; /* XR10: Single/low map */ + ChipsNew->XR[0x11] = 0; /* XR11: High map */ + if (pScrn->bitsPerPixel >= 8) { + ChipsNew->XR[0x28] |= 0x10; /* 256-color video */ + } else { + ChipsNew->XR[0x28] &= 0xEF; /* 16-color video */ + } + /* set up extended display timings */ + if (!(cPtr->PanelType & ChipsLCD)) { + /* in CRTonly mode this is simple: only set overflow for CR00-CR06 */ + ChipsNew->XR[0x17] = ((((mode->CrtcHTotal >> 3) - 5) & 0x100) >> 8) + | ((((mode->CrtcHDisplay >> 3) - 1) & 0x100) >> 7) + | ((((mode->CrtcHSyncStart >> 3) - 1) & 0x100) >> 6) + | ((((mode->CrtcHSyncEnd >> 3)) & 0x20) >> 2) + | ((((mode->CrtcHBlankStart >> 3) - 1) & 0x100) >> 4) + | ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x40) >> 1); + + ChipsNew->XR[0x16] = (((mode->CrtcVTotal -2) & 0x400) >> 10 ) + | (((mode->CrtcVDisplay -1) & 0x400) >> 9 ) + | ((mode->CrtcVSyncStart & 0x400) >> 8 ) + | (((mode->CrtcVBlankStart) & 0x400) >> 6 ); + } else { + /* horizontal timing registers */ + /* in LCD/dual mode use saved bios values to derive timing values if + * not told otherwise */ + if (!xf86ReturnOptValBool(cPtr->Options, OPTION_USE_MODELINE, FALSE)) { + lcdHTotal = cPtr->PanelSize.HTotal; + lcdHRetraceStart = cPtr->PanelSize.HRetraceStart; + lcdHRetraceEnd = cPtr->PanelSize.HRetraceEnd; + if (pScrn->bitsPerPixel == 16) { + lcdHRetraceStart <<= 1; + lcdHRetraceEnd <<= 1; + lcdHTotal <<= 1; + } else if (pScrn->bitsPerPixel == 24) { + lcdHRetraceStart += (lcdHRetraceStart << 1); + lcdHRetraceEnd += (lcdHRetraceEnd << 1); + lcdHTotal += (lcdHTotal << 1); + } + lcdHRetraceStart -=8; /* HBlank = HRetrace - 1: for */ + lcdHRetraceEnd -=8; /* compatibility with vgaHW.c */ + } else { + /* use modeline values if bios values don't work */ + lcdHTotal = mode->CrtcHTotal; + lcdHRetraceStart = mode->CrtcHSyncStart; + lcdHRetraceEnd = mode->CrtcHSyncEnd; + } + /* The chip takes the size of the visible display area from the + * CRTC values. We use bios screensize for LCD in LCD/dual mode + * wether or not we use modeline for LCD. This way we can specify + * always specify a smaller than default display size on LCD + * by writing it to the CRTC registers. */ + lcdHDisplay = cPtr->PanelSize.HDisplay; + if (pScrn->bitsPerPixel == 16) { + lcdHDisplay++; + lcdHDisplay <<= 1; + lcdHDisplay--; + } else if (pScrn->bitsPerPixel == 24) { + lcdHDisplay++; + lcdHDisplay += (lcdHDisplay << 1); + lcdHDisplay--; + } + lcdHTotal = (lcdHTotal >> 3) - 5; + lcdHDisplay = (lcdHDisplay >> 3) - 1; + lcdHRetraceStart = (lcdHRetraceStart >> 3); + lcdHRetraceEnd = (lcdHRetraceEnd >> 3); + /* This ugly hack is needed because CR01 and XR1C share the 8th bit!*/ + CrtcHDisplay = ((mode->CrtcHDisplay >> 3) - 1); + if ((lcdHDisplay & 0x100) != (CrtcHDisplay & 0x100)) { + xf86ErrorF("This display configuration might cause problems !\n"); + lcdHDisplay = 255; + } + + /* now init register values */ + ChipsNew->XR[0x17] = (((lcdHTotal) & 0x100) >> 8) + | ((lcdHDisplay & 0x100) >> 7) + | ((lcdHRetraceStart & 0x100) >> 6) + | (((lcdHRetraceEnd) & 0x20) >> 2); + + ChipsNew->XR[0x19] = lcdHRetraceStart & 0xFF; + ChipsNew->XR[0x1A] = lcdHRetraceEnd & 0x1F; + + /* XR1B: Alternate horizontal total */ + /* used in all flat panel mode with horiz. compression disabled, */ + /* CRT CGA text and graphic modes and Hercules graphics mode */ + /* similar to CR00, actual value - 5 */ + ChipsNew->XR[0x1B] = lcdHTotal & 0xFF; + + /*XR1C: Alternate horizontal blank start (CRT mode) */ + /* /horizontal panel size (FP mode) */ + /* FP horizontal panel size (FP mode), */ + /* actual value - 1 (in characters unit) */ + /* CRT horizontal blank start (CRT mode) */ + /* similar to CR02, actual value - 1 */ + ChipsNew->XR[0x1C] = lcdHDisplay & 0xFF; + + if (xf86ReturnOptValBool(cPtr->Options, OPTION_USE_MODELINE, FALSE)) { + /* for ext. packed pixel mode on 64520/64530 */ + /* no need to rescale: used only in 65530 */ + ChipsNew->XR[0x21] = lcdHRetraceStart & 0xFF; + ChipsNew->XR[0x22] = lcdHRetraceEnd & 0x1F; + ChipsNew->XR[0x23] = lcdHTotal & 0xFF; + + /* vertical timing registers */ + lcdVTotal = mode->CrtcVTotal - 2; + lcdVDisplay = cPtr->PanelSize.VDisplay - 1; + lcdVRetraceStart = mode->CrtcVSyncStart; + lcdVRetraceEnd = mode->CrtcVSyncEnd; + + ChipsNew->XR[0x64] = lcdVTotal & 0xFF; + ChipsNew->XR[0x66] = lcdVRetraceStart & 0xFF; + ChipsNew->XR[0x67] = lcdVRetraceEnd & 0x0F; + ChipsNew->XR[0x68] = lcdVDisplay & 0xFF; + ChipsNew->XR[0x65] = ((lcdVTotal & 0x100) >> 8) + | ((lcdVDisplay & 0x100) >> 7) + | ((lcdVRetraceStart & 0x100) >> 6) + | ((lcdVRetraceStart & 0x400) >> 7) + | ((lcdVTotal & 0x400) >> 6) + | ((lcdVTotal & 0x200) >> 4) + | ((lcdVDisplay & 0x200) >> 3) + | ((lcdVRetraceStart & 0x200) >> 2); + + /* + * These are important: 0x2C specifies the numbers of lines + * (hsync pulses) between vertical blank start and vertical + * line total, 0x2D specifies the number of clock ticks? to + * horiz. blank start ( caution ! 16bpp/24bpp modes: that's + * why we need HSyncStart - can't use mode->CrtcHSyncStart) + */ + tmp = ((cPtr->PanelType & ChipsDD) && !(ChipsNew->XR[0x6F] & 0x02)) + ? 1 : 0; /* double LP delay, FLM: 2 lines iff DD+no acc*/ + /* Currently we support 2 FLM schemes: #1: FLM coincides with + * VTotal ie. the delay is programmed to the difference bet- + * ween lctVTotal and lcdVRetraceStart. #2: FLM coincides + * lcdVRetraceStart - in this case FLM delay will be turned + * off. To decide which scheme to use we compare the value of + * XR2C set by the bios to the two schemes. The one that fits + * better will be used. + */ + + if (ChipsNew->XR[0x2C] < abs((cPtr->PanelSize.VTotal - + cPtr->PanelSize.VRetraceStart - tmp - 1) - + ChipsNew->XR[0x2C])) + ChipsNew->XR[0x2F] |= 0x80; /* turn FLM delay off */ + ChipsNew->XR[0x2C] = lcdVTotal - lcdVRetraceStart - tmp; + /*ChipsNew->XR[0x2D] = (HSyncStart >> (3 - tmp)) & 0xFF;*/ + ChipsNew->XR[0x2D] = (HDisplay >> (3 - tmp)) & 0xFF; + ChipsNew->XR[0x2F] = (ChipsNew->XR[0x2F] & 0xDF) + | (((HSyncStart >> (3 - tmp)) & 0x100) >> 3); + } + + /* set stretching/centering */ + if (!xf86ReturnOptValBool(cPtr->Options, OPTION_SUSPEND_HACK, FALSE)) { + ChipsNew->XR[0x51] |= 0x40; /* enable FP compensation */ + ChipsNew->XR[0x55] |= 0x01; /* enable horiz. compensation */ + ChipsNew->XR[0x57] |= 0x01; /* enable horiz. compensation */ + if (xf86ReturnOptValBool(cPtr->Options, OPTION_LCD_STRETCH, + FALSE)) { + if (mode->CrtcHDisplay < 1489) /* HWBug */ + ChipsNew->XR[0x55] |= 0x02; /* enable h-centering */ + else if (pScrn->bitsPerPixel == 24) + ChipsNew->XR[0x56] = (lcdHDisplay - CrtcHDisplay) >> 1; + } else { + ChipsNew->XR[0x55] &= 0xFD; /* disable h-centering */ + ChipsNew->XR[0x56] = 0; + } + ChipsNew->XR[0x57] = 0x03; /* enable v-comp disable v-stretch */ + if (!xf86ReturnOptValBool(cPtr->Options, OPTION_LCD_STRETCH, + FALSE)) { + ChipsNew->XR[0x55] |= 0x20; /* enable h-comp disable h-double*/ + ChipsNew->XR[0x57] |= 0x60; /* Enable vertical stretching */ + tmp = (mode->CrtcVDisplay / (cPtr->PanelSize.VDisplay - + mode->CrtcVDisplay + 1)); + if (tmp) { + if (cPtr->PanelSize.HDisplay + && cPtr->PanelSize.VDisplay + && (cPtr->PanelSize.HDisplay != mode->CrtcHDisplay) + && (cPtr->PanelSize.VDisplay != mode->CrtcVDisplay)) { + /* Possible H/W bug? */ + if(cPtr->Accel.UseHWCursor) + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Disabling HW Cursor on stretched LCD\n"); + cPtr->Flags &= ~ChipsHWCursor; + } + } + if (cPtr->Flags & ChipsHWCursor) + tmp = (tmp == 0 ? 1 : tmp); /* Bug when doubling */ + ChipsNew->XR[0x5A] = tmp > 0x0F ? 0 : (unsigned char)tmp; + } else { + ChipsNew->XR[0x55] &= 0xDF; /* disable h-comp, h-double */ + ChipsNew->XR[0x57] &= 0x9F; /* disable vertical stretching */ + } + } + } + + /* set video mode */ + ChipsNew->XR[0x2B] = chipsVideoMode(pScrn->depth, (cPtr->PanelType & ChipsLCD) ? + min(HDisplay, cPtr->PanelSize.HDisplay) : HDisplay,cPtr->PanelSize.VDisplay); +#ifdef DEBUG + ErrorF("VESA Mode: %Xh\n", ChipsNew->XR[0x2B]); +#endif + + /* set some linear specific registers */ + if (cPtr->Flags & ChipsLinearSupport) { + /* enable linear addressing */ + ChipsNew->XR[0x0B] &= 0xFD; /* dual page clear */ + ChipsNew->XR[0x0B] |= 0x10; /* linear mode on */ + if (cPtr->Chipset == CHIPS_CT65535) + ChipsNew->XR[0x08] = (unsigned char)(cPtr->FbAddress >> 17); + else if (cPtr->Chipset > CHIPS_CT65535) + ChipsNew->XR[0x08] = (unsigned char)(cPtr->FbAddress >> 20); + else { + /* Its probably set correctly by BIOS anyway. Leave it alone */ + /* 65525 - 65530 require XR04[6] set for greater than 512k of */ + /* ram. We only correct obvious bugs; VL probably uses MEMR/MEMW*/ + if (cPtr->Bus == ChipsISA) + ChipsNew->XR[0x04] &= ~0x40; /* A19 sceme */ + if (pScrn->videoRam > 512) + ChipsNew->XR[0x04] |= 0x40; /* MEMR/MEMW sceme */ + } + + /* general setup */ + ChipsNew->XR[0x03] |= 0x08; /* High bandwidth on 65548 */ + ChipsNew->XR[0x40] = 0x01; /*BitBLT Draw Mode for 8 and 24 bpp */ + } + + /* common general setup */ + ChipsNew->XR[0x52] |= 0x01; /* Refresh count */ + ChipsNew->XR[0x0F] &= 0xEF; /* not Hi-/True-Colour */ + ChipsNew->XR[0x02] |= 0x01; /* 16bit CPU Memory Access */ + ChipsNew->XR[0x02] &= 0xE3; /* Attr. Cont. default access */ + /* use ext. regs. for hor. in dual */ + ChipsNew->XR[0x06] &= 0xF3; /* bpp clear */ + + /* PCI */ + if (cPtr->Bus == ChipsPCI) + ChipsNew->XR[0x03] |= 0x40; /*PCI burst */ + + /* sync. polarities */ + if ((mode->Flags & (V_PHSYNC | V_NHSYNC)) + && (mode->Flags & (V_PVSYNC | V_NVSYNC))) { + if (mode->Flags & (V_PHSYNC | V_NHSYNC)) { + if (mode->Flags & V_PHSYNC) { + ChipsNew->XR[0x55] &= 0xBF; /* CRT Hsync positive */ + } else { + ChipsNew->XR[0x55] |= 0x40; /* CRT Hsync negative */ + } + } + if (mode->Flags & (V_PVSYNC | V_NVSYNC)) { + if (mode->Flags & V_PVSYNC) { + ChipsNew->XR[0x55] &= 0x7F; /* CRT Vsync positive */ + } else { + ChipsNew->XR[0x55] |= 0x80; /* CRT Vsync negative */ + } + } + } + + /* bpp depend */ + /*XR06: Palette control */ + /* bit 0: Pixel Data Pin Diag, 0 for flat panel pix. data (def) */ + /* bit 1: Internal DAC disable */ + /* bit 3-2: Colour depth, 0 for 4 or 8 bpp, 1 for 16(5-5-5) bpp, */ + /* 2 for 24 bpp, 3 for 16(5-6-5)bpp */ + /* bit 4: Enable PC Video Overlay on colour key */ + /* bit 5: Bypass Internal VGA palette */ + /* bit 7-6: Colour reduction select, 0 for NTSC (default), */ + /* 1 for Equivalent weighting, 2 for green only, */ + /* 3 for Colour w/o reduction */ + /* XR50 Panel Format Register 1 */ + /* bit 1-0: Frame Rate Control; 00, No FRC; */ + /* 01, 16-frame FRC for colour STN and monochrome */ + /* 10, 2-frame FRC for colour TFT or monochrome; */ + /* 11, reserved */ + /* bit 3-2: Dither Enable */ + /* 00, disable dithering; 01, enable dithering */ + /* for 256 mode */ + /* 10, enable dithering for all modes; 11, reserved */ + /* bit6-4: Clock Divide (CD) */ + /* 000, Shift Clock Freq = Dot Clock Freq; */ + /* 001, SClk = DClk/2; 010 SClk = DClk/4; */ + /* 011, SClk = DClk/8; 100 SClk = DClk/16; */ + /* bit 7: TFT data width */ + /* 0, 16 bit(565RGB); 1, 24bit (888RGB) */ + if (pScrn->bitsPerPixel == 16) { + ChipsNew->XR[0x06] |= 0xC4; /*15 or 16 bpp colour */ + ChipsNew->XR[0x0F] |= 0x10; /*Hi-/True-Colour */ + ChipsNew->XR[0x40] = 0x02; /*BitBLT Draw Mode for 16 bpp */ + if (pScrn->weight.green != 5) + ChipsNew->XR[0x06] |= 0x08; /*16bpp */ + } else if (pScrn->bitsPerPixel == 24) { + ChipsNew->XR[0x06] |= 0xC8; /*24 bpp colour */ + ChipsNew->XR[0x0F] |= 0x10; /*Hi-/True-Colour */ + if (xf86ReturnOptValBool(cPtr->Options, OPTION_18_BIT_BUS, FALSE)) { + ChipsNew->XR[0x50] &= 0x7F; /*18 bit TFT data width */ + } else { + ChipsNew->XR[0x50] |= 0x80; /*24 bit TFT data width */ + } + } + + /*CRT only: interlaced mode */ + if (!(cPtr->PanelType & ChipsLCD)) { + if (mode->Flags & V_INTERLACE){ + ChipsNew->XR[0x28] |= 0x20; /* set interlace */ + /* empirical value */ + tmp = ((((mode->CrtcHDisplay >> 3) - 1) >> 1) + - 6 * (pScrn->bitsPerPixel >= 8 ? bytesPerPixel : 1 )); + if(cPtr->Chipset < CHIPS_CT65535) + ChipsNew->XR[0x19] = tmp & 0xFF; + else + ChipsNew->XR[0x29] = tmp & 0xFF; + ChipsNew->XR[0x0F] &= ~0x40; /* set SW-Flag */ + } else { + ChipsNew->XR[0x28] &= ~0x20; /* unset interlace */ + ChipsNew->XR[0x0F] |= 0x40; /* set SW-Flag */ + } + } + + /* STN specific */ + if (IS_STN(cPtr->PanelType)) { + ChipsNew->XR[0x50] &= ~0x03; /* FRC clear */ + ChipsNew->XR[0x50] |= 0x01; /* 16 frame FRC */ + ChipsNew->XR[0x50] &= ~0x0C; /* Dither clear */ + ChipsNew->XR[0x50] |= 0x08; /* Dither all modes */ + if (cPtr->Chipset == CHIPS_CT65548) { + ChipsNew->XR[0x03] |= 0x20; /* CRT I/F priority */ + ChipsNew->XR[0x04] |= 0x10; /* RAS precharge 65548 */ + } + } + + /* This stuff was emprically derived several years ago. Not sure its + * still needed, and I'd love to get rid of it as its ugly + */ + switch (cPtr->Chipset) { + case CHIPS_CT65545: /*jet mini *//*DEC HighNote Ultra DSTN */ + ChipsNew->XR[0x03] |= 0x10; /* do not hold off CPU for palette acc*/ + break; + case CHIPS_CT65546: /*CT 65546, only for Toshiba */ + ChipsNew->XR[0x05] |= 0x80; /* EDO RAM enable */ + break; + } + + if (cPtr->PanelType & ChipsLCD) + ChipsNew->XR[0x51] |= 0x02; + else + ChipsNew->XR[0x51] &= ~0x02; + + /* Program the registers */ + /*vgaHWProtect(pScrn, TRUE);*/ + chipsRestore(pScrn, ChipsStd, ChipsNew, FALSE); + /*vgaHWProtect(pScrn, FALSE);*/ + + return (TRUE); +} + +static void +chipsRestore(ScrnInfoPtr pScrn, vgaRegPtr VgaReg, CHIPSRegPtr ChipsReg, + Bool restoreFonts) +{ + vgaHWPtr hwp = VGAHWPTR(pScrn); + CHIPSPtr cPtr = CHIPSPTR(pScrn); + unsigned char tmp = 0; + + /*vgaHWProtect(pScrn, TRUE);*/ + + /* set registers so that we can program the controller */ + if (IS_HiQV(cPtr)) { + cPtr->writeXR(cPtr, 0x0E, 0x00); + if (cPtr->Flags & ChipsDualChannelSupport) { + tmp = cPtr->readFR(cPtr, 0x01); /* Disable pipeline */ + cPtr->writeFR(cPtr, 0x01, (tmp & 0xFC)); + cPtr->writeFR(cPtr, 0x02, 0x00); /* CRT/FP off */ + } + } else { + cPtr->writeXR(cPtr, 0x10, 0x00); + cPtr->writeXR(cPtr, 0x11, 0x00); + tmp = cPtr->readXR(cPtr, 0x0C) & ~0x50; /* WINgine stores MSB here */ + cPtr->writeXR(cPtr, 0x0C, tmp); + cPtr->writeXR(cPtr, 0x15, 0x00); /* unprotect all registers */ + tmp = cPtr->readXR(cPtr, 0x14); + cPtr->writeXR(cPtr, 0x14, tmp & ~0x20); /* enable vsync on ST01 */ + } + + chipsFixResume(pScrn); + + /* + * Wait for vsync if sequencer is running - stop sequencer. + * Only do if sync reset is ignored. Dual pipeline capable + * chips have pipeline forced off here, so we don't care. + */ + if ((cPtr->SyncResetIgn) && (!(cPtr->Flags & ChipsDualChannelSupport))) { + while (((hwp->readST01(hwp)) & 0x08) == 0x08); /* VSync off */ + while (((hwp->readST01(hwp)) & 0x08) == 0x00); /* VSync on */ + hwp->writeSeq(hwp, 0x07, 0x00); /* reset hsync - just in case... */ + } + + /* set the clock */ + chipsClockLoad(pScrn, &ChipsReg->Clock); + /* chipsClockLoad() sets this so we don't want vgaHWRestore() change it */ + VgaReg->MiscOutReg = inb(cPtr->PIOBase + 0x3CC); + + /* set extended regs */ + chipsRestoreExtendedRegs(pScrn, ChipsReg); +#if 0 + /* if people complain about lock ups or blank screens -- reenable */ + /* set CRTC registers - do it before sequencer restarts */ + for (i=0; i<25; i++) + hwp->writeCrtc(hwp, i, VgaReg->CRTC[i]); +#endif + /* set generic registers */ + /* + * Enabling writing to the colourmap causes 69030's to lock. + * Anyone care to explain to me why ???? + */ + if (cPtr->Flags & ChipsDualChannelSupport) { + /* Enable pipeline if needed */ + cPtr->writeFR(cPtr, 0x01, ChipsReg->FR[0x01]); + cPtr->writeFR(cPtr, 0x02, ChipsReg->FR[0x02]); + vgaHWRestore(pScrn, VgaReg, VGA_SR_MODE | + (restoreFonts ? VGA_SR_FONTS : 0)); + } else { + vgaHWRestore(pScrn, VgaReg, VGA_SR_MODE | VGA_SR_CMAP | + (restoreFonts ? VGA_SR_FONTS : 0)); + } + + /* set stretching registers */ + if (IS_HiQV(cPtr)) { + chipsRestoreStretching(pScrn, (unsigned char)ChipsReg->FR[0x40], + (unsigned char)ChipsReg->FR[0x48]); +#if 0 + /* if people report about stretching not working -- reenable */ + /* why twice ? : + * sometimes the console is not well restored even if these registers + * are good, re-write the registers works around it + */ + chipsRestoreStretching(pScrn, (unsigned char)ChipsReg->FR[0x40], + (unsigned char)ChipsReg->FR[0x48]); +#endif + } else if (!IS_Wingine(cPtr)) + chipsRestoreStretching(pScrn, (unsigned char)ChipsReg->XR[0x55], + (unsigned char)ChipsReg->XR[0x57]); + + /* perform a synchronous reset */ + if (!cPtr->SyncResetIgn) { + if (!IS_HiQV(cPtr)) { + /* enable syncronous reset on 655xx */ + tmp = cPtr->readXR(cPtr, 0x0E); + cPtr->writeXR(cPtr, 0x0E, tmp & 0x7F); + } + hwp->writeSeq(hwp, 0x00, 0x01); + usleep(10000); + hwp->writeSeq(hwp, 0x00, 0x03); + if (!IS_HiQV(cPtr)) + cPtr->writeXR(cPtr, 0x0E, tmp); + } + /* Flag valid start address, if using CRT extensions */ + if (IS_HiQV(cPtr) && (ChipsReg->XR[0x09] & 0x1) == 0x1) { + tmp = hwp->readCrtc(hwp, 0x40); + hwp->writeCrtc(hwp, 0x40, tmp | 0x80); + } + + /* Fix resume again here, as Nozomi seems to need it */ + chipsFixResume(pScrn); + /*vgaHWProtect(pScrn, FALSE);*/ + +#if 0 + /* Enable pipeline if needed */ + if (cPtr->Flags & ChipsDualChannelSupport) { + cPtr->writeFR(cPtr, 0x01, ChipsReg->FR[0x01]); + cPtr->writeFR(cPtr, 0x02, ChipsReg->FR[0x02]); + } +#endif +} + +static void +chipsRestoreExtendedRegs(ScrnInfoPtr pScrn, CHIPSRegPtr Regs) +{ + vgaHWPtr hwp = VGAHWPTR(pScrn); + CHIPSPtr cPtr = CHIPSPTR(pScrn); + int i; + unsigned char tmp; + + if (IS_HiQV(cPtr)) { + /* set extended regs */ + for (i = 0; i < 0x43; i++) { + if ((cPtr->readXR(cPtr, i)) != Regs->XR[i]) + cPtr->writeXR(cPtr, i, Regs->XR[i]); + } + + /* Set SAR04 multimedia register correctly */ + if ((cPtr->Flags & ChipsOverlay8plus16) + || (cPtr->Flags & ChipsVideoSupport)) { +#ifdef SAR04 + cPtr->writeXR(cPtr, 0x4E, 0x04); + if (cPtr->readXR(cPtr, 0x4F) != Regs->XR[0x4F]) + cPtr->writeXR(cPtr, 0x4F, Regs->XR[0x4F]); +#endif + } + + /* Don't touch reserved memory control registers */ + for (i = 0x50; i < 0xBF; i++) { + if ((cPtr->readXR(cPtr, i)) != Regs->XR[i]) + cPtr->writeXR(cPtr, i, Regs->XR[i]); + } + /* Don't touch VCLK regs, but fix up MClk */ + + /* set mem clock */ + tmp = cPtr->readXR(cPtr, 0xCE); /* Select Fixed MClk before */ + cPtr->writeXR(cPtr, 0xCE, tmp & 0x7F); + if ((cPtr->readXR(cPtr, 0xCC)) != Regs->XR[0xCC]) + cPtr->writeXR(cPtr, 0xCC, Regs->XR[0xCC]); + if ((cPtr->readXR(cPtr, 0xCD)) != Regs->XR[0xCD]) + cPtr->writeXR(cPtr, 0xCD, Regs->XR[0xCD]); + if ((cPtr->readXR(cPtr, 0xCE)) != Regs->XR[0xCE]) + cPtr->writeXR(cPtr, 0xCE, Regs->XR[0xCE]); + + /* set flat panel regs. */ + for (i = 0xD0; i < 0xFF; i++) { + if ((cPtr->readXR(cPtr, i)) != Regs->XR[i]) + cPtr->writeXR(cPtr, i, Regs->XR[i]); + } + + for (i = 0; i < 0x80; i++) { + /* Don't touch alternate clock select reg. */ + if ((i == 0x01) && (cPtr->Chipset == CHIPS_CT69030)) { + /* restore the non clock bits */ + tmp = cPtr->readFR(cPtr, 0x01); + cPtr->writeFR(cPtr, 0x01, ((Regs->FR[0x01] & 0xF0) | + (tmp & ~0xF0))); + continue; + } + + if ((i == 0x02) && (cPtr->Chipset == CHIPS_CT69030)) + /* keep pipeline disabled till we are ready */ + continue; + + if ((i == 0x03) && (cPtr->Chipset != CHIPS_CT69030)) { + /* restore the non clock bits */ + tmp = cPtr->readFR(cPtr, 0x03); + cPtr->writeFR(cPtr, 0x03, ((Regs->FR[0x03] & 0xC3) | + (tmp & ~0xC3))); + continue; + } + + if ((i > 0x03) && (cPtr->Chipset != CHIPS_CT69030) && + (cPtr->SecondCrtc == TRUE)) + continue; + + if ( (i == 0x40) || (i==0x48)) { + /* !! set stretching but disable compensation */ + cPtr->writeFR(cPtr, i, Regs->FR[i] & 0xFE); + continue ; /* some registers must be set before FR40/FR48 */ + } + if ((cPtr->readFR(cPtr, i)) != Regs->FR[i]) { + cPtr->writeFR(cPtr, i, Regs->FR[i]); + } + } + + /* set the multimedia regs */ + for (i = 0x02; i < 0x80; i++) { + if ( (i == 0x43) || (i == 0x44)) + continue; + if ((cPtr->readMR(cPtr, i)) != Regs->MR[i]) + cPtr->writeMR(cPtr, i, Regs->MR[i]); + } + + /* set extended crtc regs. */ + for (i = 0x30; i < 0x80; i++) { + if ((hwp->readCrtc(hwp, i)) != Regs->CR[i]) + hwp->writeCrtc(hwp, i, Regs->CR[i]); + } + } else { + /* set extended regs. */ + for (i = 0; i < 0x30; i++) { + if ((cPtr->readXR(cPtr, i)) != Regs->XR[i]) + cPtr->writeXR(cPtr, i, Regs->XR[i]); + } + cPtr->writeXR(cPtr, 0x15, 0x00); /* unprotect just in case ... */ + /* Don't touch MCLK/VCLK regs. */ + for (i = 0x34; i < 0x54; i++) { + if ((cPtr->readXR(cPtr, i)) != Regs->XR[i]) + cPtr->writeXR(cPtr, i, Regs->XR[i]); + } + tmp = cPtr->readXR(cPtr, 0x54); /* restore the non clock bits */ + cPtr->writeXR(cPtr, 0x54, ((Regs->XR[0x54] & 0xF3) | (tmp & ~0xF3))); + cPtr->writeXR(cPtr, 0x55, Regs->XR[0x55] & 0xFE); /* h-comp off */ + cPtr->writeXR(cPtr, 0x56, Regs->XR[0x56]); + cPtr->writeXR(cPtr, 0x57, Regs->XR[0x57] & 0xFE); /* v-comp off */ + for (i=0x58; i < 0x7D; i++) {/* don't touch XR7D and XR7F on WINGINE */ + if ((cPtr->readXR(cPtr, i)) != Regs->XR[i]) + cPtr->writeXR(cPtr, i, Regs->XR[i]); + } + } +#ifdef DEBUG + /* debug - dump out all the extended registers... */ + if (IS_HiQV(cPtr)) { + for (i = 0; i < 0xFF; i++) { + ErrorF("XR%X - %X : %X\n", i, Regs->XR[i], + cPtr->readXR(cPtr, i)); + } + for (i = 0; i < 0x80; i++) { + ErrorF("FR%X - %X : %X\n", i, Regs->FR[i], + cPtr->readFR(cPtr, i)); + } + } else { + for (i = 0; i < 0x80; i++) { + ErrorF("XR%X - %X : %X\n", i, Regs->XR[i], + cPtr->readXR(cPtr, i)); + } + } +#endif +} + +static void +chipsRestoreStretching(ScrnInfoPtr pScrn, unsigned char ctHorizontalStretch, + unsigned char ctVerticalStretch) +{ + unsigned char tmp; + CHIPSPtr cPtr = CHIPSPTR(pScrn); + + /* write to regs. */ + if (IS_HiQV(cPtr)) { + tmp = cPtr->readFR(cPtr, 0x48); + cPtr->writeFR(cPtr, 0x48, (tmp & 0xFE) | (ctVerticalStretch & 0x01)); + tmp = cPtr->readFR(cPtr, 0x40); + cPtr->writeFR(cPtr, 0x40, (tmp & 0xFE) | (ctHorizontalStretch & 0x01)); + } else { + tmp = cPtr->readXR(cPtr, 0x55); + cPtr->writeXR(cPtr, 0x55, (tmp & 0xFE) | (ctHorizontalStretch & 0x01)); + tmp = cPtr->readXR(cPtr, 0x57); + cPtr->writeXR(cPtr, 0x57, (tmp & 0xFE) | (ctVerticalStretch & 0x01)); + } + + usleep(20000); /* to be active */ +} + +static int +chipsVideoMode(int depth, int displayHSize, + int displayVSize) +{ + /* 4 bpp 8 bpp 16 bpp 18 bpp 24 bpp 32 bpp */ + /* 640 0x20 0x30 0x40 - 0x50 - */ + /* 800 0x22 0x32 0x42 - 0x52 - */ + /*1024 0x24 0x34 0x44 - 0x54 - for 1024x768 */ + /*1024 - 0x36 0x47 - 0x56 - for 1024x600 */ + /*1152 0x27 0x37 0x47 - 0x57 - */ + /*1280 0x28 0x38 0x49 - - - */ + /*1600 0x2C 0x3C 0x4C 0x5D - - */ + /*This value is only for BIOS.... */ + + int videoMode = 0; + + switch (depth) { + case 1: + case 4: + videoMode = 0x20; + break; + case 8: + videoMode = 0x30; + break; + case 15: + videoMode = 0x40; + break; + case 16: + videoMode = 0x41; + break; + default: + videoMode = 0x50; + break; + } + + switch (displayHSize) { + case 800: + videoMode |= 0x02; + break; + case 1024: + videoMode |= 0x04; + if(displayVSize < 768) + videoMode |= 0x02; + break; + case 1152: + videoMode |= 0x07; + break; + case 1280: + videoMode |= 0x08; + break; + case 1600: + videoMode |= 0x0C; /*0x0A??*/ + break; + } + + return videoMode; +} + + +/* + * Map the framebuffer and MMIO memory. + */ + +static Bool +chipsMapMem(ScrnInfoPtr pScrn) +{ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + vgaHWPtr hwp = VGAHWPTR(pScrn); + CHIPSEntPtr cPtrEnt; + + if (cPtr->Flags & ChipsLinearSupport) { + if (cPtr->UseMMIO) { + if (IS_HiQV(cPtr)) { + if (cPtr->Bus == ChipsPCI) + cPtr->MMIOBase = xf86MapPciMem(pScrn->scrnIndex, + VIDMEM_MMIO_32BIT,cPtr->PciTag, cPtr->IOAddress, + 0x20000L); + else + cPtr->MMIOBase = xf86MapVidMem(pScrn->scrnIndex, + VIDMEM_MMIO_32BIT, cPtr->IOAddress, 0x20000L); + } else { + if (cPtr->Bus == ChipsPCI) + cPtr->MMIOBase = xf86MapPciMem(pScrn->scrnIndex, + VIDMEM_MMIO_32BIT, cPtr->PciTag, cPtr->IOAddress, + 0x10000L); + else + cPtr->MMIOBase = xf86MapVidMem(pScrn->scrnIndex, + VIDMEM_MMIO_32BIT, cPtr->IOAddress, 0x10000L); + } + + if (cPtr->MMIOBase == NULL) + return FALSE; + } + if (cPtr->FbMapSize) { + unsigned long Addr = (unsigned long)cPtr->FbAddress; + unsigned int Map = cPtr->FbMapSize; + + if ((cPtr->Flags & ChipsDualChannelSupport) && + (xf86IsEntityShared(pScrn->entityList[0]))) { + cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0], + CHIPSEntityIndex)->ptr; + if(cPtr->SecondCrtc == FALSE) { + Addr = cPtrEnt->masterFbAddress; + Map = cPtrEnt->masterFbMapSize; + } else { + Addr = cPtrEnt->slaveFbAddress; + Map = cPtrEnt->slaveFbMapSize; + } + } + + if (cPtr->Bus == ChipsPCI) + cPtr->FbBase = xf86MapPciMem(pScrn->scrnIndex,VIDMEM_FRAMEBUFFER, + cPtr->PciTag, Addr, Map); + + else + cPtr->FbBase = xf86MapVidMem(pScrn->scrnIndex,VIDMEM_FRAMEBUFFER, + Addr, Map); + + if (cPtr->FbBase == NULL) + return FALSE; + } + if (cPtr->Flags & ChipsFullMMIOSupport) { + cPtr->MMIOBaseVGA = xf86MapPciMem(pScrn->scrnIndex, + VIDMEM_MMIO,cPtr->PciTag, + cPtr->IOAddress, 0x2000L); + /* 69030 MMIO Fix. + * + * The hardware lets us map the PipeB data registers + * into the MMIO address space normally occupied by PipeA, + * but it doesn't allow remapping of the index registers. + * So we're forced to map a separate MMIO space for each + * pipe and to toggle between them as necessary. -GHB + */ + if (cPtr->Flags & ChipsDualChannelSupport) + cPtr->MMIOBasePipeB = xf86MapPciMem(pScrn->scrnIndex, + VIDMEM_MMIO,cPtr->PciTag, + cPtr->IOAddress + 0x800000, 0x2000L); + + cPtr->MMIOBasePipeA = cPtr->MMIOBaseVGA; + } + } else { + /* In paged mode Base is the VGA window at 0xA0000 */ + cPtr->FbBase = hwp->Base; + } + + return TRUE; +} + + +/* + * Unmap the framebuffer and MMIO memory. + */ + +static Bool +chipsUnmapMem(ScrnInfoPtr pScrn) +{ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + + if (cPtr->Flags & ChipsLinearSupport) { + if (IS_HiQV(cPtr)) { + if (cPtr->MMIOBase) + xf86UnMapVidMem(pScrn->scrnIndex, (pointer)cPtr->MMIOBase, + 0x20000); + if (cPtr->MMIOBasePipeB) + xf86UnMapVidMem(pScrn->scrnIndex, (pointer)cPtr->MMIOBasePipeB, + 0x20000); + cPtr->MMIOBasePipeB = NULL; + } else { + if (cPtr->MMIOBase) + xf86UnMapVidMem(pScrn->scrnIndex, (pointer)cPtr->MMIOBase, + 0x10000); + } + cPtr->MMIOBase = NULL; + xf86UnMapVidMem(pScrn->scrnIndex, (pointer)cPtr->FbBase, + cPtr->FbMapSize); + } + cPtr->FbBase = NULL; + + return TRUE; +} + +static void +chipsProtect(ScrnInfoPtr pScrn, Bool on) +{ + vgaHWProtect(pScrn, on); +} + +static void +chipsBlankScreen(ScrnInfoPtr pScrn, Bool unblank) +{ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + vgaHWPtr hwp = VGAHWPTR(pScrn); + unsigned char scrn; + CHIPSEntPtr cPtrEnt; + + if (cPtr->UseDualChannel) { + cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0], + CHIPSEntityIndex)->ptr; + DUALREOPEN; + } + + /* fix things that could be messed up by suspend/resume */ + if (!IS_HiQV(cPtr)) + cPtr->writeXR(cPtr, 0x15, 0x00); + + scrn = hwp->readSeq(hwp, 0x01); + + if (unblank) { + scrn &= 0xDF; /* enable screen */ + } else { + scrn |= 0x20; /* blank screen */ + } + + /* synchronous reset - stop counters */ + if (!cPtr->SyncResetIgn) { + hwp->writeSeq(hwp, 0x00, 0x01); + } + + hwp->writeSeq(hwp, 0x01, scrn); /* change mode */ + + /* end reset - start counters */ + if (!cPtr->SyncResetIgn) { + hwp->writeSeq(hwp, 0x00, 0x03); + } + + if ((cPtr->UseDualChannel) && + (! xf86IsEntityShared(pScrn->entityList[0]))) { + unsigned int IOSS, MSS; + IOSS = cPtr->readIOSS(cPtr); + MSS = cPtr->readMSS(cPtr); + cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) | + IOSS_PIPE_B)); + cPtr->writeMSS(cPtr, hwp, ((cPtr->storeMSS & MSS_MASK) | MSS_PIPE_B)); + + /* fix things that could be messed up by suspend/resume */ + if (!IS_HiQV(cPtr)) + cPtr->writeXR(cPtr, 0x15, 0x00); + + scrn = hwp->readSeq(hwp, 0x01); + + if (unblank) { + scrn &= 0xDF; /* enable screen */ + } else { + scrn |= 0x20; /* blank screen */ + } + + /* synchronous reset - stop counters */ + if (!cPtr->SyncResetIgn) { + hwp->writeSeq(hwp, 0x00, 0x01); + } + + hwp->writeSeq(hwp, 0x01, scrn); /* change mode */ + + /* end reset - start counters */ + if (!cPtr->SyncResetIgn) { + hwp->writeSeq(hwp, 0x00, 0x03); + } + + cPtr->writeIOSS(cPtr, IOSS); + cPtr->writeMSS(cPtr, hwp, MSS); + } + +} + +static void +chipsLock(ScrnInfoPtr pScrn) +{ + vgaHWPtr hwp = VGAHWPTR(pScrn); + CHIPSPtr cPtr = CHIPSPTR(pScrn); + unsigned char tmp; + + vgaHWLock(hwp); + + if (!IS_HiQV(cPtr)) { + /* group protection attribute controller access */ + cPtr->writeXR(cPtr, 0x15, cPtr->SuspendHack.xr15); + tmp = cPtr->readXR(cPtr, 0x02); + cPtr->writeXR(cPtr, 0x02, (tmp & ~0x18) | cPtr->SuspendHack.xr02); + tmp = cPtr->readXR(cPtr, 0x14); + cPtr->writeXR(cPtr, 0x14, (tmp & ~0x20) | cPtr->SuspendHack.xr14); + + /* reset 32 bit register access */ + if (cPtr->Chipset > CHIPS_CT65540) { + tmp = cPtr->readXR(cPtr, 0x03); + cPtr->writeXR(cPtr, 0x03, (tmp & ~0x0A) | cPtr->SuspendHack.xr03); + } + } +} + +static void +chipsUnlock(ScrnInfoPtr pScrn) +{ + vgaHWPtr hwp = VGAHWPTR(pScrn); + CHIPSPtr cPtr = CHIPSPTR(pScrn); + unsigned char tmp; + + if (!IS_HiQV(cPtr)) { + /* group protection attribute controller access */ + cPtr->writeXR(cPtr, 0x15, 0x00); + tmp = cPtr->readXR(cPtr, 0x02); + cPtr->writeXR(cPtr, 0x02, (tmp & ~0x18)); + tmp = cPtr->readXR(cPtr, 0x14); + cPtr->writeXR(cPtr, 0x14, (tmp & ~0x20)); + /* enable 32 bit register access */ + if (cPtr->Chipset > CHIPS_CT65540) { + cPtr->writeXR(cPtr, 0x03, cPtr->SuspendHack.xr03 | 0x0A); + } + } + vgaHWUnlock(hwp); +} + +static void +chipsHWCursorOn(CHIPSPtr cPtr, ScrnInfoPtr pScrn) +{ + /* enable HW cursor */ + if (cPtr->HWCursorShown) { + if (IS_HiQV(cPtr)) { + cPtr->writeXR(cPtr, 0xA0, cPtr->HWCursorContents & 0xFF); + if (cPtr->UseDualChannel && + (! xf86IsEntityShared(pScrn->entityList[0]))) { + unsigned int IOSS, MSS; + IOSS = cPtr->readIOSS(cPtr); + MSS = cPtr->readMSS(cPtr); + cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) | + IOSS_PIPE_B)); + cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), ((cPtr->storeMSS & + MSS_MASK) | MSS_PIPE_B)); + cPtr->writeXR(cPtr, 0xA0, cPtr->HWCursorContents & 0xFF); + cPtr->writeIOSS(cPtr, IOSS); + cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), MSS); + } + } else { + HW_DEBUG(0x8); + if (cPtr->UseMMIO) { + MMIOmeml(DR(0x8)) = cPtr->HWCursorContents; + } else { + outl(cPtr->PIOBase + DR(0x8), cPtr->HWCursorContents); + } + } + } +} + +static void +chipsHWCursorOff(CHIPSPtr cPtr, ScrnInfoPtr pScrn) +{ + /* disable HW cursor */ + if (cPtr->HWCursorShown) { + if (IS_HiQV(cPtr)) { + cPtr->HWCursorContents = cPtr->readXR(cPtr, 0xA0); + cPtr->writeXR(cPtr, 0xA0, cPtr->HWCursorContents & 0xF8); + } else { + HW_DEBUG(0x8); + if (cPtr->UseMMIO) { + cPtr->HWCursorContents = MMIOmeml(DR(0x8)); + /* Below used to be MMIOmemw() change back if problem!!! */ + /* Also see ct_cursor.c */ + MMIOmeml(DR(0x8)) = cPtr->HWCursorContents & 0xFFFE; + } else { + cPtr->HWCursorContents = inl(cPtr->PIOBase + DR(0x8)); + outw(cPtr->PIOBase + DR(0x8), cPtr->HWCursorContents & 0xFFFE); + } + } + } +} + +void +chipsFixResume(ScrnInfoPtr pScrn) +{ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + vgaHWPtr hwp = VGAHWPTR(pScrn); + unsigned char tmp; + + /* fix things that could be messed up by suspend/resume */ + if (!IS_HiQV(cPtr)) + cPtr->writeXR(cPtr, 0x15, 0x00); + tmp = hwp->readMiscOut(hwp); + hwp->writeMiscOut(hwp, (tmp & 0xFE) | cPtr->SuspendHack.vgaIOBaseFlag); + tmp = hwp->readCrtc(hwp, 0x11); + hwp->writeCrtc(hwp, 0x11, (tmp & 0x7F)); +} + +static char +chipsTestDACComp(ScrnInfoPtr pScrn, unsigned char a, unsigned char b, + unsigned char c) +{ + vgaHWPtr hwp = VGAHWPTR(pScrn); + unsigned char type; + + hwp->writeDacWriteAddr(hwp, 0x00); + while ((hwp->readST01(hwp)) & 0x08){}; /* wait for vsync to end */ + while (!(hwp->readST01(hwp)) & 0x08){}; /* wait for new vsync */ + hwp->writeDacData(hwp, a); /* set pattern */ + hwp->writeDacData(hwp, b); + hwp->writeDacData(hwp, c); + while (!(hwp->readST01(hwp)) & 0x01){}; /* wait for hsync to end */ + while ((hwp->readST01(hwp)) & 0x01){}; /* wait for hsync to end */ + type = hwp->readST00(hwp); /* read comparator */ + return (type & 0x10); +} + +static int +chipsProbeMonitor(ScrnInfoPtr pScrn) +{ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + vgaHWPtr hwp = VGAHWPTR(pScrn); + unsigned char dacmask; + unsigned char dacdata[3]; + unsigned char xr1, xr2; + int type = 2; /* no monitor */ + unsigned char IOSS=0, MSS=0, tmpfr02=0, tmpfr01a=0, tmpfr01b=0; + + /* Dual channel display, enable both pipelines */ + if (cPtr->Flags & ChipsDualChannelSupport) { + IOSS = cPtr->readIOSS(cPtr); + MSS = cPtr->readMSS(cPtr); + tmpfr02 = cPtr->readFR(cPtr,0x02); + cPtr->writeFR(cPtr, 0x02, (tmpfr02 & 0xCF)); /* CRT/FP off */ + usleep(1000); + cPtr->writeIOSS(cPtr, ((IOSS & IOSS_MASK) | IOSS_PIPE_A)); + cPtr->writeMSS(cPtr, hwp, ((MSS & MSS_MASK) | MSS_PIPE_A)); + tmpfr01a = cPtr->readFR(cPtr,0x01); + if ((tmpfr01a & 0x3) != 0x01) + cPtr->writeFR(cPtr, 0x01, ((tmpfr01a & 0xFC) | 0x1)); + cPtr->writeIOSS(cPtr, ((IOSS & IOSS_MASK) | IOSS_PIPE_B)); + cPtr->writeMSS(cPtr, hwp, ((MSS & MSS_MASK) | MSS_PIPE_B)); + tmpfr01b = cPtr->readFR(cPtr,0x01); + if ((tmpfr01b & 0x3) != 0x01) + cPtr->writeFR(cPtr, 0x01, ((tmpfr01b & 0xFC) | 0x1)); + cPtr->writeIOSS(cPtr, IOSS); + cPtr->writeMSS(cPtr, hwp, MSS); + cPtr->writeFR(cPtr, 0x02, (tmpfr02 & 0xCF) | 0x10); /* CRT on/FP off*/ + } + + dacmask = hwp->readDacMask(hwp); /* save registers */ + hwp->writeDacMask(hwp, 0x00); + hwp->writeDacReadAddr(hwp, 0x00); + + dacdata[0]=hwp->readDacData(hwp); + dacdata[1]=hwp->readDacData(hwp); + dacdata[2]=hwp->readDacData(hwp); + + if (!IS_HiQV(cPtr)) { + xr1 = cPtr->readXR(cPtr, 0x06); + xr2 = cPtr->readXR(cPtr, 0x1F); + cPtr->writeXR(cPtr, 0x06, xr1 & 0xF1); /* turn on dac */ + cPtr->writeXR(cPtr, 0x1F, xr2 & 0x7F); /* enable comp */ + } else { + xr1 = cPtr->readXR(cPtr, 0x81); + xr2 = cPtr->readXR(cPtr, 0xD0); + cPtr->writeXR(cPtr, 0x81,(xr1 & 0xF0)); + cPtr->writeXR(cPtr, 0xD0,(xr2 | 0x03)); + } + if (chipsTestDACComp(pScrn, 0x12,0x12,0x12)) { /* test patterns */ + if (chipsTestDACComp(pScrn,0x14,0x14,0x14)) /* taken from */ + if (!chipsTestDACComp(pScrn,0x2D,0x14,0x14)) /* BIOS */ + if (!chipsTestDACComp(pScrn,0x14,0x2D,0x14)) + if (!chipsTestDACComp(pScrn,0x14,0x14,0x2D)) + if (!chipsTestDACComp(pScrn,0x2D,0x2D,0x2D)) + type = 0; /* color monitor */ + } else { + if (chipsTestDACComp(pScrn,0x04,0x12,0x04)) + if (!chipsTestDACComp(pScrn,0x1E,0x12,0x04)) + if (!chipsTestDACComp(pScrn,0x04,0x2D,0x04)) + if (!chipsTestDACComp(pScrn,0x1E,0x16,0x15)) + if (chipsTestDACComp(pScrn,0x00,0x00,0x00)) + type = 1; /* monochrome */ + } + + hwp->writeDacWriteAddr(hwp, 0x00); /* restore registers */ + hwp->writeDacData(hwp, dacdata[0]); + hwp->writeDacData(hwp, dacdata[1]); + hwp->writeDacData(hwp, dacdata[2]); + hwp->writeDacMask(hwp, dacmask); + if (!IS_HiQV(cPtr)) { + cPtr->writeXR(cPtr,0x06,xr1); + cPtr->writeXR(cPtr,0x1F,xr2); + } else { + cPtr->writeXR(cPtr,0x81,xr1); + cPtr->writeXR(cPtr,0xD0,xr2); + } + + if (cPtr->Flags & ChipsDualChannelSupport) { + cPtr->writeIOSS(cPtr, ((IOSS & IOSS_MASK) | IOSS_PIPE_A)); + cPtr->writeMSS(cPtr, hwp, ((MSS & MSS_MASK) | MSS_PIPE_A)); + cPtr->writeFR(cPtr, 0x01, tmpfr01a); + cPtr->writeIOSS(cPtr, ((IOSS & IOSS_MASK) | IOSS_PIPE_B)); + cPtr->writeMSS(cPtr, hwp, ((MSS & MSS_MASK) | MSS_PIPE_B)); + cPtr->writeFR(cPtr, 0x01, tmpfr01b); + usleep(1000); + cPtr->writeIOSS(cPtr, IOSS); + cPtr->writeMSS(cPtr, hwp, MSS); + cPtr->writeFR(cPtr, 0x02, tmpfr02); + } + + return type; +} + +static int +chipsSetMonitor(ScrnInfoPtr pScrn) +{ + int tmp= chipsProbeMonitor(pScrn); + + switch (tmp) { + case 0: + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Color monitor detected\n"); + break; + case 1: + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Monochrome monitor detected\n"); + break; + default: + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "No monitor detected\n"); + } + return (tmp); +} + +static void +chipsSetPanelType(CHIPSPtr cPtr) +{ + CARD8 tmp; + + if (IS_HiQV(cPtr)) { + if (cPtr->Chipset == CHIPS_CT69030) { + tmp = cPtr->readFR(cPtr, 0x00); + if (tmp & 0x20) { + /* FR02: DISPLAY TYPE REGISTER */ + /* FR02[4] = CRT, FR02[5] = FlatPanel */ + tmp = cPtr->readFR(cPtr, 0x02); + if (tmp & 0x10) + cPtr->PanelType |= ChipsCRT; + if (tmp & 0x20) + cPtr->PanelType |= ChipsLCD | ChipsLCDProbed; + } else { + cPtr->PanelType |= ChipsCRT; + } + } else { + /* test LCD */ + /* FR01: DISPLAY TYPE REGISTER */ + /* FR01[1:0]: Display Type, 01 = CRT, 10 = FlatPanel */ + /* LCD */ + tmp = cPtr->readFR(cPtr, 0x01); + if ((tmp & 0x03) == 0x02) { + cPtr->PanelType |= ChipsLCD; + } + tmp = cPtr->readXR(cPtr,0xD0); + if (tmp & 0x01) { + cPtr->PanelType |= ChipsCRT; + } + } + } else { + tmp = cPtr->readXR(cPtr, 0x51); + /* test LCD */ + /* XR51: DISPLAY TYPE REGISTER */ + /* XR51[2]: Display Type, 0 = CRT, 1 = FlatPanel */ + if (tmp & 0x04) { + cPtr->PanelType |= ChipsLCD | ChipsLCDProbed; + } + if ((cPtr->readXR(cPtr, 0x06)) & 0x02) { + cPtr->PanelType |= ChipsCRT; + } + } +} + +static void +chipsBlockHandler ( + int i, + pointer blockData, + pointer pTimeout, + pointer pReadmask +){ + ScreenPtr pScreen = screenInfo.screens[i]; + ScrnInfoPtr pScrn = xf86Screens[i]; + CHIPSPtr cPtr = CHIPSPTR(pScrn); + + pScreen->BlockHandler = cPtr->BlockHandler; + (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask); + pScreen->BlockHandler = chipsBlockHandler; + + if(cPtr->VideoTimerCallback) { + UpdateCurrentTime(); + (*cPtr->VideoTimerCallback)(pScrn, currentTime.milliseconds); + } +} diff --git a/src/ct_driver.h b/src/ct_driver.h new file mode 100644 index 0000000..831ac9b --- /dev/null +++ b/src/ct_driver.h @@ -0,0 +1,553 @@ +/* $XConsortium: ct_driver.h /main/3 1996/10/27 11:49:29 kaleb $ */ +/* + * Modified 1996 by Egbert Eich <eich@xfree86.org> + * Modified 1996 by David Bateman <dbateman@club-internet.fr> + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the authors not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. The authors makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/chips/ct_driver.h,v 1.34 2002/01/25 21:56:00 tsi Exp $ */ + + +#ifndef _CT_DRIVER_H_ +#define _CT_DRIVER_H_ + +#include "xaa.h" +#include "vbe.h" +#include "xaalocal.h" /* XAA internals as we replace some of XAA */ +#include "xf86Cursor.h" +#include "xf86i2c.h" +#include "xf86DDC.h" +#include "xf86xv.h" +#include "vgaHW.h" + +/* Supported chipsets */ +typedef enum { + CHIPS_CT65520, + CHIPS_CT65525, + CHIPS_CT65530, + CHIPS_CT65535, + CHIPS_CT65540, + CHIPS_CT65545, + CHIPS_CT65546, + CHIPS_CT65548, + CHIPS_CT65550, + CHIPS_CT65554, + CHIPS_CT65555, + CHIPS_CT68554, + CHIPS_CT69000, + CHIPS_CT69030, + CHIPS_CT64200, + CHIPS_CT64300 +} CHIPSType; + +/* Clock related */ +typedef struct { + unsigned char msr; /* Dot Clock Related */ + unsigned char fcr; + unsigned char xr02; + unsigned char xr03; + unsigned char xr33; + unsigned char xr54; + unsigned char fr03; + int Clock; + int FPClock; +} CHIPSClockReg, *CHIPSClockPtr; + +typedef struct { + unsigned int ProbedClk; + unsigned int Max; /* Memory Clock Related */ + unsigned int Clk; + unsigned char M; + unsigned char N; + unsigned char P; + unsigned char PSN; + unsigned char xrCC; + unsigned char xrCD; + unsigned char xrCE; +} CHIPSMemClockReg, *CHIPSMemClockPtr; + +#define TYPE_HW 0x01 +#define TYPE_PROGRAMMABLE 0x02 +#define GET_TYPE 0x0F +#define OLD_STYLE 0x10 +#define NEW_STYLE 0x20 +#define HiQV_STYLE 0x30 +#define WINGINE_1_STYLE 0x40 /* 64300: external clock; 4 clocks */ +#define WINGINE_2_STYLE 0x50 /* 64300: internal clock; 2 hw-clocks */ +#define GET_STYLE 0xF0 +#define LCD_TEXT_CLK_FREQ 25000 /* lcd textclock if TYPE_PROGRAMMABLE */ +#define CRT_TEXT_CLK_FREQ 28322 /* crt textclock if TYPE_PROGRAMMABLE */ +#define Fref 14318180 /* The reference clock in Hertz */ + +/* The capability flags for the C&T chipsets */ +#define ChipsLinearSupport 0x00000001 +#define ChipsAccelSupport 0x00000002 +#define ChipsFullMMIOSupport 0x00000004 +#define ChipsMMIOSupport 0x00000008 +#define ChipsHDepthSupport 0x00000010 +#define ChipsDPMSSupport 0x00000020 +#define ChipsTMEDSupport 0x00000040 +#define ChipsGammaSupport 0x00000080 +#define ChipsVideoSupport 0x00000100 +#define ChipsDualChannelSupport 0x00000200 +#define ChipsDualRefresh 0x00000400 + +/* Options flags for the C&T chipsets */ +#define ChipsHWCursor 0x00001000 +#define ChipsShadowFB 0x00002000 +#define ChipsOverlay8plus16 0x00004000 +#define ChipsUseNewFB 0x00008000 + +/* Architecture type flags */ +#define ChipsHiQV 0x00010000 +#define ChipsWingine 0x00020000 +#define IS_Wingine(x) ((x->Flags) & ChipsWingine) +#define IS_HiQV(x) ((x->Flags) & ChipsHiQV) + +/* Acceleration flags for the C&T chipsets */ +#define ChipsColorTransparency 0x0100000 +#define ChipsImageReadSupport 0x0200000 + +/* Overlay Transparency Key */ +#define TRANSPARENCY_KEY 255 + +/* Flag Bus Types */ +#define ChipsUnknown 0 +#define ChipsISA 1 +#define ChipsVLB 2 +#define ChipsPCI 3 +#define ChipsCPUDirect 4 +#define ChipsPIB 5 +#define ChipsMCB 6 + +/* Macro's to select the 32 bit acceleration registers */ +#define DR(x) cPtr->Regs32[x] /* For CT655xx naming scheme */ +#define MR(x) cPtr->Regs32[x] /* CT655xx MMIO naming scheme */ +#define BR(x) cPtr->Regs32[x] /* For HiQV naming scheme */ +#define MMIOmeml(x) *(CARD32 *)(cPtr->MMIOBase + (x)) +#if 0 +#define MMIOmemw(x) *(CARD16 *)(cPtr->MMIOBase + (x)) +#endif +/* Monitor or flat panel type flags */ +#define ChipsCRT 0x0010 +#define ChipsLCD 0x1000 +#define ChipsLCDProbed 0x2000 +#define ChipsTFT 0x0100 +#define ChipsDS 0x0200 +#define ChipsDD 0x0400 +#define ChipsSS 0x0800 +#define IS_STN(x) ((x) & 0xE00) + +/* Dual channel register enable masks */ +#define IOSS_MASK 0xE0 +#define IOSS_BOTH 0x13 +#define IOSS_PIPE_A 0x11 +#define IOSS_PIPE_B 0x1E +#define MSS_MASK 0xF0 +#define MSS_BOTH 0x0B +#define MSS_PIPE_A 0x02 +#define MSS_PIPE_B 0x05 +/* Aggregate value of MSS shadow bits -GHB */ +#define MSS_SHADOW 0x07 + +/* Storage for the registers of the C&T chipsets */ +typedef struct { + unsigned char XR[0xFF]; + unsigned char CR[0x80]; + unsigned char FR[0x80]; + unsigned char MR[0x80]; + CHIPSClockReg Clock; +} CHIPSRegRec, *CHIPSRegPtr; + +/* Storage for the flat panel size */ +typedef struct { + int HDisplay; + int HRetraceStart; + int HRetraceEnd; + int HTotal; + int VDisplay; + int VRetraceStart; + int VTotal; +} CHIPSPanelSizeRec, *CHIPSPanelSizePtr; + +/* Some variables needed in the XAA acceleration */ +typedef struct { + /* General variable */ + unsigned int CommandFlags; + unsigned int BytesPerPixel; + unsigned int BitsPerPixel; + unsigned int FbOffset; + unsigned int PitchInBytes; + unsigned int ScratchAddress; + /* 64k for color expansion and imagewrites */ + unsigned char * BltDataWindow; + /* Hardware cursor address */ + unsigned int CursorAddress; + Bool UseHWCursor; + /* Boundaries of the pixmap cache */ + unsigned int CacheStart; + unsigned int CacheEnd; + /* Storage for pattern mask */ + int planemask; + /* Storage for foreground and background color */ + int fgColor; + int bgColor; + /* For the 8x8 pattern fills */ + int patternyrot; + /* For cached stipple fills */ + int SlotWidth; + /* Variables for the 24bpp fill */ + unsigned char fgpixel; + unsigned char bgpixel; + unsigned char xorpixel; + Bool fastfill; + Bool rgb24equal; + int fillindex; + unsigned int width24bpp; + unsigned int color24bpp; + unsigned int rop24bpp; +} CHIPSACLRec, *CHIPSACLPtr; +#define CHIPSACLPTR(p) &((CHIPSPtr)((p)->driverPrivate))->Accel + +/* Storage for some register values that are messed up by suspend/resumes */ +typedef struct { + unsigned char xr02; + unsigned char xr03; + unsigned char xr14; + unsigned char xr15; + unsigned char vgaIOBaseFlag; +} CHIPSSuspendHackRec, *CHIPSSuspendHackPtr; + +/* The functions to access the C&T extended registers */ +typedef struct _CHIPSRec *CHIPSPtr; +typedef CARD8 (*chipsReadXRPtr)(CHIPSPtr cPtr, CARD8 index); +typedef void (*chipsWriteXRPtr)(CHIPSPtr cPtr, CARD8 index, CARD8 value); +typedef CARD8 (*chipsReadFRPtr)(CHIPSPtr cPtr, CARD8 index); +typedef void (*chipsWriteFRPtr)(CHIPSPtr cPtr, CARD8 index, CARD8 value); +typedef CARD8 (*chipsReadMRPtr)(CHIPSPtr cPtr, CARD8 index); +typedef void (*chipsWriteMRPtr)(CHIPSPtr cPtr, CARD8 index, CARD8 value); +typedef CARD8 (*chipsReadMSSPtr)(CHIPSPtr cPtr); +typedef void (*chipsWriteMSSPtr)(CHIPSPtr cPtr, vgaHWPtr hwp, CARD8 value); +typedef CARD8 (*chipsReadIOSSPtr)(CHIPSPtr cPtr); +typedef void (*chipsWriteIOSSPtr)(CHIPSPtr cPtr, CARD8 value); + +/* The privates of the C&T driver */ +#define CHIPSPTR(p) ((CHIPSPtr)((p)->driverPrivate)) + + +typedef struct { + int lastInstance; + int refCount; + CARD32 masterFbAddress; + long masterFbMapSize; + CARD32 slaveFbAddress; + long slaveFbMapSize; + int mastervideoRam; + int slavevideoRam; + Bool masterOpen; + Bool slaveOpen; + Bool masterActive; + Bool slaveActive; +} CHIPSEntRec, *CHIPSEntPtr; + + +typedef struct _CHIPSRec { + pciVideoPtr PciInfo; + PCITAG PciTag; + int Chipset; + EntityInfoPtr pEnt; + IOADDRESS PIOBase; + CARD32 IOAddress; + unsigned long FbAddress; + unsigned int IOBase; + unsigned char * FbBase; + unsigned char * MMIOBase; + unsigned char * MMIOBaseVGA; + unsigned char * MMIOBasePipeA; + unsigned char * MMIOBasePipeB; + long FbMapSize; + unsigned char * ShadowPtr; + int ShadowPitch; + int Rotate; + void (*PointerMoved)(int index, int x, int y); + int FbOffset16; + int FbSize16; + OptionInfoPtr Options; + CHIPSPanelSizeRec PanelSize; + int FrameBufferSize; + Bool SyncResetIgn; + Bool UseMMIO; + Bool UseFullMMIO; + Bool UseDualChannel; + int Monitor; + int MinClock; + int MaxClock; + CHIPSClockReg SaveClock; /* Storage for ClockSelect */ + CHIPSMemClockReg MemClock; + unsigned char ClockType; + unsigned char CRTClk[4]; + unsigned char FPClk[4]; + int FPclock; + int FPclkInx; + int CRTclkInx; + Bool FPClkModified; + int ClockMulFactor; + int Rounding; + CHIPSSuspendHackRec SuspendHack; + CARD32 PanelType; + CHIPSRegRec ModeReg; + CHIPSRegRec SavedReg; + CHIPSRegRec SavedReg2; + vgaRegRec VgaSavedReg2; + unsigned int * Regs32; + unsigned int Flags; + CARD32 Bus; + XAAInfoRecPtr AccelInfoRec; + xf86CursorInfoPtr CursorInfoRec; + CHIPSACLRec Accel; + unsigned int HWCursorContents; + Bool HWCursorShown; + DGAModePtr DGAModes; + int numDGAModes; + Bool DGAactive; + int DGAViewportStatus; + CloseScreenProcPtr CloseScreen; + ScreenBlockHandlerProcPtr BlockHandler; + void (*VideoTimerCallback)(ScrnInfoPtr, Time); + int videoKey; + XF86VideoAdaptorPtr adaptor; + int OverlaySkewX; + int OverlaySkewY; + int VideoZoomMax; + Bool SecondCrtc; + CHIPSEntPtr entityPrivate; + unsigned char storeMSS; + unsigned char storeIOSS; +#ifdef __arm32__ +#ifdef __NetBSD__ + int TVMode; +#endif + int Bank; +#endif + unsigned char ddc_mask; + I2CBusPtr I2C; + vbeInfoPtr pVbe; + chipsReadXRPtr readXR; + chipsWriteXRPtr writeXR; + chipsReadFRPtr readFR; + chipsWriteFRPtr writeFR; + chipsReadMRPtr readMR; + chipsWriteMRPtr writeMR; + chipsReadMSSPtr readMSS; + chipsWriteMSSPtr writeMSS; + chipsReadIOSSPtr readIOSS; + chipsWriteIOSSPtr writeIOSS; + Bool cursorDelay; + unsigned int viewportMask; +} CHIPSRec; + +typedef struct _CHIPSi2c { + unsigned char i2cClockBit; + unsigned char i2cDataBit; + CHIPSPtr cPtr; +} CHIPSI2CRec, *CHIPSI2CPtr; + +/* External variables */ +extern int ChipsAluConv[]; +extern int ChipsAluConv2[]; +extern int ChipsAluConv3[]; +extern unsigned int ChipsReg32[]; +extern unsigned int ChipsReg32HiQV[]; + +/* Prototypes */ + +void CHIPSAdjustFrame(int scrnIndex, int x, int y, int flags); +Bool CHIPSSwitchMode(int scrnIndex, DisplayModePtr mode, int flags); + +/* video */ +void CHIPSInitVideo(ScreenPtr pScreen); +void CHIPSResetVideo(ScrnInfoPtr pScrn); + +/* banking */ +int CHIPSSetRead(ScreenPtr pScreen, int bank); +int CHIPSSetWrite(ScreenPtr pScreen, int bank); +int CHIPSSetReadWrite(ScreenPtr pScreen, int bank); +int CHIPSSetReadPlanar(ScreenPtr pScreen, int bank); +int CHIPSSetWritePlanar(ScreenPtr pScreen, int bank); +int CHIPSSetReadWritePlanar(ScreenPtr pScreen, int bank); +int CHIPSWINSetRead(ScreenPtr pScreen, int bank); +int CHIPSWINSetWrite(ScreenPtr pScreen, int bank); +int CHIPSWINSetReadWrite(ScreenPtr pScreen, int bank); +int CHIPSWINSetReadPlanar(ScreenPtr pScreen, int bank); +int CHIPSWINSetWritePlanar(ScreenPtr pScreen, int bank); +int CHIPSWINSetReadWritePlanar(ScreenPtr pScreen, int bank); +int CHIPSHiQVSetReadWrite(ScreenPtr pScreen, int bank); +int CHIPSHiQVSetReadWritePlanar(ScreenPtr pScreen, int bank); + +/* acceleration */ +Bool CHIPSAccelInit(ScreenPtr pScreen); +void CHIPSSync(ScrnInfoPtr pScrn); +Bool CHIPSMMIOAccelInit(ScreenPtr pScreen); +void CHIPSMMIOSync(ScrnInfoPtr pScrn); +Bool CHIPSHiQVAccelInit(ScreenPtr pScreen); +void CHIPSHiQVSync(ScrnInfoPtr pScrn); +Bool CHIPSCursorInit(ScreenPtr pScreen); + +/* register access functions */ +void CHIPSSetStdExtFuncs(CHIPSPtr cPtr); +void CHIPSSetMmioExtFuncs(CHIPSPtr cPtr); +void CHIPSHWSetMmioFuncs(ScrnInfoPtr pScrn, CARD8 *base, int offset); + +/* ddc */ +extern void chips_ddc1(ScrnInfoPtr pScrn); +extern Bool chips_i2cInit(ScrnInfoPtr pScrn); + +/* dga */ +Bool CHIPSDGAInit(ScreenPtr pScreen); + +/* shadow fb */ +void chipsRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox); +void chipsRefreshArea8(ScrnInfoPtr pScrn, int num, BoxPtr pbox); +void chipsRefreshArea16(ScrnInfoPtr pScrn, int num, BoxPtr pbox); +void chipsRefreshArea24(ScrnInfoPtr pScrn, int num, BoxPtr pbox); +void chipsRefreshArea32(ScrnInfoPtr pScrn, int num, BoxPtr pbox); +void chipsPointerMoved(int index, int x, int y); + + +/* + * Some macros for switching display channels. NOTE... It appears that we + * can't write to both display channels at the same time, and so the options + * MSS_BOTH and IOSS_BOTH should not be used. Need to get around this by set + * dual channel mode to pipe A by default and handling multiple channel writes + * in ModeInit.. + */ + +#define DUALOPEN \ + { \ + /* Set the IOSS/MSS registers to point to the right register set */ \ + if (xf86IsEntityShared(pScrn->entityList[0])) { \ + if (cPtr->SecondCrtc == TRUE) { \ + cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) | \ + IOSS_PIPE_B)); \ + cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), ((cPtr->storeMSS & \ + MSS_MASK) | MSS_PIPE_B)); \ + cPtrEnt->slaveOpen = TRUE; \ + cPtrEnt->slaveActive = TRUE; \ + cPtrEnt->masterActive = FALSE; \ + } else { \ + cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) | \ + IOSS_PIPE_A)); \ + cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), ((cPtr->storeMSS & \ + MSS_MASK) | MSS_PIPE_A)); \ + cPtrEnt->masterOpen = TRUE; \ + cPtrEnt->masterActive = TRUE; \ + cPtrEnt->slaveActive = FALSE; \ + } \ + } else { \ + cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) | \ + IOSS_PIPE_A)); \ + cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), ((cPtr->storeMSS & \ + MSS_MASK) | MSS_PIPE_A)); \ + } \ + } + +#define DUALREOPEN \ + { \ + if (xf86IsEntityShared(pScrn->entityList[0])) { \ + if (cPtr->SecondCrtc == TRUE) { \ + if (! cPtrEnt->slaveActive) { \ + cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) | \ + IOSS_PIPE_B)); \ + cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), ((cPtr->storeMSS & \ + MSS_MASK) | MSS_PIPE_B)); \ + cPtrEnt->slaveOpen = TRUE; \ + cPtrEnt->slaveActive = TRUE; \ + cPtrEnt->masterActive = FALSE; \ + } \ + } else { \ + if (! cPtrEnt->masterActive) { \ + cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) | \ + IOSS_PIPE_A)); \ + cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), ((cPtr->storeMSS & \ + MSS_MASK) | MSS_PIPE_A)); \ + cPtrEnt->masterOpen = TRUE; \ + cPtrEnt->masterActive = TRUE; \ + cPtrEnt->slaveActive = FALSE; \ + } \ + } \ + } \ + } + +#define DUALCLOSE \ + { \ + if (! xf86IsEntityShared(pScrn->entityList[0])) { \ + cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) | \ + IOSS_PIPE_A)); \ + cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), ((cPtr->storeMSS & \ + MSS_MASK) | MSS_PIPE_A)); \ + chipsHWCursorOff(cPtr, pScrn); \ + chipsRestore(pScrn, &(VGAHWPTR(pScrn))->SavedReg, \ + &cPtr->SavedReg, TRUE); \ + chipsLock(pScrn); \ + cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) | \ + IOSS_PIPE_B)); \ + cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), ((cPtr->storeMSS & \ + MSS_MASK) | MSS_PIPE_B)); \ + chipsHWCursorOff(cPtr, pScrn); \ + chipsRestore(pScrn, &cPtr->VgaSavedReg2, &cPtr->SavedReg2, TRUE); \ + cPtr->writeIOSS(cPtr, cPtr->storeIOSS); \ + cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), cPtr->storeMSS); \ + chipsLock(pScrn); \ + } else { \ + chipsHWCursorOff(cPtr, pScrn); \ + chipsRestore(pScrn, &(VGAHWPTR(pScrn))->SavedReg, &cPtr->SavedReg,\ + TRUE); \ + if (cPtr->SecondCrtc == TRUE) { \ + cPtrEnt->slaveActive = FALSE; \ + cPtrEnt->slaveOpen = FALSE; \ + if (! cPtrEnt->masterActive) { \ + cPtr->writeIOSS(cPtr, cPtr->storeIOSS); \ + cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), cPtr->storeMSS); \ + chipsLock(pScrn); \ + } \ + } else { \ + cPtrEnt->masterActive = FALSE; \ + cPtrEnt->masterOpen = FALSE; \ + if (! cPtrEnt->slaveActive) { \ + cPtr->writeIOSS(cPtr, cPtr->storeIOSS); \ + cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), cPtr->storeMSS); \ + chipsLock(pScrn); \ + } \ + } \ + } \ + } + + +/* To aid debugging of 32 bit register access we make the following defines */ +/* +#define DEBUG +#define CT_HW_DEBUG +*/ +#if defined(DEBUG) & defined(CT_HW_DEBUG) +#define HW_DEBUG(x) {usleep(500000); ErrorF("Register/Address: 0x%X\n",x);} +#else +#define HW_DEBUG(x) +#endif +#endif diff --git a/src/ct_regs.c b/src/ct_regs.c new file mode 100644 index 0000000..201ac5c --- /dev/null +++ b/src/ct_regs.c @@ -0,0 +1,535 @@ +/* + * Created 1998 by David Bateman <dbateman@eng.uts.edu.au> + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the authors not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. The authors makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/chips/ct_regs.c,v 1.8 2002/01/25 21:56:00 tsi Exp $ */ + +/* + * The functions in this file are used to read/write the C&T extension register + * and supply MMIO replacements of the VGA register access functions in + * vgaHW.c for chips that support MMIO access (eg 69000). Unlike the MGA + * chips, for instance, the C&T chipsets don't have a direct mapping between + * the MMIO mapped vga registers and the PIO versions. + * + * In General, these are the ONLY supported way of access the video processors + * registers. Exception are + * + * 1) chipsFindIsaDevice, where we don't know the chipset and so we don't know + * if the chipset supports MMIO access to its VGA registers, and we don't + * know the chips MemBase address and so can't map the VGA registers even + * if the chip did support MMIO. This effectively limits the use of non-PCI + * MMIO and multihead to a single card accessing 0x3D6/0x3D7. I.E. You can + * only have a single C&T card in a non-PCI multihead arrangement. Also as + * ISA has no method to disable I/O access to a card ISA multihead will + * never be supported. + * + * 2) ct_Blitter.h, ct_BlitMM.h and ct_BltHiQV.h, where speed is crucial and + * we know exactly whether we are using MMIO or PIO. + * + * 3) The 6554x 32bit DRxx in ct_cursor.c where the choice between MMIO and + * PIO is made explicitly + */ + + +/* All drivers should typically include these */ +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86_ansic.h" + +/* Everything using inb/outb, etc needs "compiler.h" */ +#include "compiler.h" + +/* Drivers for PCI hardware need this */ +#include "xf86PciInfo.h" + +/* Drivers that need to access the PCI config space directly need this */ +#include "xf86Pci.h" + +/* This is used for module versioning */ +#include "xf86Version.h" + +/* Driver specific headers */ +#include "ct_driver.h" + +#define CHIPS_MONO_STAT_1 0x3BA +#define CHIPS_STAT_0 0x3BA +#define CHIPS_MSS 0x3CB +#define CHIPS_IOSS 0x3CD +#define CHIPS_FR_INDEX 0x3D0 +#define CHIPS_FR_DATA 0x3D1 +#define CHIPS_MR_INDEX 0x3D2 +#define CHIPS_MR_DATA 0x3D3 +#define CHIPS_XR_INDEX 0x3D6 +#define CHIPS_XR_DATA 0x3D7 +#define CHIPS_COLOR_STAT_1 0x3DA + +#define CHIPS_MMIO_MONO_CRTC_INDEX 0x768 +#define CHIPS_MMIO_MONO_CRTC_DATA 0x769 +#define CHIPS_MMIO_MONO_STAT_1 0x774 +#define CHIPS_MMIO_ATTR_INDEX 0x780 +#define CHIPS_MMIO_ATTR_DATA_W 0x780 +#define CHIPS_MMIO_ATTR_DATA_R 0x781 +#define CHIPS_MMIO_STAT_0 0x784 +#define CHIPS_MMIO_MISC_OUT_W 0x784 +#define CHIPS_MMIO_SEQ_INDEX 0x788 +#define CHIPS_MMIO_SEQ_DATA 0x789 +#define CHIPS_MMIO_DAC_MASK 0x78C +#define CHIPS_MMIO_DAC_READ_ADDR 0x78D +#define CHIPS_MMIO_DAC_WRITE_ADDR 0x790 +#define CHIPS_MMIO_DAC_DATA 0x791 +#define CHIPS_MMIO_FEATURE_R 0x794 +#define CHIPS_MMIO_MSS 0x795 +#define CHIPS_MMIO_MISC_OUT_R 0x798 +#define CHIPS_MMIO_IOSS 0x799 +#define CHIPS_MMIO_GRAPH_INDEX 0x79C +#define CHIPS_MMIO_GRAPH_DATA 0x79D +#define CHIPS_MMIO_FR_INDEX 0x7A0 +#define CHIPS_MMIO_FR_DATA 0x7A1 +#define CHIPS_MMIO_MR_INDEX 0x7A4 +#define CHIPS_MMIO_MR_DATA 0x7A5 +#define CHIPS_MMIO_COLOR_CRTC_INDEX 0x7A8 +#define CHIPS_MMIO_COLOR_CRTC_DATA 0x7A9 +#define CHIPS_MMIO_XR_INDEX 0x7AC +#define CHIPS_MMIO_XR_DATA 0x7AD +#define CHIPS_MMIO_COLOR_STAT_1 0x7B4 + +/* + * PIO Access to the C&T extension registers + */ +void +chipsStdWriteXR(CHIPSPtr cPtr, CARD8 index, CARD8 value) +{ + outb(cPtr->PIOBase + CHIPS_XR_INDEX, index); + outb(cPtr->PIOBase + CHIPS_XR_DATA, value); +} + +static CARD8 +chipsStdReadXR(CHIPSPtr cPtr, CARD8 index) +{ + outb(cPtr->PIOBase + CHIPS_XR_INDEX, index); + return inb(cPtr->PIOBase + CHIPS_XR_DATA); +} + +static void +chipsStdWriteFR(CHIPSPtr cPtr, CARD8 index, CARD8 value) +{ + outb(cPtr->PIOBase + CHIPS_FR_INDEX, index); + outb(cPtr->PIOBase + CHIPS_FR_DATA, value); +} + +static CARD8 +chipsStdReadFR(CHIPSPtr cPtr, CARD8 index) +{ + outb(cPtr->PIOBase + CHIPS_FR_INDEX, index); + return inb(cPtr->PIOBase + CHIPS_FR_DATA); +} + +static void +chipsStdWriteMR(CHIPSPtr cPtr, CARD8 index, CARD8 value) +{ + outb(cPtr->PIOBase + CHIPS_MR_INDEX, index); + outb(cPtr->PIOBase + CHIPS_MR_DATA, value); +} + +static CARD8 +chipsStdReadMR(CHIPSPtr cPtr, CARD8 index) +{ + outb(cPtr->PIOBase + CHIPS_MR_INDEX, index); + return inb(cPtr->PIOBase + CHIPS_MR_DATA); +} + +static void +chipsStdWriteMSS(CHIPSPtr cPtr, vgaHWPtr hwp, CARD8 value) +{ + outb(cPtr->PIOBase + CHIPS_MSS, value); +} + +static CARD8 +chipsStdReadMSS(CHIPSPtr cPtr) +{ + return inb(cPtr->PIOBase + CHIPS_MSS); +} + +static void +chipsStdWriteIOSS(CHIPSPtr cPtr, CARD8 value) +{ + outb(cPtr->PIOBase + CHIPS_IOSS, value); +} + +static CARD8 +chipsStdReadIOSS(CHIPSPtr cPtr) +{ + return inb(cPtr->PIOBase + CHIPS_IOSS); +} + +void +CHIPSSetStdExtFuncs(CHIPSPtr cPtr) +{ + cPtr->writeFR = chipsStdWriteFR; + cPtr->readFR = chipsStdReadFR; + cPtr->writeMR = chipsStdWriteMR; + cPtr->readMR = chipsStdReadMR; + cPtr->writeXR = chipsStdWriteXR; + cPtr->readXR = chipsStdReadXR; + cPtr->writeMSS = chipsStdWriteMSS; + cPtr->readMSS = chipsStdReadMSS; + cPtr->writeIOSS = chipsStdWriteIOSS; + cPtr->readIOSS = chipsStdReadIOSS; +} + +/* + * MMIO Access to the C&T extension registers + */ + +#define chipsminb(p) MMIO_IN8(cPtr->MMIOBaseVGA, (p)) +#define chipsmoutb(p,v) MMIO_OUT8(cPtr->MMIOBaseVGA, (p),(v)) + +static void +chipsMmioWriteXR(CHIPSPtr cPtr, CARD8 index, CARD8 value) +{ + chipsmoutb(CHIPS_MMIO_XR_INDEX, index); + chipsmoutb(CHIPS_MMIO_XR_DATA, value); +} + +static CARD8 +chipsMmioReadXR(CHIPSPtr cPtr, CARD8 index) +{ + chipsmoutb(CHIPS_MMIO_XR_INDEX, index); + return chipsminb(CHIPS_MMIO_XR_DATA); +} + +static void +chipsMmioWriteFR(CHIPSPtr cPtr, CARD8 index, CARD8 value) +{ + chipsmoutb(CHIPS_MMIO_FR_INDEX, index); + chipsmoutb(CHIPS_MMIO_FR_DATA, value); +} + +static CARD8 +chipsMmioReadFR(CHIPSPtr cPtr, CARD8 index) +{ + chipsmoutb(CHIPS_MMIO_FR_INDEX, index); + return chipsminb(CHIPS_MMIO_FR_DATA); +} + +static void +chipsMmioWriteMR(CHIPSPtr cPtr, CARD8 index, CARD8 value) +{ + chipsmoutb(CHIPS_MMIO_MR_INDEX, index); + chipsmoutb(CHIPS_MMIO_MR_DATA, value); +} + +static CARD8 +chipsMmioReadMR(CHIPSPtr cPtr, CARD8 index) +{ + chipsmoutb(CHIPS_MMIO_MR_INDEX, index); + return chipsminb(CHIPS_MMIO_MR_DATA); +} + +static void +chipsMmioWriteMSS(CHIPSPtr cPtr, vgaHWPtr hwp, CARD8 value) +{ + /* 69030 MMIO Fix. + * + * <value> determines which MMIOBase to use; either + * Pipe A or Pipe B. -GHB + */ + if ((value & MSS_SHADOW) == MSS_PIPE_B) + cPtr->MMIOBaseVGA = cPtr->MMIOBasePipeB; + else + cPtr->MMIOBaseVGA = cPtr->MMIOBasePipeA; + + hwp->MMIOBase = cPtr->MMIOBaseVGA; + + /* Since our Pipe constants don't set bit 3 of MSS, the value + * written here has no effect on the hardware's behavior. It + * does allow us to use the value returned by readMSS() to key + * the above logic, though. -GHB + */ + chipsmoutb(CHIPS_MMIO_MSS, value); +} + +static CARD8 +chipsMmioReadMSS(CHIPSPtr cPtr) +{ + return chipsminb(CHIPS_MMIO_MSS); +} + +static void +chipsMmioWriteIOSS(CHIPSPtr cPtr, CARD8 value) +{ + chipsmoutb(CHIPS_MMIO_IOSS, value); +} + +static CARD8 +chipsMmioReadIOSS(CHIPSPtr cPtr) +{ + return chipsminb(CHIPS_MMIO_IOSS); +} + +void +CHIPSSetMmioExtFuncs(CHIPSPtr cPtr) +{ + cPtr->writeFR = chipsMmioWriteFR; + cPtr->readFR = chipsMmioReadFR; + cPtr->writeMR = chipsMmioWriteMR; + cPtr->readMR = chipsMmioReadMR; + cPtr->writeXR = chipsMmioWriteXR; + cPtr->readXR = chipsMmioReadXR; + cPtr->writeMSS = chipsMmioWriteMSS; + cPtr->readMSS = chipsMmioReadMSS; + cPtr->writeIOSS = chipsMmioWriteIOSS; + cPtr->readIOSS = chipsMmioReadIOSS; +} + +/* + * MMIO versions of the VGA register access functions. + */ + +#define minb(p) MMIO_IN8(hwp->MMIOBase, (p)) +#define moutb(p,v) MMIO_OUT8(hwp->MMIOBase, (p),(v)) + +static void +chipsMmioWriteCrtc(vgaHWPtr hwp, CARD8 index, CARD8 value) +{ + if (hwp->IOBase == VGA_IOBASE_MONO) { + moutb(CHIPS_MMIO_MONO_CRTC_INDEX, index); + moutb(CHIPS_MMIO_MONO_CRTC_DATA, value); + } else { + moutb(CHIPS_MMIO_COLOR_CRTC_INDEX, index); + moutb(CHIPS_MMIO_COLOR_CRTC_DATA, value); + } +} + +static CARD8 +chipsMmioReadCrtc(vgaHWPtr hwp, CARD8 index) +{ + if (hwp->IOBase == VGA_IOBASE_MONO) { + moutb(CHIPS_MMIO_MONO_CRTC_INDEX, index); + return minb(CHIPS_MMIO_MONO_CRTC_DATA); + } else { + moutb(CHIPS_MMIO_COLOR_CRTC_INDEX, index); + return minb(CHIPS_MMIO_COLOR_CRTC_DATA); + } +} + +static void +chipsMmioWriteGr(vgaHWPtr hwp, CARD8 index, CARD8 value) +{ + moutb(CHIPS_MMIO_GRAPH_INDEX, index); + moutb(CHIPS_MMIO_GRAPH_DATA, value); +} + +static CARD8 +chipsMmioReadGr(vgaHWPtr hwp, CARD8 index) +{ + moutb(CHIPS_MMIO_GRAPH_INDEX, index); + return minb(CHIPS_MMIO_GRAPH_DATA); +} + +static void +chipsMmioWriteSeq(vgaHWPtr hwp, CARD8 index, CARD8 value) +{ + moutb(CHIPS_MMIO_SEQ_INDEX, index); + moutb(CHIPS_MMIO_SEQ_DATA, value); +} + +static CARD8 +chipsMmioReadSeq(vgaHWPtr hwp, CARD8 index) +{ + moutb(CHIPS_MMIO_SEQ_INDEX, index); + return minb(CHIPS_MMIO_SEQ_DATA); +} + +static void +chipsMmioWriteAttr(vgaHWPtr hwp, CARD8 index, CARD8 value) +{ + CARD8 tmp; + + if (hwp->paletteEnabled) + index &= ~0x20; + else + index |= 0x20; + + if (hwp->IOBase == VGA_IOBASE_MONO) + tmp = minb(CHIPS_MMIO_MONO_STAT_1); + else + tmp = minb(CHIPS_MMIO_COLOR_STAT_1); + moutb(CHIPS_MMIO_ATTR_INDEX, index); + moutb(CHIPS_MMIO_ATTR_DATA_W, value); +} + +static CARD8 +chipsMmioReadAttr(vgaHWPtr hwp, CARD8 index) +{ + CARD8 tmp; + + if (hwp->paletteEnabled) + index &= ~0x20; + else + index |= 0x20; + + if (hwp->IOBase == VGA_IOBASE_MONO) + tmp = minb(CHIPS_MMIO_MONO_STAT_1); + else + tmp = minb(CHIPS_MMIO_COLOR_STAT_1); + moutb(CHIPS_MMIO_ATTR_INDEX, index); + return minb(CHIPS_MMIO_ATTR_DATA_R); +} + +static void +chipsMmioWriteMiscOut(vgaHWPtr hwp, CARD8 value) +{ + moutb(CHIPS_MMIO_MISC_OUT_W, value); +} + +static CARD8 +chipsMmioReadMiscOut(vgaHWPtr hwp) +{ + return minb(CHIPS_MMIO_MISC_OUT_R); +} + +static void +chipsMmioEnablePalette(vgaHWPtr hwp) +{ + CARD8 tmp; + + if (hwp->IOBase == VGA_IOBASE_MONO) + tmp = minb(CHIPS_MMIO_MONO_STAT_1); + else + tmp = minb(CHIPS_MMIO_COLOR_STAT_1); + moutb(CHIPS_MMIO_ATTR_INDEX, 0x00); + hwp->paletteEnabled = TRUE; +} + +static void +chipsMmioDisablePalette(vgaHWPtr hwp) +{ + CARD8 tmp; + + if (hwp->IOBase == VGA_IOBASE_MONO) + tmp = minb(CHIPS_MMIO_MONO_STAT_1); + else + tmp = minb(CHIPS_MMIO_COLOR_STAT_1); + moutb(CHIPS_MMIO_ATTR_INDEX, 0x20); + hwp->paletteEnabled = FALSE; +} + +static void +chipsMmioWriteDacMask(vgaHWPtr hwp, CARD8 value) +{ + moutb(CHIPS_MMIO_DAC_MASK, value); +} + +static CARD8 +chipsMmioReadDacMask(vgaHWPtr hwp) +{ + return minb(CHIPS_MMIO_DAC_MASK); +} + +static void +chipsMmioWriteDacReadAddr(vgaHWPtr hwp, CARD8 value) +{ + moutb(CHIPS_MMIO_DAC_READ_ADDR, value); +} + +static void +chipsMmioWriteDacWriteAddr(vgaHWPtr hwp, CARD8 value) +{ + moutb(CHIPS_MMIO_DAC_WRITE_ADDR, value); +} + +static void +chipsMmioWriteDacData(vgaHWPtr hwp, CARD8 value) +{ + moutb(CHIPS_MMIO_DAC_DATA, value); +} + +static CARD8 +chipsMmioReadDacData(vgaHWPtr hwp) +{ + return minb(CHIPS_MMIO_DAC_DATA); +} + +static CARD8 +chipsMmioReadST00(vgaHWPtr hwp) +{ + return minb(CHIPS_MMIO_STAT_0); +} + +static CARD8 +chipsMmioReadST01(vgaHWPtr hwp) +{ + if (hwp->IOBase == VGA_IOBASE_MONO) + return minb(CHIPS_MMIO_MONO_STAT_1); + else + return minb(CHIPS_MMIO_COLOR_STAT_1); +} + +static CARD8 +chipsMmioReadFCR(vgaHWPtr hwp) +{ + return minb(CHIPS_MMIO_FEATURE_R); +} + +static void +chipsMmioWriteFCR(vgaHWPtr hwp, CARD8 value) +{ + if (hwp->IOBase == VGA_IOBASE_MONO) { + moutb(CHIPS_MMIO_MONO_STAT_1, value); + } else { + moutb(CHIPS_MMIO_COLOR_STAT_1, value); + } +} + +void +CHIPSHWSetMmioFuncs(ScrnInfoPtr pScrn, CARD8 *base, int offset) +{ + vgaHWPtr hwp = VGAHWPTR(pScrn); + + hwp->writeCrtc = chipsMmioWriteCrtc; + hwp->readCrtc = chipsMmioReadCrtc; + hwp->writeGr = chipsMmioWriteGr; + hwp->readGr = chipsMmioReadGr; + hwp->writeAttr = chipsMmioWriteAttr; + hwp->readAttr = chipsMmioReadAttr; + hwp->writeSeq = chipsMmioWriteSeq; + hwp->readSeq = chipsMmioReadSeq; + hwp->writeMiscOut = chipsMmioWriteMiscOut; + hwp->readMiscOut = chipsMmioReadMiscOut; + hwp->enablePalette = chipsMmioEnablePalette; + hwp->disablePalette = chipsMmioDisablePalette; + hwp->writeDacMask = chipsMmioWriteDacMask; + hwp->readDacMask = chipsMmioReadDacMask; + hwp->writeDacWriteAddr = chipsMmioWriteDacWriteAddr; + hwp->writeDacReadAddr = chipsMmioWriteDacReadAddr; + hwp->writeDacData = chipsMmioWriteDacData; + hwp->readDacData = chipsMmioReadDacData; + hwp->readST00 = chipsMmioReadST00; + hwp->readST01 = chipsMmioReadST01; + hwp->readFCR = chipsMmioReadFCR; + hwp->writeFCR = chipsMmioWriteFCR; + hwp->MMIOBase = base; + hwp->MMIOOffset = offset; +} + + + + diff --git a/src/ct_shadow.c b/src/ct_shadow.c new file mode 100644 index 0000000..ecbb642 --- /dev/null +++ b/src/ct_shadow.c @@ -0,0 +1,243 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/chips/ct_shadow.c,v 1.1 2000/02/08 13:13:13 eich Exp $ */ + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86Resources.h" +#include "xf86_ansic.h" +#include "xf86PciInfo.h" +#include "xf86Pci.h" +#include "shadowfb.h" +#include "servermd.h" +#include "ct_driver.h" + +void +chipsRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox) +{ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + int width, height, Bpp, FBPitch; + unsigned char *src, *dst; + + Bpp = pScrn->bitsPerPixel >> 3; + FBPitch = BitmapBytePad(pScrn->displayWidth * pScrn->bitsPerPixel); + + while(num--) { + width = (pbox->x2 - pbox->x1) * Bpp; + height = pbox->y2 - pbox->y1; + src = cPtr->ShadowPtr + (pbox->y1 * cPtr->ShadowPitch) + + (pbox->x1 * Bpp); + dst = cPtr->FbBase + (pbox->y1 * FBPitch) + (pbox->x1 * Bpp); + + while(height--) { + memcpy(dst, src, width); + dst += FBPitch; + src += cPtr->ShadowPitch; + } + + pbox++; + } +} + +void +chipsPointerMoved(int index, int x, int y) +{ + ScrnInfoPtr pScrn = xf86Screens[index]; + CHIPSPtr cPtr = CHIPSPTR(pScrn); + int newX, newY; + + if(cPtr->Rotate == 1) { + newX = pScrn->pScreen->height - y - 1; + newY = x; + } else { + newX = y; + newY = pScrn->pScreen->width - x - 1; + } + + (*cPtr->PointerMoved)(index, newX, newY); +} + +void +chipsRefreshArea8(ScrnInfoPtr pScrn, int num, BoxPtr pbox) +{ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + int count, width, height, y1, y2, dstPitch, srcPitch; + CARD8 *dstPtr, *srcPtr, *src; + CARD32 *dst; + + dstPitch = pScrn->displayWidth; + srcPitch = -cPtr->Rotate * cPtr->ShadowPitch; + + while(num--) { + width = pbox->x2 - pbox->x1; + y1 = pbox->y1 & ~3; + y2 = (pbox->y2 + 3) & ~3; + height = (y2 - y1) >> 2; /* in dwords */ + + if(cPtr->Rotate == 1) { + dstPtr = cPtr->FbBase + + (pbox->x1 * dstPitch) + pScrn->virtualX - y2; + srcPtr = cPtr->ShadowPtr + ((1 - y2) * srcPitch) + pbox->x1; + } else { + dstPtr = cPtr->FbBase + + ((pScrn->virtualY - pbox->x2) * dstPitch) + y1; + srcPtr = cPtr->ShadowPtr + (y1 * srcPitch) + pbox->x2 - 1; + } + + while(width--) { + src = srcPtr; + dst = (CARD32*)dstPtr; + count = height; + while(count--) { + *(dst++) = src[0] | (src[srcPitch] << 8) | + (src[srcPitch * 2] << 16) | + (src[srcPitch * 3] << 24); + src += srcPitch * 4; + } + srcPtr += cPtr->Rotate; + dstPtr += dstPitch; + } + + pbox++; + } +} + + +void +chipsRefreshArea16(ScrnInfoPtr pScrn, int num, BoxPtr pbox) +{ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + int count, width, height, y1, y2, dstPitch, srcPitch; + CARD16 *dstPtr, *srcPtr, *src; + CARD32 *dst; + + dstPitch = pScrn->displayWidth; + srcPitch = -cPtr->Rotate * cPtr->ShadowPitch >> 1; + + while(num--) { + width = pbox->x2 - pbox->x1; + y1 = pbox->y1 & ~1; + y2 = (pbox->y2 + 1) & ~1; + height = (y2 - y1) >> 1; /* in dwords */ + + if(cPtr->Rotate == 1) { + dstPtr = (CARD16*)cPtr->FbBase + + (pbox->x1 * dstPitch) + pScrn->virtualX - y2; + srcPtr = (CARD16*)cPtr->ShadowPtr + + ((1 - y2) * srcPitch) + pbox->x1; + } else { + dstPtr = (CARD16*)cPtr->FbBase + + ((pScrn->virtualY - pbox->x2) * dstPitch) + y1; + srcPtr = (CARD16*)cPtr->ShadowPtr + + (y1 * srcPitch) + pbox->x2 - 1; +/* ErrorF("dst: %x base: %x\n",dstPtr,cPtr->FbBase);*/ + } + + while(width--) { + src = srcPtr; + dst = (CARD32*)dstPtr; + count = height; + while(count--) { + *(dst++) = src[0] | (src[srcPitch] << 16); + src += srcPitch * 2; + } + srcPtr += cPtr->Rotate; + dstPtr += dstPitch; + } + + pbox++; + } +} + + +/* this one could be faster */ +void +chipsRefreshArea24(ScrnInfoPtr pScrn, int num, BoxPtr pbox) +{ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + int count, width, height, y1, y2, dstPitch, srcPitch; + CARD8 *dstPtr, *srcPtr, *src; + CARD32 *dst; + + dstPitch = BitmapBytePad(pScrn->displayWidth * 24); + srcPitch = -cPtr->Rotate * cPtr->ShadowPitch; + + while(num--) { + width = pbox->x2 - pbox->x1; + y1 = pbox->y1 & ~3; + y2 = (pbox->y2 + 3) & ~3; + height = (y2 - y1) >> 2; /* blocks of 3 dwords */ + + if(cPtr->Rotate == 1) { + dstPtr = cPtr->FbBase + + (pbox->x1 * dstPitch) + ((pScrn->virtualX - y2) * 3); + srcPtr = cPtr->ShadowPtr + ((1 - y2) * srcPitch) + (pbox->x1 * 3); + } else { + dstPtr = cPtr->FbBase + + ((pScrn->virtualY - pbox->x2) * dstPitch) + (y1 * 3); + srcPtr = cPtr->ShadowPtr + (y1 * srcPitch) + (pbox->x2 * 3) - 3; + } + + while(width--) { + src = srcPtr; + dst = (CARD32*)dstPtr; + count = height; + while(count--) { + dst[0] = src[0] | (src[1] << 8) | (src[2] << 16) | + (src[srcPitch] << 24); + dst[1] = src[srcPitch + 1] | (src[srcPitch + 2] << 8) | + (src[srcPitch * 2] << 16) | + (src[(srcPitch * 2) + 1] << 24); + dst[2] = src[(srcPitch * 2) + 2] | (src[srcPitch * 3] << 8) | + (src[(srcPitch * 3) + 1] << 16) | + (src[(srcPitch * 3) + 2] << 24); + dst += 3; + src += srcPitch * 4; + } + srcPtr += cPtr->Rotate * 3; + dstPtr += dstPitch; + } + + pbox++; + } +} + +void +chipsRefreshArea32(ScrnInfoPtr pScrn, int num, BoxPtr pbox) +{ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + int count, width, height, dstPitch, srcPitch; + CARD32 *dstPtr, *srcPtr, *src, *dst; + + dstPitch = pScrn->displayWidth; + srcPitch = -cPtr->Rotate * cPtr->ShadowPitch >> 2; + + while(num--) { + width = pbox->x2 - pbox->x1; + height = pbox->y2 - pbox->y1; + + if(cPtr->Rotate == 1) { + dstPtr = (CARD32*)cPtr->FbBase + + (pbox->x1 * dstPitch) + pScrn->virtualX - pbox->y2; + srcPtr = (CARD32*)cPtr->ShadowPtr + + ((1 - pbox->y2) * srcPitch) + pbox->x1; + } else { + dstPtr = (CARD32*)cPtr->FbBase + + ((pScrn->virtualY - pbox->x2) * dstPitch) + pbox->y1; + srcPtr = (CARD32*)cPtr->ShadowPtr + + (pbox->y1 * srcPitch) + pbox->x2 - 1; + } + + while(width--) { + src = srcPtr; + dst = dstPtr; + count = height; + while(count--) { + *(dst++) = *src; + src += srcPitch; + } + srcPtr += cPtr->Rotate; + dstPtr += dstPitch; + } + + pbox++; + } +} diff --git a/src/ct_video.c b/src/ct_video.c new file mode 100644 index 0000000..f5a824e --- /dev/null +++ b/src/ct_video.c @@ -0,0 +1,1163 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/chips/ct_video.c,v 1.12 2002/11/25 14:04:58 eich Exp $ */ + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86Resources.h" +#include "xf86_ansic.h" +#include "compiler.h" +#include "xf86PciInfo.h" +#include "xf86Pci.h" +#include "xf86fbman.h" +#include "regionstr.h" + +#include "ct_driver.h" +#include "Xv.h" +#include "xaa.h" +#include "xaalocal.h" +#include "dixstruct.h" +#include "fourcc.h" + +#define OFF_DELAY 200 /* milliseconds */ +#define FREE_DELAY 60000 + +#define OFF_TIMER 0x01 +#define FREE_TIMER 0x02 +#define CLIENT_VIDEO_ON 0x04 + +#define TIMER_MASK (OFF_TIMER | FREE_TIMER) + +#ifndef XvExtension +void CHIPSInitVideo(ScreenPtr pScreen) {} +void CHIPSResetVideo(ScrnInfoPtr pScrn) {} +#else + +static XF86VideoAdaptorPtr CHIPSSetupImageVideo(ScreenPtr); +static void CHIPSInitOffscreenImages(ScreenPtr); +static void CHIPSStopVideo(ScrnInfoPtr, pointer, Bool); +static int CHIPSSetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer); +static int CHIPSGetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer); +static void CHIPSQueryBestSize(ScrnInfoPtr, Bool, + short, short, short, short, unsigned int *, unsigned int *, pointer); +static int CHIPSPutImage( ScrnInfoPtr, + short, short, short, short, short, short, short, short, + int, unsigned char*, short, short, Bool, RegionPtr, pointer); +static int CHIPSQueryImageAttributes(ScrnInfoPtr, + int, unsigned short *, unsigned short *, int *, int *); +static void CHIPSVideoTimerCallback(ScrnInfoPtr pScrn, Time time); + + +#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) + +static Atom xvColorKey; + +void +CHIPSInitVideo(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL; + XF86VideoAdaptorPtr newAdaptor = NULL; + CHIPSPtr cPtr = CHIPSPTR(pScrn); + int num_adaptors; + + if (!(cPtr->Flags & ChipsOverlay8plus16) && + (cPtr->Flags & ChipsVideoSupport)) { + newAdaptor = CHIPSSetupImageVideo(pScreen); + CHIPSInitOffscreenImages(pScreen); + } + + num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); + + if(newAdaptor) { + if(!num_adaptors) { + num_adaptors = 1; + adaptors = &newAdaptor; + } else { + newAdaptors = /* need to free this someplace */ + xalloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*)); + if(newAdaptors) { + memcpy(newAdaptors, adaptors, num_adaptors * + sizeof(XF86VideoAdaptorPtr)); + newAdaptors[num_adaptors] = newAdaptor; + adaptors = newAdaptors; + num_adaptors++; + } + } + } + + if(num_adaptors) + xf86XVScreenInit(pScreen, adaptors, num_adaptors); + + if(newAdaptors) + xfree(newAdaptors); +} + +/* client libraries expect an encoding */ +static +XF86VideoEncodingRec DummyEncoding[1] = +{ + { + 0, + "XV_IMAGE", + 1024, 1024, + {1, 1} + } +}; + +#define NUM_FORMATS 4 + +static XF86VideoFormatRec Formats[NUM_FORMATS] = +{ + {8, PseudoColor}, {15, TrueColor}, {16, TrueColor}, {24, TrueColor} +}; + +#define NUM_ATTRIBUTES 1 + +static XF86AttributeRec Attributes[NUM_ATTRIBUTES] = +{ + {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"} +}; + +#define NUM_IMAGES 4 + +static XF86ImageRec Images[NUM_IMAGES] = +{ + { + 0x35315652, + XvRGB, + LSBFirst, + {'R','V','1','5', + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + 16, + XvPacked, + 1, + 15, 0x7C00, 0x03E0, 0x001F, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + {'R','V','B',0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + XvTopToBottom + }, + { + 0x36315652, + XvRGB, + LSBFirst, + {'R','V','1','6', + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + 16, + XvPacked, + 1, + 16, 0xF800, 0x07E0, 0x001F, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + {'R','V','B',0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + XvTopToBottom + }, + XVIMAGE_YV12, + XVIMAGE_YUY2 +}; + +typedef struct { + FBLinearPtr linear; + RegionRec clip; + CARD32 colorKey; + CARD32 videoStatus; + Time offTime; + Time freeTime; + Bool doubleBuffer; + Bool manualDoubleBuffer; + int currentBuffer; +} CHIPSPortPrivRec, *CHIPSPortPrivPtr; + + +#define GET_PORT_PRIVATE(pScrn) \ + (CHIPSPortPrivPtr)((CHIPSPTR(pScrn))->adaptor->pPortPrivates[0].ptr) + +void +CHIPSResetVideo(ScrnInfoPtr pScrn) +{ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSPortPrivPtr pPriv = cPtr->adaptor->pPortPrivates[0].ptr; + unsigned char mr3c; + int red, green, blue; + + if (cPtr->Flags & ChipsAccelSupport) + CHIPSHiQVSync(pScrn); + + mr3c = cPtr->readMR(cPtr, 0x3C); + cPtr->writeMR(cPtr, 0x3C, (mr3c | 0x6)); + switch (pScrn->depth) { + case 8: + cPtr->writeMR(cPtr, 0x3D, 0x00); + cPtr->writeMR(cPtr, 0x3E, 0x00); + cPtr->writeMR(cPtr, 0x3F, (pPriv->colorKey & 0xFF)); + cPtr->writeMR(cPtr, 0x40, 0xFF); + cPtr->writeMR(cPtr, 0x41, 0xFF); + cPtr->writeMR(cPtr, 0x42, 0x00); + break; + default: + red = (pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red; + green = (pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green; + blue = (pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue; + switch (pScrn->depth) { + case 15: + cPtr->writeMR(cPtr, 0x3D, (red << 3)); + cPtr->writeMR(cPtr, 0x3E, (green << 3)); + cPtr->writeMR(cPtr, 0x3F, (blue << 3)); + cPtr->writeMR(cPtr, 0x40, 0x07); + cPtr->writeMR(cPtr, 0x41, 0x07); + cPtr->writeMR(cPtr, 0x42, 0x07); + break; + case 16: + cPtr->writeMR(cPtr, 0x3D, (red << 3)); + cPtr->writeMR(cPtr, 0x3E, (green << 2)); + cPtr->writeMR(cPtr, 0x3F, (blue << 3)); + cPtr->writeMR(cPtr, 0x40, 0x07); + cPtr->writeMR(cPtr, 0x41, 0x03); + cPtr->writeMR(cPtr, 0x42, 0x07); + break; + case 24: + cPtr->writeMR(cPtr, 0x3D, red); + cPtr->writeMR(cPtr, 0x3E, green); + cPtr->writeMR(cPtr, 0x3F, blue); + cPtr->writeMR(cPtr, 0x40, 0x00); + cPtr->writeMR(cPtr, 0x41, 0x00); + cPtr->writeMR(cPtr, 0x42, 0x00); + break; + } + } +} + + +static XF86VideoAdaptorPtr +CHIPSSetupImageVideo(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + CHIPSPtr cPtr = CHIPSPTR(pScrn); + XF86VideoAdaptorPtr adapt; + CHIPSPortPrivPtr pPriv; + + if(!(adapt = xcalloc(1, sizeof(XF86VideoAdaptorRec) + + sizeof(CHIPSPortPrivRec) + + sizeof(DevUnion)))) + return NULL; + + adapt->type = XvWindowMask | XvInputMask | XvImageMask; + adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; + adapt->name = "Chips and Technologies Backend Scaler"; + adapt->nEncodings = 1; + adapt->pEncodings = DummyEncoding; + adapt->nFormats = NUM_FORMATS; + adapt->pFormats = Formats; + adapt->nPorts = 1; + adapt->pPortPrivates = (DevUnion*)(&adapt[1]); + pPriv = (CHIPSPortPrivPtr)(&adapt->pPortPrivates[1]); + adapt->pPortPrivates[0].ptr = (pointer)(pPriv); + adapt->pAttributes = Attributes; + adapt->nImages = NUM_IMAGES; + adapt->nAttributes = NUM_ATTRIBUTES; + adapt->pImages = Images; + adapt->PutVideo = NULL; + adapt->PutStill = NULL; + adapt->GetVideo = NULL; + adapt->GetStill = NULL; + adapt->StopVideo = CHIPSStopVideo; + adapt->SetPortAttribute = CHIPSSetPortAttribute; + adapt->GetPortAttribute = CHIPSGetPortAttribute; + adapt->QueryBestSize = CHIPSQueryBestSize; + adapt->PutImage = CHIPSPutImage; + adapt->QueryImageAttributes = CHIPSQueryImageAttributes; + + pPriv->colorKey = cPtr->videoKey; + pPriv->videoStatus = 0; + pPriv->doubleBuffer = TRUE; + pPriv->manualDoubleBuffer = FALSE; + pPriv->currentBuffer = 0; + + /* gotta uninit this someplace */ + REGION_INIT(pScreen, &pPriv->clip, NullBox, 0); + + cPtr->adaptor = adapt; + + xvColorKey = MAKE_ATOM("XV_COLORKEY"); + + CHIPSResetVideo(pScrn); + + return adapt; +} + + +static Bool +RegionsEqual(RegionPtr A, RegionPtr B) +{ + int *dataA, *dataB; + int num; + + num = REGION_NUM_RECTS(A); + if(num != REGION_NUM_RECTS(B)) + return FALSE; + + if((A->extents.x1 != B->extents.x1) || + (A->extents.x2 != B->extents.x2) || + (A->extents.y1 != B->extents.y1) || + (A->extents.y2 != B->extents.y2)) + return FALSE; + + dataA = (int*)REGION_RECTS(A); + dataB = (int*)REGION_RECTS(B); + + while(num--) { + if((dataA[0] != dataB[0]) || (dataA[1] != dataB[1])) + return FALSE; + dataA += 2; + dataB += 2; + } + + return TRUE; +} + + +/* CHIPSClipVideo - + + Takes the dst box in standard X BoxRec form (top and left + edges inclusive, bottom and right exclusive). The new dst + box is returned. The source boundaries are given (x1, y1 + inclusive, x2, y2 exclusive) and returned are the new source + boundaries in 16.16 fixed point. +*/ + +static Bool +CHIPSClipVideo( + BoxPtr dst, + INT32 *x1, + INT32 *x2, + INT32 *y1, + INT32 *y2, + RegionPtr reg, + INT32 width, + INT32 height +){ + INT32 vscale, hscale, delta; + BoxPtr extents = REGION_EXTENTS(DummyScreen, reg); + int diff; + + hscale = ((*x2 - *x1) << 16) / (dst->x2 - dst->x1); + vscale = ((*y2 - *y1) << 16) / (dst->y2 - dst->y1); + + *x1 <<= 16; *x2 <<= 16; + *y1 <<= 16; *y2 <<= 16; + + diff = extents->x1 - dst->x1; + if(diff > 0) { + dst->x1 = extents->x1; + *x1 += diff * hscale; + } + diff = dst->x2 - extents->x2; + if(diff > 0) { + dst->x2 = extents->x2; + *x2 -= diff * hscale; + } + diff = extents->y1 - dst->y1; + if(diff > 0) { + dst->y1 = extents->y1; + *y1 += diff * vscale; + } + diff = dst->y2 - extents->y2; + if(diff > 0) { + dst->y2 = extents->y2; + *y2 -= diff * vscale; + } + + if(*x1 < 0) { + diff = (- *x1 + hscale - 1)/ hscale; + dst->x1 += diff; + *x1 += diff * hscale; + } + delta = *x2 - (width << 16); + if(delta > 0) { + diff = (delta + hscale - 1)/ hscale; + dst->x2 -= diff; + *x2 -= diff * hscale; + } + if(*x1 >= *x2) return FALSE; + + if(*y1 < 0) { + diff = (- *y1 + vscale - 1)/ vscale; + dst->y1 += diff; + *y1 += diff * vscale; + } + delta = *y2 - (height << 16); + if(delta > 0) { + diff = (delta + vscale - 1)/ vscale; + dst->y2 -= diff; + *y2 -= diff * vscale; + } + if(*y1 >= *y2) return FALSE; + + if((dst->x1 != extents->x1) || (dst->x2 != extents->x2) || + (dst->y1 != extents->y1) || (dst->y2 != extents->y2)) + { + RegionRec clipReg; + REGION_INIT(DummyScreen, &clipReg, dst, 1); + REGION_INTERSECT(DummyScreen, reg, reg, &clipReg); + REGION_UNINIT(DummyScreen, &clipReg); + } + return TRUE; +} + +static void +CHIPSStopVideo(ScrnInfoPtr pScrn, pointer data, Bool shadow) +{ + CHIPSPortPrivPtr pPriv = (CHIPSPortPrivPtr)data; + CHIPSPtr cPtr = CHIPSPTR(pScrn); + unsigned char mr3c, tmp; + + REGION_EMPTY(pScrn->pScreen, &pPriv->clip); + if (cPtr->Flags & ChipsAccelSupport) + CHIPSHiQVSync(pScrn); + if(shadow) { + if(pPriv->videoStatus & CLIENT_VIDEO_ON) { + mr3c = cPtr->readMR(cPtr, 0x3C); + cPtr->writeMR(cPtr, 0x3C, (mr3c & 0xFE)); + tmp = cPtr->readXR(cPtr, 0xD0); + cPtr->writeXR(cPtr, 0xD0, (tmp & 0xf)); + } + if(pPriv->linear) { + xf86FreeOffscreenLinear(pPriv->linear); + pPriv->linear = NULL; + } + pPriv->videoStatus = 0; + } else { + if(pPriv->videoStatus & CLIENT_VIDEO_ON) { + pPriv->videoStatus |= OFF_TIMER; + pPriv->offTime = currentTime.milliseconds + OFF_DELAY; + cPtr->VideoTimerCallback = CHIPSVideoTimerCallback; + } + } +} + +static int +CHIPSSetPortAttribute( + ScrnInfoPtr pScrn, + Atom attribute, + INT32 value, + pointer data +){ + CHIPSPortPrivPtr pPriv = (CHIPSPortPrivPtr)data; + CHIPSPtr cPtr = CHIPSPTR(pScrn); + + if (cPtr->Flags & ChipsAccelSupport) + CHIPSHiQVSync(pScrn); + if(attribute == xvColorKey) { + int red, green, blue; + pPriv->colorKey = value; + switch (pScrn->depth) { + case 8: + cPtr->writeMR(cPtr, 0x3D, 0x00); + cPtr->writeMR(cPtr, 0x3E, 0x00); + cPtr->writeMR(cPtr, 0x3F, (pPriv->colorKey & 0xFF)); + break; + default: + red = (pPriv->colorKey & pScrn->mask.red) >> pScrn->offset.red; + green = (pPriv->colorKey & pScrn->mask.green) >> pScrn->offset.green; + blue = (pPriv->colorKey & pScrn->mask.blue) >> pScrn->offset.blue; + switch (pScrn->depth) { + case 15: + cPtr->writeMR(cPtr, 0x3D, (red << 3)); + cPtr->writeMR(cPtr, 0x3E, (green << 3)); + cPtr->writeMR(cPtr, 0x3F, (blue << 3)); + break; + case 16: + cPtr->writeMR(cPtr, 0x3D, (red << 3)); + cPtr->writeMR(cPtr, 0x3E, (green << 2)); + cPtr->writeMR(cPtr, 0x3F, (blue << 3)); + break; + case 24: + cPtr->writeMR(cPtr, 0x3D, red); + cPtr->writeMR(cPtr, 0x3E, green); + cPtr->writeMR(cPtr, 0x3F, blue); + break; + } + } + REGION_EMPTY(pScrn->pScreen, &pPriv->clip); + } else return BadMatch; + + return Success; +} + +static int +CHIPSGetPortAttribute( + ScrnInfoPtr pScrn, + Atom attribute, + INT32 *value, + pointer data +){ + CHIPSPortPrivPtr pPriv = (CHIPSPortPrivPtr)data; + + if(attribute == xvColorKey) { + *value = pPriv->colorKey; + } else return BadMatch; + + return Success; +} + +static void +CHIPSQueryBestSize( + ScrnInfoPtr pScrn, + Bool motion, + short vid_w, short vid_h, + short drw_w, short drw_h, + unsigned int *p_w, unsigned int *p_h, + pointer data +){ + *p_w = drw_w; + *p_h = drw_h; + + if(*p_w > 16384) *p_w = 16384; +} + + +static void +CHIPSCopyData( + unsigned char *src, + unsigned char *dst, + int srcPitch, + int dstPitch, + int h, + int w +){ + w <<= 1; + while(h--) { + memcpy(dst, src, w); + src += srcPitch; + dst += dstPitch; + } +} + +static void +CHIPSCopyMungedData( + unsigned char *src1, + unsigned char *src2, + unsigned char *src3, + unsigned char *dst1, + int srcPitch, + int srcPitch2, + int dstPitch, + int h, + int w +){ + CARD32 *dst = (CARD32*)dst1; + int i, j; + + dstPitch >>= 2; + w >>= 1; + + for(j = 0; j < h; j++) { + for(i = 0; i < w; i++) { + dst[i] = src1[i << 1] | (src1[(i << 1) + 1] << 16) | + (src3[i] << 8) | (src2[i] << 24); + } + dst += dstPitch; + src1 += srcPitch; + if(j & 1) { + src2 += srcPitch2; + src3 += srcPitch2; + } + } +} + +static FBLinearPtr +CHIPSAllocateMemory( + ScrnInfoPtr pScrn, + FBLinearPtr linear, + int size +){ + ScreenPtr pScreen; + FBLinearPtr new_linear; + + if(linear) { + if(linear->size >= size) + return linear; + + if(xf86ResizeOffscreenLinear(linear, size)) + return linear; + + xf86FreeOffscreenLinear(linear); + } + + pScreen = screenInfo.screens[pScrn->scrnIndex]; + + new_linear = xf86AllocateOffscreenLinear(pScreen, size, 16, + NULL, NULL, NULL); + + if(!new_linear) { + int max_size; + + xf86QueryLargestOffscreenLinear(pScreen, &max_size, 16, + PRIORITY_EXTREME); + + if(max_size < size) + return NULL; + + xf86PurgeUnlockedOffscreenAreas(pScreen); + new_linear = xf86AllocateOffscreenLinear(pScreen, size, 16, + NULL, NULL, NULL); + } + + return new_linear; +} + +static int +CHIPSSetCurrentPlaybackBuffer(CHIPSPtr cPtr, int n) +{ + + CARD8 mr20; + mr20 = cPtr->readMR(cPtr, 0x20); + mr20 &= ~0x1B; + if (!n) mr20 |= 0x10; + cPtr->writeMR(cPtr, 0x22, mr20); + return n; +} + +static int +CHIPSWaitGetNextFrame(CHIPSPtr cPtr) +{ + volatile CARD8 mr20; + volatile CARD8 mr21; + + mr20 = cPtr->readMR(cPtr, 0x20); + while (1) { + mr21 = cPtr->readMR(cPtr, 0x21); + if (!(mr20 & (1 << 5)) || !(mr21 & 1)) + break; + } + mr20 &= ~0x4; + mr20 = cPtr->readMR(cPtr, 0x20); + return (mr21 & 2)? 0 : 1; +} + +static void +CHIPSDisplayVideo( + ScrnInfoPtr pScrn, + int id, + int offset, + short width, short height, + int pitch, + int x1, int y1, int x2, int y2, + BoxPtr dstBox, + short src_w, short src_h, + short drw_w, short drw_h, + Bool triggerBufSwitch +){ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn); + DisplayModePtr mode = pScrn->currentMode; + unsigned char tmp, m1f, m1e; + int buffer = pPriv->currentBuffer; + + if (cPtr->Flags & ChipsAccelSupport) + CHIPSHiQVSync(pScrn); + + tmp = cPtr->readXR(cPtr, 0xD0); + cPtr->writeXR(cPtr, 0xD0, (tmp | 0x10)); + + m1e = cPtr->readMR(cPtr, 0x1E); + m1e &= 0xE0; /* Set Zoom and Direction */ + if ((!(cPtr->PanelType & ChipsLCD)) && (mode->Flags & V_INTERLACE)) + m1e |= 0x10; + + m1f = cPtr->readMR(cPtr, 0x1F); + m1f = (m1f & 0x14); /* Mask reserved bits, unset interpolation */ + switch(id) { + case 0x35315652: /* RGB15 */ + m1f |= 0x09; + break; + case 0x36315652: /* RGB16 */ + m1f |= 0x08; + break; + case FOURCC_YV12: /* YV12 */ + /* m1f |= 0x03 */ + m1f |= 0x00; + break; + case FOURCC_YUY2: /* YUY2 */ + default: + m1f |= 0x00; /* Do nothing here */ + break; + } + + offset += (x1 >> 15) & ~0x01; + /* Setup Pointer 1 */ + if (!buffer || pPriv->manualDoubleBuffer || !pPriv->doubleBuffer) { + cPtr->writeMR(cPtr, 0x22, (offset & 0xF8)); + cPtr->writeMR(cPtr, 0x23, ((offset >> 8) & 0xFF)); + cPtr->writeMR(cPtr, 0x24, ((offset >> 16) & 0xFF)); + } + /* Setup Pointer 2 */ + if ((buffer && !pPriv->manualDoubleBuffer) || !pPriv->doubleBuffer) { + cPtr->writeMR(cPtr, 0x25, (offset & 0xF8)); + cPtr->writeMR(cPtr, 0x26, ((offset >> 8) & 0xFF)); + cPtr->writeMR(cPtr, 0x27, ((offset >> 16) & 0xFF)); + } + + + tmp = cPtr->readMR(cPtr, 0x04); + if (pPriv->doubleBuffer && !pPriv->manualDoubleBuffer && triggerBufSwitch) + tmp |= 0x18; + cPtr->writeMR(cPtr, 0x04, tmp); + + tmp = cPtr->readMR(cPtr, 0x20); + tmp &= 0xC3; + if (pPriv->doubleBuffer && !pPriv->manualDoubleBuffer && triggerBufSwitch) + tmp |= ((1 << 2 | 1 << 5) | ((buffer) ? (1 << 4) : 0)); + cPtr->writeMR(cPtr, 0x20, tmp); + + cPtr->writeMR(cPtr, 0x28, ((width >> 2) - 1)); /* Width */ + cPtr->writeMR(cPtr, 0x34, ((width >> 2) - 1)); + + /* Left Edge of Overlay */ + cPtr->writeMR(cPtr, 0x2A, ((cPtr->OverlaySkewX + dstBox->x1) & 0xFF)); + tmp = cPtr->readMR(cPtr, 0x2B); + tmp = (tmp & 0xF8) + (((cPtr->OverlaySkewX + dstBox->x1) >> 8) & 0x07); + cPtr->writeMR(cPtr, 0x2B, tmp); + /* Right Edge of Overlay */ + cPtr->writeMR(cPtr, 0x2C, ((cPtr->OverlaySkewX + dstBox->x2 -1) + & 0xFF)); + tmp = cPtr->readMR(cPtr, 0x2D); + tmp = (tmp & 0xF8) + (((cPtr->OverlaySkewX + dstBox->x2 - 1) >> 8) & 0x07); + cPtr->writeMR(cPtr, 0x2D, tmp); + /* Top Edge of Overlay */ + cPtr->writeMR(cPtr, 0x2E, ((cPtr->OverlaySkewY + dstBox->y1) & 0xFF)); + tmp = cPtr->readMR(cPtr, 0x2F); + tmp = (tmp & 0xF8) + (((cPtr->OverlaySkewY + dstBox->y1) >> 8) & 0x07); + cPtr->writeMR(cPtr, 0x2F, tmp); + /* Bottom Edge of Overlay*/ + cPtr->writeMR(cPtr, 0x30, ((cPtr->OverlaySkewY + dstBox->y2 - 1) & 0xFF)); + tmp = cPtr->readMR(cPtr, 0x31); + tmp = (tmp & 0xF8) + (((cPtr->OverlaySkewY + dstBox->y2 - 1) >> 8) & 0x07); + cPtr->writeMR(cPtr, 0x31, tmp); + + /* Horizontal Zoom */ + if (drw_w > src_w) { + m1f = m1f | 0x20; /* set H-interpolation */ + m1e = m1e | 0x04; + tmp = cPtr->VideoZoomMax * src_w / drw_w; + cPtr->writeMR(cPtr, 0x32, tmp); + } + + /* Vertical Zoom */ + if (drw_h > src_h) { + m1f = m1f | 0x80; + m1e = m1e | 0x08; /* set V-interpolation */ + tmp = cPtr->VideoZoomMax * src_h / drw_h ; + cPtr->writeMR(cPtr, 0x33, tmp); + } + cPtr->writeMR(cPtr, 0x1F, m1f); + cPtr->writeMR(cPtr, 0x1E, m1e); + + tmp = cPtr->readMR(cPtr, 0x3C); + cPtr->writeMR(cPtr, 0x3C, (tmp | 0x7)); + if (cPtr->Flags & ChipsAccelSupport) + CHIPSHiQVSync(pScrn); +} + +static int +CHIPSPutImage( + ScrnInfoPtr pScrn, + short src_x, short src_y, + short drw_x, short drw_y, + short src_w, short src_h, + short drw_w, short drw_h, + int id, unsigned char* buf, + short width, short height, + Bool sync, + RegionPtr clipBoxes, pointer data +){ + CHIPSPortPrivPtr pPriv = (CHIPSPortPrivPtr)data; + CHIPSPtr cPtr = CHIPSPTR(pScrn); + INT32 x1, x2, y1, y2; + unsigned char *dst_start; + int pitch, new_size, offset, offset2 = 0, offset3 = 0; + int srcPitch, srcPitch2 = 0, dstPitch; + int top, left, npixels, nlines, bpp; + BoxRec dstBox; + CARD32 tmp; + + if(drw_w > 16384) drw_w = 16384; + + /* Clip */ + x1 = src_x; + x2 = src_x + src_w; + y1 = src_y; + y2 = src_y + src_h; + + dstBox.x1 = drw_x; + dstBox.x2 = drw_x + drw_w; + dstBox.y1 = drw_y; + dstBox.y2 = drw_y + drw_h; + + if (!CHIPSClipVideo(&dstBox, &x1, &x2, &y1, &y2, clipBoxes, width, height)) + return Success; + + dstBox.x1 -= pScrn->frameX0 & cPtr->viewportMask; + dstBox.x2 -= pScrn->frameX0 & cPtr->viewportMask; + dstBox.y1 -= pScrn->frameY0; + dstBox.y2 -= pScrn->frameY0; + + bpp = pScrn->bitsPerPixel >> 3; + pitch = bpp * pScrn->displayWidth; + + dstPitch = ((width << 1) + 15) & ~15; + new_size = ((dstPitch * height) + bpp - 1) / bpp; + if (pPriv->doubleBuffer) + new_size <<= 1; + + switch(id) { + case FOURCC_YV12: /* YV12 */ + srcPitch = (width + 3) & ~3; + offset2 = srcPitch * height; + srcPitch2 = ((width >> 1) + 3) & ~3; + offset3 = (srcPitch2 * (height >> 1)) + offset2; + break; + default: /* RGB15, RGB16, YUY2 */ + srcPitch = (width << 1); + break; + } + + if(!(pPriv->linear = CHIPSAllocateMemory(pScrn, pPriv->linear, new_size))) { + if (pPriv->doubleBuffer && + (pPriv->linear = CHIPSAllocateMemory(pScrn, pPriv->linear, + new_size >> 1))) { + new_size >>= 1; + pPriv->doubleBuffer = FALSE; + } else + return BadAlloc; + } + + /* copy data */ + top = y1 >> 16; + left = (x1 >> 16) & ~1; + npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left; + left <<= 1; + + offset = pPriv->linear->offset * bpp; + if (!pPriv->manualDoubleBuffer) + pPriv->currentBuffer = CHIPSWaitGetNextFrame(cPtr); + if(pPriv->doubleBuffer && pPriv->currentBuffer) + offset += (new_size * bpp) >> 1; + + dst_start = cPtr->FbBase + offset + left + (top * dstPitch); + + switch(id) { + case FOURCC_YV12: /* YV12 */ + top &= ~1; + tmp = ((top >> 1) * srcPitch2) + (left >> 2); + offset2 += tmp; + offset3 += tmp; + nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top; + CHIPSCopyMungedData(buf + (top * srcPitch) + (left >> 1), + buf + offset2, buf + offset3, dst_start, + srcPitch, srcPitch2, dstPitch, nlines, npixels); + break; + default: /* RGB15, RGB16, YUY2 */ + buf += (top * srcPitch) + left; + nlines = ((y2 + 0xffff) >> 16) - top; + CHIPSCopyData(buf, dst_start, srcPitch, dstPitch, nlines, npixels); + break; + } + + /* update cliplist */ + if(!RegionsEqual(&pPriv->clip, clipBoxes)) { + REGION_COPY(pScreen, &pPriv->clip, clipBoxes); + xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes); + } + + offset += top * dstPitch; + CHIPSDisplayVideo(pScrn, id, offset, width, height, dstPitch, + x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h, TRUE); + + pPriv->videoStatus = CLIENT_VIDEO_ON; + + if (pPriv->manualDoubleBuffer) + pPriv->currentBuffer ^= 1; + + return Success; +} + +static int +CHIPSQueryImageAttributes( + ScrnInfoPtr pScrn, + int id, + unsigned short *w, unsigned short *h, + int *pitches, int *offsets +){ + int size, tmp; + + if(*w > 1024) *w = 1024; + if(*h > 1024) *h = 1024; + + *w = (*w + 1) & ~1; + if(offsets) offsets[0] = 0; + + switch(id) { + case FOURCC_YV12: /* YV12 */ + *h = (*h + 1) & ~1; + size = (*w + 3) & ~3; + if(pitches) pitches[0] = size; + size *= *h; + if(offsets) offsets[1] = size; + tmp = ((*w >> 1) + 3) & ~3; + if(pitches) pitches[1] = pitches[2] = tmp; + tmp *= (*h >> 1); + size += tmp; + if(offsets) offsets[2] = size; + size += tmp; + break; + default: /* RGB15, RGB16, YUY2 */ + size = *w << 1; + if(pitches) pitches[0] = size; + size *= *h; + break; + } + + return size; +} + + +static void +CHIPSVideoTimerCallback(ScrnInfoPtr pScrn, Time time) +{ + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSPortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn); + unsigned char mr3c; + + if(pPriv->videoStatus & TIMER_MASK) { + if(pPriv->videoStatus & OFF_TIMER) { + if(pPriv->offTime < time) { + if (cPtr->Flags & ChipsAccelSupport) + CHIPSHiQVSync(pScrn); + mr3c = cPtr->readMR(cPtr, 0x3C); + cPtr->writeMR(cPtr, 0x3C, (mr3c & 0xFE)); + pPriv->videoStatus = FREE_TIMER; + pPriv->freeTime = currentTime.milliseconds + FREE_DELAY; + } + } else { /* FREE_TIMER */ + if(pPriv->freeTime < time) { + if(pPriv->linear) { + xf86FreeOffscreenLinear(pPriv->linear); + pPriv->linear = NULL; + } + pPriv->videoStatus = 0; + cPtr->VideoTimerCallback = NULL; + } + } + } else /* shouldn't get here */ + cPtr->VideoTimerCallback = NULL; +} + + +/****************** Offscreen stuff ***************/ + +typedef struct { + FBLinearPtr linear; + Bool isOn; +} OffscreenPrivRec, * OffscreenPrivPtr; + +static int +CHIPSAllocateSurface( + ScrnInfoPtr pScrn, + int id, + unsigned short w, + unsigned short h, + XF86SurfacePtr surface +){ + FBLinearPtr linear; + int pitch, fbpitch, size, bpp; + OffscreenPrivPtr pPriv; + + if((w > 1024) || (h > 1024)) + return BadAlloc; + + w = (w + 1) & ~1; + pitch = ((w << 1) + 15) & ~15; + bpp = pScrn->bitsPerPixel >> 3; + fbpitch = bpp * pScrn->displayWidth; + size = ((pitch * h) + bpp - 1) / bpp; + + if(!(linear = CHIPSAllocateMemory(pScrn, NULL, size))) + return BadAlloc; + + surface->width = w; + surface->height = h; + + if(!(surface->pitches = xalloc(sizeof(int)))) { + xf86FreeOffscreenLinear(linear); + return BadAlloc; + } + if(!(surface->offsets = xalloc(sizeof(int)))) { + xfree(surface->pitches); + xf86FreeOffscreenLinear(linear); + return BadAlloc; + } + if(!(pPriv = xalloc(sizeof(OffscreenPrivRec)))) { + xfree(surface->pitches); + xfree(surface->offsets); + xf86FreeOffscreenLinear(linear); + return BadAlloc; + } + + pPriv->linear = linear; + pPriv->isOn = FALSE; + + surface->pScrn = pScrn; + surface->id = id; + surface->pitches[0] = pitch; + surface->offsets[0] = linear->offset * bpp; + surface->devPrivate.ptr = (pointer)pPriv; + + return Success; +} + +static int +CHIPSStopSurface( + XF86SurfacePtr surface +){ + OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; + + if(pPriv->isOn) { + CHIPSPtr cPtr = CHIPSPTR(surface->pScrn); + unsigned char mr3c, tmp; + tmp = cPtr->readXR(cPtr, 0xD0); + cPtr->writeXR(cPtr, 0xD0, (tmp & 0xf)); + mr3c = cPtr->readMR(cPtr, 0x3C); + cPtr->writeMR(cPtr, 0x3C, (mr3c & 0xFE)); + pPriv->isOn = FALSE; + } + + return Success; +} + + +static int +CHIPSFreeSurface( + XF86SurfacePtr surface +){ + OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; + + if(pPriv->isOn) + CHIPSStopSurface(surface); + xf86FreeOffscreenLinear(pPriv->linear); + xfree(surface->pitches); + xfree(surface->offsets); + xfree(surface->devPrivate.ptr); + + return Success; +} + +static int +CHIPSGetSurfaceAttribute( + ScrnInfoPtr pScrn, + Atom attribute, + INT32 *value +){ + return CHIPSGetPortAttribute(pScrn, attribute, value, + (pointer)(GET_PORT_PRIVATE(pScrn))); +} + +static int +CHIPSSetSurfaceAttribute( + ScrnInfoPtr pScrn, + Atom attribute, + INT32 value +){ + return CHIPSSetPortAttribute(pScrn, attribute, value, + (pointer)(GET_PORT_PRIVATE(pScrn))); +} + + +static int +CHIPSDisplaySurface( + XF86SurfacePtr surface, + short src_x, short src_y, + short drw_x, short drw_y, + short src_w, short src_h, + short drw_w, short drw_h, + RegionPtr clipBoxes +){ + OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; + ScrnInfoPtr pScrn = surface->pScrn; + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSPortPrivPtr portPriv = GET_PORT_PRIVATE(pScrn); + INT32 x1, y1, x2, y2; + BoxRec dstBox; + + x1 = src_x; + x2 = src_x + src_w; + y1 = src_y; + y2 = src_y + src_h; + + dstBox.x1 = drw_x; + dstBox.x2 = drw_x + drw_w; + dstBox.y1 = drw_y; + dstBox.y2 = drw_y + drw_h; + + if(!CHIPSClipVideo(&dstBox, &x1, &x2, &y1, &y2, clipBoxes, + surface->width, surface->height)) + return Success; + + dstBox.x1 -= pScrn->frameX0; + dstBox.x2 -= pScrn->frameX0; + dstBox.y1 -= pScrn->frameY0; + dstBox.y2 -= pScrn->frameY0; + + if (portPriv->doubleBuffer) + portPriv->currentBuffer = CHIPSSetCurrentPlaybackBuffer(cPtr,0); + else + portPriv->currentBuffer = 0; + + CHIPSDisplayVideo(pScrn, surface->id, surface->offsets[0], + surface->width, surface->height, surface->pitches[0], + x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h, FALSE); + xf86XVFillKeyHelper(pScrn->pScreen, portPriv->colorKey, clipBoxes); + + pPriv->isOn = TRUE; + if(portPriv->videoStatus & CLIENT_VIDEO_ON) { + REGION_EMPTY(pScrn->pScreen, &portPriv->clip); + UpdateCurrentTime(); + portPriv->videoStatus = FREE_TIMER; + portPriv->freeTime = currentTime.milliseconds + FREE_DELAY; + cPtr->VideoTimerCallback = CHIPSVideoTimerCallback; + } + + return Success; +} + + +static void +CHIPSInitOffscreenImages(ScreenPtr pScreen) +{ + XF86OffscreenImagePtr offscreenImages; + + /* need to free this someplace */ + if(!(offscreenImages = xalloc(sizeof(XF86OffscreenImageRec)))) + return; + + offscreenImages[0].image = &Images[0]; + offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES | + VIDEO_CLIP_TO_VIEWPORT; + offscreenImages[0].alloc_surface = CHIPSAllocateSurface; + offscreenImages[0].free_surface = CHIPSFreeSurface; + offscreenImages[0].display = CHIPSDisplaySurface; + offscreenImages[0].stop = CHIPSStopSurface; + offscreenImages[0].setAttribute = CHIPSSetSurfaceAttribute; + offscreenImages[0].getAttribute = CHIPSGetSurfaceAttribute; + offscreenImages[0].max_width = 1024; + offscreenImages[0].max_height = 1024; + offscreenImages[0].num_attributes = NUM_ATTRIBUTES; + offscreenImages[0].attributes = Attributes; + + xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1); +} + +#endif /* !XvExtension */ diff --git a/util/AsmMacros.h b/util/AsmMacros.h new file mode 100644 index 0000000..feb5ce0 --- /dev/null +++ b/util/AsmMacros.h @@ -0,0 +1,450 @@ +/* $XConsortium: AsmMacros.h /main/13 1996/10/25 11:33:12 kaleb $ */ +/* + * (c) Copyright 1993,1994 by David Wexelblat <dwex@xfree86.org> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * DAVID WEXELBLAT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of David Wexelblat shall not be + * used in advertising or otherwise to promote the sale, use or other dealings + * in this Software without prior written authorization from David Wexelblat. + * + */ +/* + * Copyright 1997 + * Digital Equipment Corporation. All rights reserved. + * This software is furnished under license and may be used and copied only in + * accordance with the following terms and conditions. Subject to these + * conditions, you may download, copy, install, use, modify and distribute + * this software in source and/or binary form. No title or ownership is + * transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce and retain + * this copyright notice and list of conditions as they appear in the source + * file. + * + * 2) No right is granted to use any trade name, trademark, or logo of Digital + * Equipment Corporation. Neither the "Digital Equipment Corporation" name + * nor any trademark or logo of Digital Equipment Corporation may be used + * to endorse or promote products derived from this software without the + * prior written permission of Digital Equipment Corporation. + * + * 3) This software is provided "AS-IS" and any express or implied warranties, + * including but not limited to, any implied warranties of merchantability, + * fitness for a particular purpose, or non-infringement are disclaimed. In + * no event shall DIGITAL be liable for any damages whatsoever, and in + * particular, DIGITAL shall not be liable for special, indirect, + * consequential, or incidental damages or damages for + * lost profits, loss of revenue or loss of use, whether such damages arise + * in contract, + * negligence, tort, under statute, in equity, at law or otherwise, even if + * advised of the possibility of such damage. + * + */ + +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/chips/util/AsmMacros.h,v 1.1 2001/11/16 21:13:34 tsi Exp $ */ + +#if defined(__GNUC__) +#if defined(linux) && (defined(__alpha__) || defined(__ia64__)) +#undef inb +#undef inw +#undef inl +#undef outb +#undef outw +#undef outl +#define inb _inb +#define inw _inw +#define inl _inl +#define outb(p,v) _outb((v),(p)) +#define outw(p,v) _outw((v),(p)) +#define outl(p,v) _outl((v),(p)) +#else +#if defined(__sparc__) +#ifndef ASI_PL +#define ASI_PL 0x88 +#endif + +static __inline__ void +outb(port, val) +unsigned long port; +char val; +{ + __asm__ __volatile__("stba %0, [%1] %2" : : "r" (val), "r" (port), "i" (ASI_PL)); +} + +static __inline__ void +outw(port, val) +unsigned long port; +char val; +{ + __asm__ __volatile__("stha %0, [%1] %2" : : "r" (val), "r" (port), "i" (ASI_PL)); +} + +static __inline__ void +outl(port, val) +unsigned long port; +char val; +{ + __asm__ __volatile__("sta %0, [%1] %2" : : "r" (val), "r" (port), "i" (ASI_PL)); +} + +static __inline__ unsigned int +inb(port) +unsigned long port; +{ + unsigned char ret; + __asm__ __volatile__("lduba [%1] %2, %0" : "=r" (ret) : "r" (port), "i" (ASI_PL)); + return ret; +} + +static __inline__ unsigned int +inw(port) +unsigned long port; +{ + unsigned char ret; + __asm__ __volatile__("lduha [%1] %2, %0" : "=r" (ret) : "r" (port), "i" (ASI_PL)); + return ret; +} + +static __inline__ unsigned int +inl(port) +unsigned long port; +{ + unsigned char ret; + __asm__ __volatile__("lda [%1] %2, %0" : "=r" (ret) : "r" (port), "i" (ASI_PL)); + return ret; +} +#else +#ifdef __arm32__ +unsigned int IOPortBase; /* Memory mapped I/O port area */ + +static __inline__ void +outb(port, val) + short port; + char val; +{ + if ((unsigned short)port >= 0x400) return; + + *(volatile unsigned char*)(((unsigned short)(port))+IOPortBase) = val; +} + +static __inline__ void +outw(port, val) + short port; + short val; +{ + if ((unsigned short)port >= 0x400) return; + + *(volatile unsigned short*)(((unsigned short)(port))+IOPortBase) = val; +} + +static __inline__ void +outl(port, val) + short port; + int val; +{ + if ((unsigned short)port >= 0x400) return; + + *(volatile unsigned long*)(((unsigned short)(port))+IOPortBase) = val; +} + +static __inline__ unsigned int +inb(port) + short port; +{ + if ((unsigned short)port >= 0x400) return((unsigned int)-1); + + return(*(volatile unsigned char*)(((unsigned short)(port))+IOPortBase)); +} + +static __inline__ unsigned int +inw(port) + short port; +{ + if ((unsigned short)port >= 0x400) return((unsigned int)-1); + + return(*(volatile unsigned short*)(((unsigned short)(port))+IOPortBase)); +} + +static __inline__ unsigned int +inl(port) + short port; +{ + if ((unsigned short)port >= 0x400) return((unsigned int)-1); + + return(*(volatile unsigned long*)(((unsigned short)(port))+IOPortBase)); +} +#else /* __arm32__ */ +#if defined(Lynx) && defined(__powerpc__) +extern unsigned char *ioBase; + +static volatile void +eieio() +{ + __asm__ __volatile__ ("eieio"); +} + +static void +outb(port, value) +short port; +unsigned char value; +{ + *(uchar *)(ioBase + port) = value; eieio(); +} + +static void +outw(port, value) +short port; +unsigned short value; +{ + *(unsigned short *)(ioBase + port) = value; eieio(); +} + +static void +outl(port, value) +short port; +unsigned long value; +{ + *(unsigned long *)(ioBase + port) = value; eieio(); +} + +static unsigned char +inb(port) +short port; +{ + unsigned char val; + + val = *((unsigned char *)(ioBase + port)); eieio(); + return(val); +} + +static unsigned short +inw(port) +short port; +{ + unsigned short val; + + val = *((unsigned short *)(ioBase + port)); eieio(); + return(val); +} + +static unsigned long +inl(port) +short port; +{ + unsigned long val; + + val = *((unsigned long *)(ioBase + port)); eieio(); + return(val); +} + +#else +#if defined(__FreeBSD__) && defined(__alpha__) + +#include <sys/types.h> + +extern void outb(u_int32_t port, u_int8_t val); +extern void outw(u_int32_t port, u_int16_t val); +extern void outl(u_int32_t port, u_int32_t val); +extern u_int8_t inb(u_int32_t port); +extern u_int16_t inw(u_int32_t port); +extern u_int32_t inl(u_int32_t port); + +#else +#ifdef GCCUSESGAS +static __inline__ void +outb(port, val) +short port; +char val; +{ + __asm__ __volatile__("outb %0,%1" : :"a" (val), "d" (port)); +} + +static __inline__ void +outw(port, val) +short port; +short val; +{ + __asm__ __volatile__("outw %0,%1" : :"a" (val), "d" (port)); +} + +static __inline__ void +outl(port, val) +short port; +unsigned int val; +{ + __asm__ __volatile__("outl %0,%1" : :"a" (val), "d" (port)); +} + +static __inline__ unsigned int +inb(port) +short port; +{ + unsigned char ret; + __asm__ __volatile__("inb %1,%0" : + "=a" (ret) : + "d" (port)); + return ret; +} + +static __inline__ unsigned int +inw(port) +short port; +{ + unsigned short ret; + __asm__ __volatile__("inw %1,%0" : + "=a" (ret) : + "d" (port)); + return ret; +} + +static __inline__ unsigned int +inl(port) +short port; +{ + unsigned int ret; + __asm__ __volatile__("inl %1,%0" : + "=a" (ret) : + "d" (port)); + return ret; +} + +#else /* GCCUSESGAS */ + +static __inline__ void +outb(port, val) + short port; + char val; +{ + __asm__ __volatile__("out%B0 (%1)" : :"a" (val), "d" (port)); +} + +static __inline__ void +outw(port, val) + short port; + short val; +{ + __asm__ __volatile__("out%W0 (%1)" : :"a" (val), "d" (port)); +} + +static __inline__ void +outl(port, val) + short port; + unsigned int val; +{ + __asm__ __volatile__("out%L0 (%1)" : :"a" (val), "d" (port)); +} + +static __inline__ unsigned int +inb(port) + short port; +{ + unsigned int ret; + __asm__ __volatile__("in%B0 (%1)" : + "=a" (ret) : + "d" (port)); + return ret; +} + +static __inline__ unsigned int +inw(port) + short port; +{ + unsigned int ret; + __asm__ __volatile__("in%W0 (%1)" : + "=a" (ret) : + "d" (port)); + return ret; +} + +static __inline__ unsigned int +inl(port) + short port; +{ + unsigned int ret; + __asm__ __volatile__("in%L0 (%1)" : + "=a" (ret) : + "d" (port)); + return ret; +} + +#endif /* GCCUSESGAS */ +#endif /* Lynx && __powerpc__ */ +#endif /* arm32 */ +#endif /* linux && __sparc__ */ +#endif /* linux && __alpha__ */ +#endif /* __FreeBSD__ && __alpha__ */ + +#if defined(linux) || defined(__arm32__) || (defined(Lynx) && defined(__powerpc__)) + +#define intr_disable() +#define intr_enable() + +#else + +static __inline__ void +intr_disable() +{ + __asm__ __volatile__("cli"); +} + +static __inline__ void +intr_enable() +{ + __asm__ __volatile__("sti"); +} + +#endif /* else !linux && !__arm32__ */ + +#else /* __GNUC__ */ + +#if defined(_MINIX) && defined(_ACK) + +/* inb, outb, inw and outw are defined in the library */ +/* ... but I've no idea if the same is true for inl & outl */ + +u8_t inb(U16_t); +void outb(U16_t, U8_t); +u16_t inw(U16_t); +void outw(U16_t, U16_t); +u32_t inl(U16_t); +void outl(U16_t, U32_t); + +#else /* not _MINIX and _ACK */ + +# if defined(__STDC__) && (__STDC__ == 1) +# ifndef NCR +# define asm __asm +# endif +# endif +# ifdef SVR4 +# include <sys/types.h> +# ifndef __USLC__ +# define __USLC__ +# endif +# endif +#ifndef SCO325 +# include <sys/inline.h> +#else +# include "../common/scoasm.h" +#endif +#define intr_disable() asm("cli") +#define intr_enable() asm("sti") + +#endif /* _MINIX and _ACK */ +#endif /* __GNUC__ */ diff --git a/util/dRegs.c b/util/dRegs.c new file mode 100644 index 0000000..0c8ee62 --- /dev/null +++ b/util/dRegs.c @@ -0,0 +1,305 @@ +/* $XConsortium: dRegs.c /main/2 1996/10/27 11:49:40 kaleb $ */ + + + + + +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/chips/util/dRegs.c,v 1.9 2001/11/16 21:13:34 tsi Exp $ */ + +#ifdef __NetBSD__ +# include <sys/types.h> +# include <machine/pio.h> +# include <machine/sysarch.h> +#else +# if defined(SVR4) && defined(i386) +# include <sys/types.h> +# ifdef NCR + /* broken NCR <sys/sysi86.h> */ +# define __STDC +# include <sys/sysi86.h> +# undef __STDC +# else +# include <sys/sysi86.h> +# endif +# ifdef SVR4 +# if !defined(sun) +# include <sys/seg.h> +# endif +# endif +# include <sys/v86.h> +# if defined(sun) +# include <sys/psw.h> +# endif +# endif +# include "AsmMacros.h" +#endif /* NetBSD */ + +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> + +#ifdef __NetBSD__ +# define SET_IOPL() i386_iopl(3) +# define RESET_IOPL() i386_iopl(0) +#else +# if defined(SVR4) && defined(i386) +# ifndef SI86IOPL +# define SET_IOPL() sysi86(SI86V86,V86SC_IOPL,PS_IOPL) +# define RESET_IOPL() sysi86(SI86V86,V86SC_IOPL,0) +# else +# define SET_IOPL() sysi86(SI86IOPL,3) +# define RESET_IOPL() sysi86(SI86IOPL,0) +# endif +# else +# ifdef linux +# define SET_IOPL() iopl(3) +# define RESET_IOPL() iopl(0) +# else +# define SET_IOPL() (void)0 +# define RESET_IOPL() (void)0 +# endif +# endif +#endif + +int main(void) +{ + int i, HTotal, HDisplay, HSyncStart, HSyncEnd, + VTotal, VDisplay, VSyncStart, VSyncEnd; + unsigned char storeReg, bpp, shift, IOSS = 0, MSS = 0, again = 0; + unsigned short port; + int isHiQV = 0; + int is69030 = 0; + + SET_IOPL(); + + printf("0x3C6\t0x%X\n",inw(0x3C6)); + +/* Check to see if the Chip is HiQV */ + outb(0x3D6,0x02); + storeReg = inb(0x3D7); + if (storeReg == 0xE0 /* CT65550 */ + || storeReg == 0xE4 /* CT65554 */ + || storeReg == 0xE5 /* CT65555 */ + || storeReg == 0xF4 /* CT68554 */ + || storeReg == 0xC0) /* CT69000 */ + { + isHiQV = 1; + } else if (storeReg == 0x30) { + outb(0x3D6,0x03); + storeReg = inb(0x3D7); + if (storeReg == 0xC) { + isHiQV = 1; + is69030 = 1; + IOSS=inb(0x3CD); + MSS=inb(0x3CB); + outb(0x3CD,((IOSS&0xE0)| 0x11)); /* Select Channel 0 */ + outb(0x3CB,((MSS&0xF0)| 0x8)); + again = 1; + printf("Pipeline A:\n"); + } + } + + again: + printf("port 0x3D6 (C&T)\n"); + storeReg = inb(0x3D6); + shift = 3; + if (isHiQV==1) { + outw(0x102,1); /*global enable, VGA awake*/ + printf("0x%2.2X\n",inb(0x3C3)&0xFF); + outb(0x3C3,0); /*disable VGA*/ + outb(0x3C3,1); /*enable VGA*/ + for(i = 0;i < 0xFF;i++){ + outb(0x3D6,i); + printf("XR 0x%2.2X\t0x%2.2X\n",i,inb(0x3D7)&0xFF); + } + outb(0x3D6,0xE2); + bpp = inb(0x3D7)&0xF0; + } else { + outb(0x3D6, 0x70); + outw(0x3D6, (inw(0x3D6) | 0x8070)); + outw(0x46E8,0x0016); /*setup mode*/ + outw(0x102,1); /*global enable, VGA awake*/ + outw(0x46E8,0x000E); /*exit from setup mode*/ + printf("0x%2.2X\n",inb(0x3C3)&0xFF); + outb(0x3C3,0); /*disable VGA*/ + outw(0x46E8,0x0000); /*exit from setup mode*/ + outw(0x46E8,0x000E); /*exit from setup mode*/ + outb(0x3C3,1); /*enable VGA*/ + outw(0x46E8,0x0000); /*exit from setup mode*/ + for(i = 0;i < 0x80;i++){ + outb(0x3D6,i); + printf("XR 0x%2.2X\t0x%2.2X\n",i,inb(0x3D7)&0xFF); + } + outb(0x3D6,0x2B); + bpp = inb(0x3D7)&0xF0; + } + + switch(bpp){ + case 0x20: + bpp = 4; + break; + case 0x30: + bpp = 8; + break; + case 0x40: + bpp = 16; + shift = 2; + break; + case 0x50: + bpp = 24; + break; + default: + bpp = 0; + } + outb(0x3D6,storeReg); + + printf("\nport 0x3D4 (CRTC)\n"); + storeReg = inb(0x3D4); + if (isHiQV==1) { + for(i = 0;i < 0x7F;i++){ + outb(0x3D4,i); + printf("CR 0x%2.2X\t0x%2.2X\n",i,inb(0x3D5)&0xFF); + } + outb(0x3D4,storeReg); + printf("\nport 0x3D0 (Flat Panel)\n"); + storeReg = inb(0x3D0); + for(i = 0;i < 0x7F;i++){ + outb(0x3D0,i); + printf("FR 0x%2.2X\t0x%2.2X\n",i,inb(0x3D1)&0xFF); + } + outb(0x3D1,storeReg); + printf("\nport 0x3D2 (Multimedia)\n"); + storeReg = inb(0x3D2); + for(i = 0;i < 0x7F;i++){ + outb(0x3D2,i); + printf("MR 0x%2.2X\t0x%2.2X\n",i,inb(0x3D3)&0xFF); + } + outb(0x3D3,storeReg); + } else { + for(i = 0;i < 0x40;i++){ + outb(0x3D4,i); + printf("CR 0x%2.2X\t0x%2.2X\n",i,inb(0x3D5)&0xFF); + } + outb(0x3D4,storeReg); + } + + + printf("port 0x3CE (GC)\n"); + storeReg = inb(0x3CE); + for(i = 0;i < 0x10;i++){ + outb(0x3CE,i); + printf("GC 0x%2.2X\t0x%2.2X\n",i,inb(0x3CF)&0xFF); + } + outb(0x3CE,storeReg); + printf("port 0x3C4 (Sequencer)\n"); + storeReg = inb(0x3C4); + for(i = 0;i < 0x10;i++){ + outb(0x3C4,i); + printf("SQ 0x%2.2X\t0x%X2.2\n",i,inb(0x3C5)&0xFF); + } + outb(0x3C4,storeReg); + + + printf("port 0x3C0 (Attribute)\n"); + inb(0x3DA); + storeReg = inb(0x3C0); + for(i = 0;i < 0xFF;i++){ + inb(0x3DA); + outb(0x3C0,i); + printf("AT 0x%2.2X\t0x%2.2X\n",i,inb(0x3C1)&0xFF); + } + inb(0x3DA); + outb(0x3C0,storeReg); + + printf("0x3CC\t0x%X\n",inb(0x3CC)&0xFF); + printf("0x3C2\t0x%X\n",inb(0x3C2)&0xFF); + printf("0x3C3\t0x%X\n",inb(0x3C2)&0xFF); + printf("0x3CA\t0x%X\n",inb(0x3CA)&0xFF); + printf("0x3DA\t0x%X\n",inb(0x3DA)&0xFF); + + printf("\nRAMDAC\nport\tvalue\n"); + for(port = 0x83C6; port < 0x83CA;port++){ + printf("0x%4X\t0x%4X\n",port,inw(port)); + } + + if (isHiQV!=1) { + printf("\nBitBLT\nport\tvalue\n"); + for(port = 0x83D0; port <= 0x9FD0;port+=0x400){ + printf("0x%4.4X\t0x%4X\n",port,inw(port)); + } + + printf("\nH/W cursor\nport\tvalue\n"); + for(port = 0xA3D0; port <= 0xB3D0;port+=0x400){ + printf("0x%4.4X\t0x%4X\n",port,inw(port)); + } + + + outb(0x3D6, 0x70); + outw(0x3D6, (inw(0x3D6) | 0x8070)); + + printf("0x46E8\t0x%8X\n",inl(0x46E8)); + printf("0x4AE8\t0x%8X\n",inl(0x4AE8)); + printf("0x102\t0x%8X\n",inl(0x102)); + printf("0x103\t0x%8X\n",inl(0x103)); + + } + + storeReg = inb(0x3D4); + { + outb(0x3D4,0); + HTotal = ((inb(0x3D5)&0xFF) + 5) << shift; + outb(0x3D4,1); + HDisplay = ((inb(0x3D5)&0xFF) + 1) << shift; + outb(0x3D4,4); + HSyncStart = ((inb(0x3D5)&0xFF) + 1) << shift; + outb(0x3D4,5); + HSyncEnd = inb(0x3D5)&0x1F; + outb(0x3D4,5); + HSyncEnd += HSyncStart >> shift; + HSyncEnd <<= shift; + + outb(0x3D4,6); + VTotal = inb(0x3D5)&0xFF; + outb(0x3D4,7); + VTotal |= (inb(0x3D5)&0x1) << 8; + VTotal |= (inb(0x3D5)&0x20) << 4; + VTotal += 2; + VDisplay = (inb(0x3D5)&0x2) << 7; + VDisplay |= (inb(0x3D5)&0x40) << 3; + VSyncStart = (inb(0x3D5)&0x4) << 6; + VSyncStart |= (inb(0x3D5)&0x80) << 2; + outb(0x3D4,0x12); + VDisplay |= inb(0x3D5)&0xFF; + VDisplay += 1; + outb(0x3D4,0x10); + VSyncStart |= inb(0x3D5)&0xFF; + + outb(0x3D4,0x11); + VSyncEnd = inb(0x3D5)&0xF; + VSyncEnd += VSyncStart; + + } + outb(0x3D4,storeReg); + + printf("\nModeLine with port 0x3D4 (CRTC) %d %d %d %d %d %d %d %d\n", + HDisplay, HSyncStart, HSyncEnd, HTotal, + VDisplay, VSyncStart, VSyncEnd, VTotal); + + + if (is69030==1) { + if (again==1) { + again=0; + printf("\n\nPipeline B:\n"); + outb(0x3CD,((IOSS&0xE0)| 0x1F)); /* Select Channel 1 */ + outb(0x3CB,((MSS&0xF0)| 0xF)); + goto again; + } else { + outb(0x3CD,IOSS); + outb(0x3CB,MSS); + printf("\n\n0x3CB\t0x%X (MSS)\n",inb(0x3CB)&0xFF); + printf("0x3CD\t0x%X (IOSS)\n",inb(0x3CD)&0xFF); + } + } + RESET_IOPL(); + return 0; +} diff --git a/util/mRegs.c b/util/mRegs.c new file mode 100644 index 0000000..4d8da11 --- /dev/null +++ b/util/mRegs.c @@ -0,0 +1,186 @@ +/* $XConsortium: mRegs.c /main/2 1996/10/27 11:49:43 kaleb $ */ + + + + + +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/chips/util/mRegs.c,v 1.6 2001/11/16 21:13:34 tsi Exp $ */ + +#ifdef __NetBSD__ +# include <sys/types.h> +# include <machine/pio.h> +# include <machine/sysarch.h> +#else +# if defined(SVR4) && defined(i386) +# include <sys/types.h> +# ifdef NCR + /* broken NCR <sys/sysi86.h> */ +# define __STDC +# include <sys/sysi86.h> +# undef __STDC +# else +# include <sys/sysi86.h> +# endif +# ifdef SVR4 +# if !defined(sun) +# include <sys/seg.h> +# endif +# endif +# include <sys/v86.h> +# if defined(sun) +# include <sys/psw.h> +# endif +# endif +# include "AsmMacros.h" +#endif /* NetBSD */ + +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> + +#ifdef __NetBSD__ +# define SET_IOPL() i386_iopl(3) +# define RESET_IOPL() i386_iopl(0) +#else +# if defined(SVR4) && defined(i386) +# ifndef SI86IOPL +# define SET_IOPL() sysi86(SI86V86,V86SC_IOPL,PS_IOPL) +# define RESET_IOPL() sysi86(SI86V86,V86SC_IOPL,0) +# else +# define SET_IOPL() sysi86(SI86IOPL,3) +# define RESET_IOPL() sysi86(SI86IOPL,0) +# endif +# else +# ifdef linux +# define SET_IOPL() iopl(3) +# define RESET_IOPL() iopl(0) +# else +# define SET_IOPL() (void)0 +# define RESET_IOPL() (void)0 +# endif +# endif +#endif + +int hex2int(char* str); + +int main(int argc, char** argv) +{ + int i, value, index = 0; + char c, cport; + char* str; + unsigned int port, port1 = 0; + int query = 0; + + if(argc < 2) { + printf("usage: %s [Cvvxx [Cvvxx]] [Dxx]\n",argv[0]); + printf(" where C = A|a write vv to ARxx\n"); + printf(" = C|c write vv to CRxx\n"); + printf(" = F|f write vv to FRxx (6555x only)\n"); + printf(" = G|g write vv to GRxx\n"); + printf(" = M|m write vv to MRxx (6555x only)\n"); + printf(" = S|s write vv to SRxx\n"); + printf(" = X|x write vv to XRxx\n"); + printf(" where D = Y|y write xx to FCR\n"); + printf(" = Z|z write vv to MSR\n"); + printf(" xx is in hexadecimal\n"); + printf(" vv is in hexadecimal or '?' for query\n"); + } + + SET_IOPL(); + + for(i = 1; i < argc; i++){ + value = 0; + str = argv[i]; + c = *str++; + switch (c) { + case 'f': + case 'F': + cport = 'F'; + port = 0x3D0; + break; + case 'c': + case 'C': + cport = 'C'; + port = 0x3D4; + break; + case 'x': + case 'X': + cport = 'X'; + port = 0x3D6; + break; + case 'g': + case 'G': + cport = 'G'; + port = 0x3CE; + break; + case 'a': + case 'A': + cport = 'A'; + port = 0x3C0; + break; + case 's': + case 'S': + cport = 'S'; + port = 0x3C4; + break; + case 'm': + case 'M': + cport = 'M'; + port = 0x3D2; + break; + case 'y': + case 'Y': + cport = 'Y'; + port = 0x3DA; + port1 = 0x3CA; + break; + case 'z': + case 'Z': + cport = 'Z'; + port = 0x3C2; + port1 = 0x3CC; + break; + default: + continue; + break; + } + if ((cport != 'Z') && (cport != 'Y')) index = inb(port); + while ((c = *str++)) { + if (c == '?') { + query = 1; + } + if(c >= '0' && c <= '9') + value = (value << 4) | (c - '0'); /*ASCII assumed*/ + else if(c >= 'A' && c < 'G') + value = (value << 4) | (c - 'A'+10); /*ASCII assumed*/ + else if(c >= 'a' && c < 'g') + value = (value << 4) | (c - 'a'+10); /*ASCII assumed*/ + } + if ((cport != 'Z') && (cport != 'Y')) outb(port,value&0xFF); + if (query) { + if ((cport != 'Z') && (cport != 'Y')) + printf("%cR%X: 0x%X\n", cport, value & 0xFF, + inb(port+1)&0xFF); + else + if (cport == 'Z') + printf("MSR: 0x%X\n", inb(port1)&0xFF); + else + printf("FCR: 0x%X\n", inb(port1)&0xFF); + } else { + if ((cport != 'Z') && (cport != 'Y')) { + printf("%cR%X: 0x%X -> 0x%X\n", cport, value & 0xFF, + inb(port+1)&0xFF, (value&0xFF00)>>8); + outw(port, value); + outb(port, index &0xFF); + } else { + if (cport == 'Z') + printf("MSR: 0x%X -> 0x%X\n", inb(port1)&0xFF, value&0xFF); + else + printf("FCR: 0x%X -> 0x%X\n", inb(port1)&0xFF, value&0xFF); + outb(port, value & 0xFF); + } + } + } + RESET_IOPL(); + return 0; +} diff --git a/util/modClock.c b/util/modClock.c new file mode 100644 index 0000000..cce4f84 --- /dev/null +++ b/util/modClock.c @@ -0,0 +1,412 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/chips/util/modClock.c,v 1.6 2001/11/16 21:13:34 tsi Exp $ */ + +#ifdef __NetBSD__ +# include <sys/types.h> +# include <machine/pio.h> +# include <machine/sysarch.h> +#else +# if defined(SVR4) && defined(i386) +# include <sys/types.h> +# ifdef NCR + /* broken NCR <sys/sysi86.h> */ +# define __STDC +# include <sys/sysi86.h> +# undef __STDC +# else +# include <sys/sysi86.h> +# endif +# ifdef SVR4 +# if !defined(sun) +# include <sys/seg.h> +# endif +# endif +# include <sys/v86.h> +# if defined(sun) +# include <sys/psw.h> +# endif +# endif +# include "AsmMacros.h" +#endif /* NetBSD */ + +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#ifndef Lynx +#include <fnmatch.h> +#endif + +#ifdef __NetBSD__ +# define SET_IOPL() i386_iopl(3) +# define RESET_IOPL() i386_iopl(0) +#else +# if defined(SVR4) && defined(i386) +# ifndef SI86IOPL +# define SET_IOPL() sysi86(SI86V86,V86SC_IOPL,PS_IOPL) +# define RESET_IOPL() sysi86(SI86V86,V86SC_IOPL,0) +# else +# define SET_IOPL() sysi86(SI86IOPL,3) +# define RESET_IOPL() sysi86(SI86IOPL,0) +# endif +# else +# ifdef linux +# define SET_IOPL() iopl(3) +# define RESET_IOPL() iopl(0) +# else +# define SET_IOPL() (void)0 +# define RESET_IOPL() (void)0 +# endif +# endif +#endif + +#define tolerance 0.01 /* +/- 1% */ + + +#define CT65520 0x1 +#define CT65525 0x2 +#define CT65530 0x3 +#define CT64200 0x4 + +#define CT65535 0x11 +#define CT65540 0x12 +#define CT65545 0x13 +#define CT65546 0x14 +#define CT65548 0x15 +#define CT64300 0x16 + +#define CT65550 0x31 +#define CT65554 0x32 +#define CT65555 0x33 +#define CT68554 0x34 +#define CT69000 0x35 +#define CT69030 0x36 + +#define IS_Programmable(X) X&0x10 +#define IS_HiQV(X) X&0x20 + +#define DotClk 0 +#define MemClk 1 +#define IS_MemClk(X) X&0x1 + +int compute_clock ( + unsigned int ChipType, + double target, + double Fref, + unsigned int ClkMaxN, + unsigned int ClkMaxM, + unsigned int *bestM, + unsigned int *bestN, + unsigned int *bestP, + unsigned int *bestPSN) { + + unsigned int M, N, P, PSN, PSNx; + + double bestError = 0, abest = 42, bestFout = 0; + + double Fvco, Fout; + double error, aerror; + + unsigned int M_min = 3; + unsigned int M_max = ClkMaxM; + + if (target < 1e6){ + fprintf (stderr, "MHz assumed, changed to %g MHz\n", target); + target *= 1e6; + } + + if (target > 220.0e6) { + fprintf (stderr, "too large\n"); + return 1; + } + + /* Other parameters available onthe 65548 but not the 65545, and + not documented in the Clock Synthesizer doc in rev 1.0 of the + 65548 datasheet: + + + XR30[4] = 0, VCO divider loop uses divide by 4 (same as 65545) + 1, VCO divider loop uses divide by 16 + + + XR30[5] = 1, reference clock is divided by 5 + + I haven't put in any support for those here. For simplicity, + they should be set to 0 on the 65548, and left untouched on + earlier chips. */ + + for (PSNx = ((ChipType == CT69000) || (ChipType == CT69030)) ? 1 : 0; + PSNx <= 1; PSNx++) { + unsigned int low_N, high_N; + double Fref4PSN; + + PSN = PSNx ? 1 : 4; + + low_N = 3; + high_N = ClkMaxN; + + while (Fref / (PSN * low_N) > (((ChipType == CT69000) || + (ChipType == CT69030)) ? 5.0e6 : 2.0e6)) + low_N++; + while (Fref / (PSN * high_N) < 150.0e3) + high_N--; + + Fref4PSN = Fref * 4 / PSN; + for (N = low_N; N <= high_N; N++) { + double tmp = Fref4PSN / N; + + for (P = (IS_HiQV(ChipType) && (ChipType != CT69000) && + (ChipType != CT69030)) ? 1 : 0; P <= 5; P++) { + double Fvco_desired = target * (1 << P); + double M_desired = Fvco_desired / tmp; + /* Which way will M_desired be rounded? Do all three just to + be safe. */ + unsigned int M_low = M_desired - 1; + unsigned int M_hi = M_desired + 1; + + if (M_hi < M_min || M_low > M_max) + continue; + + if (M_low < M_min) + M_low = M_min; + if (M_hi > M_max) + M_hi = M_max; + + for (M = M_low; M <= M_hi; M++) { + Fvco = tmp * M; + if (Fvco <= ((ChipType == CT69000) || (ChipType == CT69030) ? + 100e6 : 48.0e6)) + continue; + if (Fvco > 220.0e6) + break; + + Fout = Fvco / (1 << P); + + error = (target - Fout) / target; + + aerror = (error < 0) ? -error : error; + if (aerror < abest) { + abest = aerror; + bestError = error; + *bestM = M; + *bestN = N; + *bestP = P; + *bestPSN = PSN; + bestFout = Fout; + } + } + } + } + } + + if (abest < tolerance) { + printf ("best: M=%d N=%d P=%d PSN=%d\n", *bestM, *bestN, *bestP, *bestPSN); + + if (bestFout > 1.0e6) + printf ("Fout = %g MHz", bestFout / 1.0e6); + else if (bestFout > 1.0e3) + printf ("Fout = %g kHz", bestFout / 1.0e3); + else + printf ("Fout = %g Hz", bestFout); + printf (", error = %g\n", bestError); + return 0; + } + printf ("can't do it with less than %g error\n", bestError); + return 1; +} + +int set_clock( + unsigned int ChipType, + unsigned int ClockType, + unsigned int ProgClock, + unsigned int M, + unsigned int N, + unsigned int P, + unsigned int PSN) { + + unsigned int tmp, idx; + + SET_IOPL(); + + idx = inb(0x3D6); + if (IS_HiQV(ChipType)) { + if (IS_MemClk(ClockType)) { + printf ("XRCC = 0x%02X\n", M - 2); + printf ("XRCD = 0x%02X\n", N - 2); + printf ("XRCE = 0x%02X\n", (0x80 | (P * 16 + (PSN == 1)))); + + outb(0x3D6, 0xCE); /* Select Fix MClk before */ + tmp = inb(0x3D7); + outb(0x3D7, tmp & 0x7F); + outb(0x3D6, 0xCC); + outb(0x3D7, (M - 2)); + outb(0x3D6, 0xCD); + outb(0x3D7, (N - 2)); + outb(0x3D6, 0xCE); + outb(0x3D7, (0x80 | (P * 16 + (PSN == 1)))); + } else { + printf ("XR%X = 0x%02X\n", 0xC0 + 4 * ProgClock, M - 2); + printf ("XR%X = 0x%02X\n", 0xC1 + 4 * ProgClock, N - 2); + printf ("XR%X = 0x%02X\n", 0xC2 + 4 * ProgClock, 0); + printf ("XR%X = 0x%02X\n", 0xC3 + 4 * ProgClock, P * 16 + (PSN == 1)); + + outb(0x3D6, 0xC0 + 4 * ProgClock); + outb(0x3D7, (M - 2)); + outb(0x3D6, 0xC1 + 4 * ProgClock); + outb(0x3D7, (N - 2)); + outb(0x3D6, 0xC2 + 4 * ProgClock); + outb(0x3D7, 0x0); + outb(0x3D6, 0xC3 + 4 * ProgClock); + outb(0x3D7, (P * 16 + (PSN == 1))); + } + } else { + printf ("XR30 = 0x%02X\n", P * 2 + (PSN == 1)); + printf ("XR31 = 0x%02X\n", M - 2); + printf ("XR32 = 0x%02X\n", N - 2); + outb(0x3D6, 0x33); + tmp = inb(0x3D7); + if (IS_MemClk(ClockType)) { + outb(0x3D7, tmp | 0x20); + } else { + outb(0x3D7, tmp & ~0x20); + } + outb(0x3D6, 0x30); + outb(0x3D7, (P * 2 + (PSN == 1))); + outb(0x3D6, 0x31); + outb(0x3D7, (M - 2)); + outb(0x3D6, 0x32); + outb(0x3D7, (N - 2)); + outb(0x3D6, 0x33); + outb(0x3D7, tmp); + } + outb(0x3D6, idx); + RESET_IOPL(); + return 0; +} + +unsigned int probe_chip(void) { + + unsigned int ChipType, temp; + + SET_IOPL(); + + outb(0x3D6, 0x00); + temp = inb(0x3D7); + ChipType = 0; + if (temp != 0xA5) { + if ((temp & 0xF0) == 0x70) { + ChipType = CT65520; + } + if ((temp & 0xF0) == 0x80) { /* could also be a 65525 */ + ChipType = CT65530; + } + if ((temp & 0xF0) == 0xA0) { + ChipType = CT64200; + } + if ((temp & 0xF0) == 0xB0) { + ChipType = CT64300; + } + if ((temp & 0xF0) == 0xC0) { + ChipType = CT65535; + } + if ((temp & 0xF8) == 0xD0) { + ChipType = CT65540; + } + if ((temp & 0xF8) == 0xD8) { + switch (temp & 0x07) { + case 3: + ChipType = CT65546; + break; + case 4: + ChipType = CT65548; + break; + default: + ChipType = CT65545; + } + } + } + /* At this point the chip could still be a HiQV, so check for + * that. This test needs some looking at */ + if ((temp != 0) && (ChipType == 0)) { + outb(0x3D6, 0x02); + temp = inb(0x03D7); + if (temp == 0xE0) { + ChipType = CT65550; + } + if (temp == 0xE4) { + ChipType = CT65554; + } + if (temp == 0xE5) { + ChipType = CT65555; + } + if (temp == 0xF4) { + ChipType = CT68554; + } + if (temp == 0xC0) { + ChipType = CT69000; + } + if (temp == 0x30) { + outb(0x3D6, 0x03); + temp = inb(0x03D7); + if (temp == 0x0C) ChipType = CT69030; + } + } + + RESET_IOPL(); + + if (ChipType == 0) { /* failure */ + fprintf(stderr, "Not a Chips and Technologies Chipset\n"); + } + + return ChipType; +} + + +int main (int argc, char *argv[]) { + double target; + double Fref = 14318180; + unsigned int M, N, P, PSN, ChipType, ClockType, progclock; + + switch (argc) { + case 2: + progclock = 2; + target = atof (argv[1]); + break; + case 3: + progclock = abs(atof (argv[1])); + target = atof (argv[2]); + break; + default: + fprintf (stderr, "usage: %s [-0|-1|-2] freq\n", argv[0]); + return 1; + } + + ClockType = DotClk; +#ifndef Lynx + if (! fnmatch("*memClock",argv[0],FNM_PATHNAME)) { +#else + if (strstr("memClock",argv[0]) != NULL) { +#endif + ClockType = MemClk; + } + + ChipType = probe_chip(); + if (!ChipType) { + return 1; + } + + if (! IS_Programmable(ChipType)) { + fprintf(stderr, "No programmable Clock!\n"); + return 1; + } + + if (IS_HiQV(ChipType)) { + if (! compute_clock(ChipType, target, Fref, 63, 127, &M, &N, &P, &PSN)) { + return set_clock(ChipType, ClockType, progclock, M, N, P, PSN); + } else { + return 1; + } + } else { + if (! compute_clock(ChipType, target, Fref, 127, 127, &M, &N, &P, &PSN)) { + return set_clock(ChipType, ClockType, progclock, M, N, P, PSN); + } else { + return 1; + } + } +} |