From 9b82d329788f1efe3eae46fc81e7e6249ec2c485 Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Mon, 21 Jul 2025 16:20:01 +0200 Subject: [PATCH] xfree86: drivers: chips: copy over xf86-video-chips tree Since this driver doesn't receive much functional changes, except fixups for server ABI changes, it's a good candidate to move it back into the main Xserver tree. As the first step to move back this driver into the Xserver tree, copy over the source from last release tag. Skipped files we don't need here (eg. gitlab pipeline, automake files, ...) repo: git@github.com:X11Libre/xf86-video-chips.git git tag: xlibre-xf86-video-chips-1.5.0.1 Signed-off-by: Enrico Weigelt, metux IT consult --- hw/xfree86/drivers/video/chips/COPYING | 153 + hw/xfree86/drivers/video/chips/README | 1180 +++ hw/xfree86/drivers/video/chips/man/chips.man | 250 + .../drivers/video/chips/src/compat-api.h | 104 + .../drivers/video/chips/src/ct_BlitMM.h | 138 + .../drivers/video/chips/src/ct_Blitter.h | 166 + .../drivers/video/chips/src/ct_BltHiQV.h | 185 + hw/xfree86/drivers/video/chips/src/ct_accel.c | 80 + hw/xfree86/drivers/video/chips/src/ct_bank.c | 629 ++ .../drivers/video/chips/src/ct_cursor.c | 475 ++ hw/xfree86/drivers/video/chips/src/ct_ddc.c | 287 + hw/xfree86/drivers/video/chips/src/ct_dga.c | 235 + .../drivers/video/chips/src/ct_driver.c | 7315 +++++++++++++++++ .../drivers/video/chips/src/ct_driver.h | 565 ++ hw/xfree86/drivers/video/chips/src/ct_exa.c | 329 + .../drivers/video/chips/src/ct_pcirename.h | 122 + hw/xfree86/drivers/video/chips/src/ct_regs.c | 523 ++ .../drivers/video/chips/src/ct_shadow.c | 243 + hw/xfree86/drivers/video/chips/src/ct_video.c | 1033 +++ .../drivers/video/chips/util/AsmMacros.h | 338 + hw/xfree86/drivers/video/chips/util/dRegs.c | 248 + hw/xfree86/drivers/video/chips/util/iopl.h | 46 + hw/xfree86/drivers/video/chips/util/mRegs.c | 129 + .../drivers/video/chips/util/modClock.c | 356 + 24 files changed, 15129 insertions(+) create mode 100644 hw/xfree86/drivers/video/chips/COPYING create mode 100644 hw/xfree86/drivers/video/chips/README create mode 100644 hw/xfree86/drivers/video/chips/man/chips.man create mode 100644 hw/xfree86/drivers/video/chips/src/compat-api.h create mode 100644 hw/xfree86/drivers/video/chips/src/ct_BlitMM.h create mode 100644 hw/xfree86/drivers/video/chips/src/ct_Blitter.h create mode 100644 hw/xfree86/drivers/video/chips/src/ct_BltHiQV.h create mode 100644 hw/xfree86/drivers/video/chips/src/ct_accel.c create mode 100644 hw/xfree86/drivers/video/chips/src/ct_bank.c create mode 100644 hw/xfree86/drivers/video/chips/src/ct_cursor.c create mode 100644 hw/xfree86/drivers/video/chips/src/ct_ddc.c create mode 100644 hw/xfree86/drivers/video/chips/src/ct_dga.c create mode 100644 hw/xfree86/drivers/video/chips/src/ct_driver.c create mode 100644 hw/xfree86/drivers/video/chips/src/ct_driver.h create mode 100644 hw/xfree86/drivers/video/chips/src/ct_exa.c create mode 100644 hw/xfree86/drivers/video/chips/src/ct_pcirename.h create mode 100644 hw/xfree86/drivers/video/chips/src/ct_regs.c create mode 100644 hw/xfree86/drivers/video/chips/src/ct_shadow.c create mode 100644 hw/xfree86/drivers/video/chips/src/ct_video.c create mode 100644 hw/xfree86/drivers/video/chips/util/AsmMacros.h create mode 100644 hw/xfree86/drivers/video/chips/util/dRegs.c create mode 100644 hw/xfree86/drivers/video/chips/util/iopl.h create mode 100644 hw/xfree86/drivers/video/chips/util/mRegs.c create mode 100644 hw/xfree86/drivers/video/chips/util/modClock.c diff --git a/hw/xfree86/drivers/video/chips/COPYING b/hw/xfree86/drivers/video/chips/COPYING new file mode 100644 index 0000000000..40dbdbaebb --- /dev/null +++ b/hw/xfree86/drivers/video/chips/COPYING @@ -0,0 +1,153 @@ +Copyright 1996, 1997, 1998 by David Bateman + 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. + +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. + +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. + +Copyright 1993 by Jon Block +Modified by Mike Hollick +Modified 1994 by Régis Cridlig + +Major Contributors to XFree86 3.2 + Modified 1995/6 by Nozomi Ytow + Modified 1996 by Egbert Eich + Modified 1996 by David Bateman + Modified 1996 by Xavier Ducoin + +Contributors to XFree86 3.2 + Modified 1995/6 by Ken Raeburn + Modified 1996 by Shigehiro Nomura + Modified 1996 by Marc de Courville + Modified 1996 by Adam Sulmicki + Modified 1996 by Jens Maurer + +Large parts rewritten for XFree86 4.0 + Modified 1998 by David Bateman + Modified 1998 by Egbert Eich + 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 2007 George Sapountzis + +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 (including the next +paragraph) 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 +THE AUTHORS OR COPYRIGHT HOLDERS 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. + +(c) Copyright 1993,1994 by David Wexelblat + +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. + diff --git a/hw/xfree86/drivers/video/chips/README b/hw/xfree86/drivers/video/chips/README new file mode 100644 index 0000000000..f95e35f492 --- /dev/null +++ b/hw/xfree86/drivers/video/chips/README @@ -0,0 +1,1180 @@ + Information for Chips and Technologies Users + David Bateman ( ), Egbert + Eich ( ) + 1st January 2001 + ____________________________________________________________ + + Table of Contents + + + 1. Introduction + 2. Supported Chips + 2.1 Basic architecture + 2.2 WinGine architecture + 2.3 HiQV Architecture + + 3. xorg.conf Options + 4. Modelines + 5. Dual Display Channel + 6. The Full Story on Clock Limitations + 7. Troubleshooting + 8. Disclaimer + 9. Acknowledgement + 10. Authors + + + ______________________________________________________________________ + + 1. Introduction + + + The Chips and Technologies driver release in X11R7.5 came from XFree86 + 4.4 rc2; this document was originally included in that release and has + been updated modestly to reflect differences between X11R7.5 and + XFree86 4.4 rc2. + + With the release of XFree86 version 4.0, the Chips and Technologies + driver has been extensively rewritten and contains many new features. + This driver must be considered work in progress, and those users + wanting stability are encouraged to use the older XFree86 3.3.x + versions. However this version of the Chips and Technologies driver + has many new features and bug fixes that might make users prefer to + use this version. These features include + + + o The long standing black/blue screen problem that some people have + had should be fixed. + + o Hardware/Software cursor switching on the fly, that should fix many + of the known hardware cursor problems. + + o Gamma correction at all depths and DirectColor visuals for depths + of 15 or greater with the HiQV series of chipsets. + + o Supports PseudoColor overlays on 16bpp TrueColor screens for HiQV. + + o Supports YUV colour space conversion with the XVideo extension. + + o 32bpp pixmaps while using a framebuffer in 24bpp packed pixel mode. + + o Heaps more acceleration. + + o 1/4bpp support. + + o Multihead + + + o Much more... + + This document attempts to discuss the features of this driver, the + options useful in configuring it and the known problems. Most of the + Chips and Technologies chipsets are supported by this driver to some + degree. + + + 2. Supported Chips + + + The Chips and Technologies chipsets supported by this driver have one + of three basic architectures. A basic architecture, the WinGine + architecture which is a modification on this basic architecture and a + completely new HiQV architecture. + + + 2.1. Basic architecture + + + ct65520 + (Max Ram: 1Mb, Max Dclk: 68MHz@5V) + + ct65525 + This chip is basically identical to the 65530. It has the same + ID and is identified as a 65530 when probed. See ct65530 for + details. + + ct65530 + This is a very similar chip to the 65520. However it + additionally has the ability for mixed 5V and 3.3V operation and + linear addressing of the video memory. (Max Ram: 1Mb, Max Dclk: + 56MHz@3.3V, 68MHz@5V) + + ct65535 + This is the first chip of the ct655xx series to support fully + programmable clocks. Otherwise it has the the same properties as + the 65530. + + ct65540 + This is the first version of the of the ct655xx that was capable + of supporting Hi-Color and True-Color. It also includes a fully + programmable dot clock and supports all types of flat panels. + (Max Ram: 1Mb, Max Dclk: 56MHz@3.3V, 68MHz@5V) + + ct65545 + The chip is very similar to the 65540, with the addition of H/W + cursor, pop-menu acceleration, BitBLT and support of PCI Buses. + PCI version also allow all the BitBLT and H/W cursor registers + to be memory mapped 2Mb above the Base Address. (Max Ram: 1Mb, + Max Dclk: 56MHz@3.3V,68MHz@5V) + + ct65546 + This chip is specially manufactured for Toshiba, and so + documentation is not widely available. It is believed that this + is really just a 65545 with a higher maximum dot-clock of 80MHz. + (Max Ram: 1Mb?, Max Dclk: 80MHz?) + + ct65548 + This chip is similar to the 65545, but it also includes XRAM + support and supports the higher dot clocks of the 65546. (Max + Ram: 1Mb, Max Dclk: 80MHz) + + + + 2.2. WinGine architecture + + + ct64200 + This chip, also known as the WinGine, is used in video cards for + desktop systems. It often uses external DAC's and programmable + clock chips to supply additional functionally. None of these are + currently supported within the driver itself, so many cards will + only have limited support. Linear addressing is not supported + for this card in the driver. (Max Ram: 2Mb, Max Dclk: 80MHz) + + ct64300 + This is a more advanced version of the WinGine chip, with + specification very similar to the 6554x series of chips. However + there are many differences at a register level. A similar level + of acceleration to the 65545 is included for this driver. (Max + Ram: 2Mb, Max Dclk: 80MHz) + + + 2.3. HiQV Architecture + + + ct65550 + This chip includes many new features, including improved BitBLT + support (24bpp colour expansion, wider maximum pitch, etc), + Multimedia unit (video capture, zoom video port, etc) and 24bpp + uncompressed true colour (i.e 32bpp mode). Also memory mapped + I/O is possible on all bus configurations. (Max Ram: 2Mb, Max + Dclk: 80MHz@3.3V,100MHz@5V) + + ct65554 + This chip is similar to the 65550 but has a 64bit memory bus as + opposed to a 32bit bus. It also has higher limits on the maximum + memory and pixel clocks (Max Ram: 4Mb, Max Dclk: 100MHz@3.3V) + + ct65555 + Similar to the 65554 but has yet higher maximum memory and pixel + clocks. It also includes a new DSTN dithering scheme that + improves the performance of DSTN screens. (Max Ram: 4Mb, Max + Dclk: 110MHz@3.3V) + + ct68554 + Similar to the 65555 but also incorporates "PanelLink" drivers. + This serial link allows an LCD screens to be located up to 100m + from the video processor. Expect to see this chip soon in LCD + desktop machines (Max Ram: 4Mb, Max Dclk: 110MHz@3.3V) + + ct69000 + Similar to the 65555 but incorporates 2Mbytes of SGRAM on chip. + It is the first Chips and Technologies chipset where all of the + registers are accessible through MMIO, rather than just the + BitBlt registers. (Max Ram: 2Mb Only, Max Dclk: 130MHz@3.3V) + + ct69030 + Similar to the 69000 but incorporates 4Mbytes of SGRAM on chip + and has faster memory and pixel clock limits. Also includes a + second display channel so that the CRT can display independently + of the LCD. (Max Ram: 4Mb Only, Max Dclk: 170MHz@3.3V) + + + + 3. xorg.conf Options + + + The following options are of particular interest to the Chips and + Technologies driver. It should be noted that the options are case + insensitive, and that white space and "_" characters are ignored. + There are therefore a wide variety of possible forms for all options. + The forms given below are the preferred forms. + + Options related to drivers can be present in the Screen, Device and + Monitor sections and the Display subsections. The order of precedence + is Display, Screen, Monitor, Device. + + + Option + This option will disable the use of any accelerated functions. + This is likely to help with some problems related to DRAM + timing, high dot clocks, and bugs in accelerated functions, at + the cost of performance (which will still be reasonable on + VLB/PCI). + + VideoRam 1024 (or another value) + This option will override the detected amount of video memory, + and pretend the given amount of memory is present on the card. + + Option + By default linear addressing is used on all chips where it can + be set up automatically. The exception is for depths of 1 or + 4bpp where linear addressing is turned off by default. It is + possible to turn the linear addressing off with this option. + Note that H/W acceleration is only supported with linear + addressing. + + Option + When the chipset is capable of linear addressing and it has been + turned off by default, this option can be used to turn it back + on. This is useful for the 65530 chipset where the base address + of the linear framebuffer must be supplied by the user, or at + depths 1 and 4bpp. Note that linear addressing at 1 and 4bpp is + not guaranteed to work correctly. + + MemBase 0x03b00000 (or a different address) + This sets the physical memory base address of the linear + framebuffer. Typically this is probed correctly, but if you + believe it to be mis-probed, this option might help. Also for + non PCI machines specifying this force the linear base address + to be this value, reprogramming the video processor to suit. + Note that for the 65530 this is required as the base address + can't be correctly probed. + + Option + For chipsets that support hardware cursors, this option enforces + their use, even for cases that are known to cause problems on + some machines. Note that it is overridden by the "SWcursor" + option. Hardware cursors effectively speeds all graphics + operations as the job of ensuring that the cursor remains on top + is now given to the hardware. It also reduces the effect of + cursor flashing during graphics operations. + + Option + This disables use of the hardware cursor provided by the chip. + Try this if the cursor seems to have problems. + + Option + The server is unable to differentiate between SS STN and TFT + displays. This forces it to identify the display as a SS STN + rather than a TFT. + + Option + The flat panel timings are related to the panel size and not the + size of the mode specified in xorg.conf. For this reason the + default behaviour of the server is to use the panel timings + already installed in the chip. The user can force the panel + timings to be recalculated from the modeline with this option. + However the panel size will still be probed. + + Option + For some machines the LCD panel size is incorrectly probed from + the registers. This option forces the LCD panel size to be + overridden by the modeline display sizes. This will prevent the + use of a mode that is a different size than the panel. Before + using this check that the server reports an incorrect panel + size. This option can be used in conjunction with the option + "UseModeline" to program all the panel timings using the + modeline values. + + Option + When the size of the mode used is less than the panel size, the + default behaviour of the server is to stretch the mode in an + attempt to fill the screen. A "letterbox" effect with no + stretching can be achieved using this option. + + Option + When the size of the mode used is less than the panel size, the + default behaviour of the server is to align the left hand edge + of the display with the left hand edge of the screen. Using this + option the mode can be centered in the screen. This option is + reported to have problems with some machines at 16/24/32bpp, the + effect of which is that the right-hand edge of the mode will be + pushed off the screen. + + Option + For the chips either using the WinGine or basic architectures, + the chips generates a number of fixed clocks internally. With + the chips 65535 and later or the 64300, the default is to use + the programmable clock for all clocks. It is possible to use the + fixed clocks supported by the chip instead by using this option. + Typically this will give you some or all of the clocks 25.175, + 28.322, 31.000 and 36.000MHz. The current programmable clock + will be given as the last clock in the list. On a cold-booted + system this might be the appropriate value to use at the text + console (see the "TextClockFreq" option), as many flat panels + will need a dot clock different than the default to synchronise. + The programmable clock makes this option obsolete and so it's + use isn't recommended. It is completely ignored for HiQV + chipsets. + + TextClockFreq 25.175 + Except for the HiQV chipsets, it is impossible for the server to + read the value of the currently used frequency for the text + console when using programmable clocks. Therefore the server + uses a default value of 25.175MHz as the text console clock. For + some LCDs, in particular DSTN screens, this clock will be wrong. + This allows the user to select a different clock for the server + to use when returning to the text console. + + Option + Option "FPClock16" "65.0MHz" Option "FPClock24" "65.0MHz" Option + "FPClock32" "65.0MHz"" In general the LCD panel clock should be + set independently of the modelines supplied. Normally the chips + BIOS set the flat panel clock correctly and so the default + behaviour with HiQV chipset is to leave the flat panel clock + alone, or force it to be 90% of the maximum allowable clock if + the current panel clock exceeds the dotclock limitation due to a + depth change. This option allows the user to force the server + the reprogram the flat panel clock independently of the modeline + with HiQV chipset. The four options are for 8bpp or less, 16, 24 + or 32bpp LCD panel clocks, where the options above set the + clocks to 65MHz. + + Option + Option "FPClkIndx" "1"" The HiQV series of chips have three + programmable clocks. The first two are usually loaded with + 25.175 and 28.322MHz for VGA backward compatibility, and the + third is used as a fully programmable clock. On at least one + system (the Inside 686 LCD/S single board computer) the third + clock is unusable. These options can be used to force a + particular clock index to be used + + Option + This has a different effect depending on the hardware on which + it is used. For the 6554x machines MMIO is only used to talk to + the BitBLT engine and is only usable with PCI buses. It is + enabled by default for 65545 machines since the blitter can not + be used otherwise. The HiQV series of chipsets must use MMIO + with their BitBLT engines, and so this is enabled by default. + + Option + The 690xx chipsets can use MMIO for all communications with the + video processor. So using this option on a 690xx chipset forces + them to use MMIO for all communications. This only makes sense + when the 690xx is on a PCI bus so that normal PIO can be + disabled. + + Option + This option sets the centering and stretching to the BIOS + default values. This can fix suspend/resume problems on some + machines. It overrides the options "LcdCenter" and "NoStretch". + + Option For 24bpp on TFT screens, the server assumes that + a 24bit bus is being used. This can result in a + reddish tint to 24bpp mode. This option, selects + an 18 bit TFT bus. For other depths this option + has no effect. + + Chipset It is possible that the chip could be + misidentified, particular due to interactions + with other drivers in the server. It is possible + to force the server to identify a particular chip + with this option. + + Option Composite sync on green. Possibly useful if you + wish to use an old workstation monitor. The HiQV + internal RAMDAC's supports this mode of + operation, but whether a particular machine does + depends on the manufacturer. + + DacSpeed 80.000 The server will limit the maximum dotclock to a + value as specified by the manufacturer. This + might make certain modes impossible to obtain + with a reasonable refresh rate. Using this option + the user can override the maximum dot-clock and + specify any value they prefer. Use caution with + this option, as driving the video processor + beyond its specifications might cause damage. + + Option Option "SetMClk" "38000kHz"" This option sets the + internal memory clock (MCLK) registers of HiQV + chipsets to 38MHz or some other value. Use + caution as excess heat generated by the video + processor if its specifications are exceeded + might cause damage. However careful use of this + option might boost performance. This option might + also be used to reduce the speed of the memory + clock to preserve power in modes that don't need + the full speed of the memory to work correctly. + This option might also be needed to reduce the + speed of the memory clock with the "Overlay" + option. + + Option By default it is assumed that there are 6 + significant bits in the RGB representation of the + colours in 4bpp and above. If the colours seem + darker than they should be, perhaps your ramdac + is has 8 significant bits. This option forces the + server to assume that there are 8 significant + bits. + + Option This is a debugging option and general users have + no need of it. Using this option, when the + virtual desktop is scrolled away from the zero + position, the pixmap cache becomes visible. This + is useful to see that pixmaps, tiles, etc have + been properly cached. + + Option This option is only useful when acceleration + can't be used and linear addressing can be used. + With this option all of the graphics are rendered + into a copy of the framebuffer that is keep in + the main memory of the computer, and the screen + is updated from this copy. In this way the + expensive operation of reading back to contents + of the screen is never performed and the + performance is improved. Because the rendering is + all done into a virtual framebuffer acceleration + can not be used. + + Option The new TMED DSTN dithering scheme available on + recent HiQV chipsets gives improved performance. + However, some machines appear to have this + feature incorrectly setup. If you have snow on + your DSTN LCD, try using this option. This option + is only relevant for chipsets more recent than + the ct65555 and only when used with a DSTN LCD. + + Option The HiQV chipsets contain a multimedia engine + that allow a 16bpp window to be overlaid on the + screen. This driver uses this capability to + include a 16bpp framebuffer on top of an 8bpp + framebuffer. In this way PseudoColor and + TrueColor visuals can be used on the same screen. + XFree86 believes that the 8bpp framebuffer is + overlaid on the 16bpp framebuffer. Therefore to + use this option the server must be started in + either 15 or 16bpp depth. Also the maximum size + of the desktop with this option is 1024x1024, as + this is the largest window that the HiQV + multimedia engine can display. Note that this + option using the multimedia engine to its limit, + and some manufacturers have set a default memory + clock that will cause pixel errors with this + option. If you get pixel error with this option + try using the "SetMClk" option to slow the memory + clock. It should also be noted that the XVideo + extension uses the same capabilities of the HiQV + chipsets as the Overlays. So using this option + disables the XVideo extension. + + + Option Normally the colour transparency key for the + overlay is the 8bpp lookup table entry 255. This + might cause troubles with some applications, and + so this option allows the colour transparency key + to be set to some other value. Legal values are 2 + to 255 inclusive. + + Option This sets the default pixel value for the YUV + video overlay key. Legal values for this key are + depth dependent. That is from 0 to 255 for 8bit + depth, 0 to 32,767 for 15bit depth, etc. This + option might be used if the default video overlay + key causes problems. + + Option The 69030 chipset has independent display + channels, that can be configured to support + independent refresh rates on the flat panel and + on the CRT. The default behaviour is to have both + the flat panel and the CRT use the same display + channel and thus the same refresh rate. This + option forces the two display channels to be + used, giving independent refresh rates. + + Option The ct69030 supports dual-head display. By + default the two display share equally the + available memory. This option forces the second + display to take a particular amount of memory. + Please read the section below about dual-head + display. + + Option Option "XaaNoSolidFillRect", Option "XaaNoSolid- + HorVertLine", Option "XaaNoMono8x8PatternFill- + Rect", Option "XaaNoColor8x8PatternFillRect", + Option "XaaNoCPUToScreenColorExpandFill", Option + "XaaNoScreenToScreenColorExpandFill", Option + "XaaNoImageWriteRect", Option "XaaNoImageRead- + Rect", Option "XaaNoPixmapCache", Option + "XaaNoOffscreenPixmaps" " These option + individually disable the features of the XAA + acceleration code that the Chips and Technologies + driver uses. If you have a problem with the + acceleration and these options will allow you to + isolation the problem. This information will be + invaluable in debugging any problems. + + + 4. Modelines + + + When constructing a modeline for use with the Chips and Technologies + driver you'll needed to considered several points + + + * Virtual Screen Size + It is the virtual screen size that determines the amount of + memory used by a mode. So if you have a virtual screen size set + to 1024x768 using a 800x600 at 8bpp, you use 768kB for the mode. + Further to this some of the XAA acceleration requires that the + display pitch is a multiple of 64 pixels. So the driver will + attempt to round-up the virtual X dimension to a multiple of 64, + but leave the virtual resolution untouched. This might further + reduce the available memory. + + * 16/24/32 Bits Per Pixel + Hi-Color and True-Color modes are implemented in the server. The + clocks in the 6554x series of chips are internally divided by 2 + for 16bpp and 3 for 24bpp, allowing one modeline to be used at + all depths. The effect of this is that the maximum dot clock + visible to the user is a half or a third of the value at 8bpp. + The HiQV series of chips doesn't need to use additional clock + cycles to display higher depths, and so the same modeline can be + used at all depths, without needing to divide the clocks. Also + 16/24/32 bpp modes will need 2 , 3 or 4 times respectively more + video ram. + + * Frame Acceleration + Many DSTN screens use frame acceleration to improve the + performance of the screen. This can be done by using an external + frame buffer, or incorporating the framebuffer at the top of + video ram depending on the particular implementation. The + Xserver assumes that the framebuffer, if used, will be at the + top of video ram. The amount of ram required for the + framebuffer will vary depending on the size of the screen, and + will reduce the amount of video ram available to the modes. + Typical values for the size of the framebuffer will be 61440 + bytes (640x480 panel), 96000 bytes (800x600 panel) and 157287 + bytes (1024x768 panel). + + * H/W Acceleration + The H/W cursor will need 1kB for the 6554x and 4kb for the + 65550. On the 64300 chips the H/W cursor is stored in registers + and so no allowance is needed for the H/W cursor. In addition to + this many graphics operations are speeded up using a "pixmap + cache". Leaving too little memory available for the cache will + only have a detrimental effect on the graphics performance. + + * PseudoColor Overlay + If you use the "overlay" option, then there are actually two + framebuffers in the video memory. An 8bpp one and a 16bpp one. + The total memory requirements in this mode of operation is + therefore similar to a 24bpp mode. The overlay consumes memory + bandwidth, so that the maximum dotclock will be similar to a + 24bpp mode. + + * XVideo extension* + Like the overlays, the Xvideo extension uses a part of the video + memory for a second framebuffer. In this case enough memory + needs to be left for the largest unscaled video window that will + be displayed. + + * VESA like modes + We recommend that you try and pick a mode that is similar to a + standard VESA mode. If you don't a suspend/resume or LCD/CRT + switch might mess up the screen. This is a problem with the + video BIOS not knowing about all the funny modes that might be + selected. + + * Dot Clock + For LCD screens, the lowest clock that gives acceptable contrast + and flicker is usually the best one. This also gives more memory + bandwidth for use in the drawing operations. Some users prefer + to use clocks that are defined by their BIOS. This has the + advantage that the BIOS will probably restore the clock they + specified after a suspend/resume or LCD/CRT switch. For a + complete discussion on the dot clock limitations, see the next + section. + + * Dual-head display + Dual-head display has two effects on the modelines. Firstly, the + memory requirements of both heads must fit in the available + memory. Secondly, the memory bandwidth of the video processor is + shared between the two heads. Hence the maximum dot-clock might + need to be limited. + + The driver is capable of driving both a CRT and a flat panel display. + In fact the timing for the flat panel are dependent on the + specification of the panel itself and are independent of the + particular mode chosen. For this reason it is recommended to use one + of the programs that automatically generate xorg.conf files, such as + "xorgconfig". + + However there are many older machines, particularly those with 800x600 + screen or larger, that need to reprogram the panel timings. The reason + for this is that the manufacturer has used the panel timings to get a + standard EGA mode to work on flat panel, and these same timings don't + work for an SVGA mode. For these machines the "UseModeline" and/or + possibly the "FixPanelSize" option might be needed. Some machines that + are known to need these options include. + + + + Modeline "640x480@8bpp" 25.175 640 672 728 816 480 489 501 526 + Modeline "640x480@16bpp" 25.175 640 672 728 816 480 489 501 526 + Options: "UseModeline" + Tested on a Prostar 8200, (640x480, 65548, 1Mbyte) + + + + Modeline "800x600@8bpp" 28.322 800 808 848 936 600 600 604 628 + Options: "FixPanelSize", "UseModeline" + Tested on a HP OmniBook 5000CTS (800x600 TFT, 65548, 1Mbyte) + + + + Modeline "800x600@8bpp" 30.150 800 896 960 1056 600 600 604 628 + Options: "FixPanelSize", "UseModeline" + Tested on a Zeos Meridan 850c (800x600 DSTN, 65545, 1Mbyte) + + + + The IBM PC110 works best with a 15MHz clock (Thanks to Alan Cox): + + + Modeline "640x480" 15.00 640 672 728 816 480 489 496 526 + Options: "TextClockFreq" "15.00" + IBM PC110 (65535, Citizen L6481L-FF DSTN) + + + + The NEC Versa 4080 just needs the "FixPanelSize" option. To the best + of my knowledge no machine with a HiQV needs the "UseModeline" or + "FixPanelSize" options. + + + 5. Dual Display Channel + + + XFree86 releases later than 4.1.0 and X.Org releases later than 6.7.0 + support dual-channel display on the ct69030. This support can be used + to give a single display image on two screen with different refresh + rates, or entirely different images on the two displays. + + Dual refresh rate display can be selected with the "DualRefresh" + option described above. However to use the dual-head support is + slightly more complex. Firstly, the ct69030 chipset must be installed + on a PCI bus. This is a driver limitation that might be relaxed in the + future. In addition the device, screen and layout sections of the + "xorg.conf" must be correctly configured. A sample of an incomplete + "xorg.conf" is given below + + + + Section "Device" + Identifier "Chips and Technologies - Pipe A" + Driver "chips" + BusID "PCI:0:20:0" + Screen 0 + EndSection + + Section "Device" + Identifier "Chips and Technologies - Pipe B" + Driver "chips" + BusID "PCI:0:20:0" + Screen 1 + EndSection + + Section "Screen" + Identifier "Screen 0" + Device "Chips and Technologies - Pipe A" + Monitor "generic LCD" + + SubSection "Display" + Depth 16 + Modes "1024x768" + EndSubsection + EndSection + + Section "Screen" + Identifier "Screen 1" + Device "Chips and Technologies - Pipe B" + Monitor "generic CRT" + + SubSection "Display" + Depth 16 + Modes "1024x768" + EndSubsection + EndSection + + Section "ServerLayout" + Identifier "Main Layout" + Screen "Screen 0" + Screen "Screen 1" RightOf "Screen 0" + InputDevice "Mouse1" "CorePointer" + InputDevice "Keyboard1" "CoreKeyboard" + EndSection + + + + The device section must include the PCI BusID. This can be found from + the log file of a working single-head installation. For instance, the + line + + + + (--) PCI:*(0:20:0) C&T 69030 rev 97, Mem @ 0xed000000/24 + + + + appears for the case above. Additionally, the "Screen" option must + appear in the device section. It should be noted that if a flat panel + is used, this it must be allocated to "Screen 0". + + The server can then be started with the "+xinerama" option as follows + + + + startx -- +xinerama + + + + For more information, read the Xinerama documentation. + + It should be noted that the dual channel display options of the 69030 + require the use of additional memory bandwidth, as each display + channel independently accesses the video memory. For this reason, the + maximum colour depth and resolution that can be supported in a dual + channel mode will be reduced compared to a single display channel + mode. However, as the driver does not prevent you from using a mode + that will exceed the memory bandwidth of the 69030, but a warning like + + + + (WW) Memory bandwidth requirements exceeded by dual-channel + (WW) mode. Display might be corrupted!!! + + + + If you see such display corruption, and you have this warning, your + choices are to reduce the refresh rate, colour depth or resolution, or + increase the speed of the memory clock with the the "SetMClk" option + described above. Note that increasing the memory clock also has its + own problems as described above. + + + 6. The Full Story on Clock Limitations + + + There has been much confusion about exactly what the clock limitations + of the Chips and Technologies chipsets are. Hence I hope that this + section will clear up the misunderstandings. + + In general there are two factors determining the maximum dotclock. + There is the limit of the maximum dotclock the video processor can + handle, and there is another limitation of the available memory + bandwidth. The memory bandwidth is determined by the clock used for + the video memory. For chipsets incapable of colour depths greater + that 8bpp like the 65535, the dotclock limit is solely determined by + the highest dotclock the video processor is capable of handling. So + this limit will be either 56MHz or 68MHz for the 655xx chipsets, + depending on what voltage they are driven with, or 80MHz for the 64200 + WinGine machines. + + The 6554x and 64300 WinGine chipsets are capable of colour depths of + 16 or 24bpp. However there is no reliable way of probing the memory + clock used in these chipsets, and so a conservative limit must be + taken for the dotclock limit. In this case the driver divides the + video processors dotclock limitation by the number of bytes per pixel, + so that the limitations for the various colour depths are + + + 8bpp 16bpp 24bpp + 64300 85 42.5 28.33 + 65540/65545 3.3v 56 28 18.67 + 65540/65545 5v 68 34 22.67 + 65546/65548 80 40 26.67 + + + + For a CRT or TFT screen these limitations are conservative and the + user might safely override them with the "DacSpeed" option to some + extent. However these numbers take no account of the extra bandwidth + needed for DSTN screens. + + For the HiQV series of chips, the memory clock can be successfully + probed. Hence you will see a line like + + + (--) CHIPS(0): Probed memory clock of 40.090 MHz + + + + in your startx log file. Note that many chips are capable of higher + memory clocks than actually set by BIOS. You can use the "SetMClk" + option in your xorg.conf file to get a higher MClk. However some video + ram, particularly EDO, might not be fast enough to handle this, + resulting in drawing errors on the screen. The formula to determine + the maximum usable dotclock on the HiQV series of chips is + + + Max dotclock = min(MaxDClk, 0.70 * 8 * MemoryClk / (BytesPerPixel + + (isDSTN == TRUE ? 1 : 0))) + + + + if you chips is a 69030 or 69000 or + + + Max dotclock = min(MaxDClk, 0.70 * 4 * MemoryClk / (BytesPerPixel + + (isDSTN == TRUE ? 1 : 0))) + + + + otherwise. This effectively means that there are two limits on the + dotclock. One the overall maximum, and another due to the available + memory bandwidth of the chip. The 69030 and 69000 have a 64bit memory + bus and thus transfer 8 bytes every clock thus (hence the 8), while + the other HiQV chipsets are 32bit and transfer 4 bytes per clock cycle + (hence the 4). However, after accounting for the RAS/CAS signaling + only about 70% of the bandwidth is available. The whole thing is + divided by the bytes per pixel, plus an extra byte if you are using a + DSTN. The extra byte with DSTN screens is used for the frame + buffering/acceleration in these screens. So for the various Chips and + Technologies chips the maximum specifications are + + + + Max DClk MHz Max Mem Clk MHz + 65550 rev A 3.3v 80 38 + 65550 rev A 5v 110 38 + 65550 rev B 95 50 + 65554 94.5 55 + 65555 110 55 + 68554 110 55 + 69000 135 83 + 69030 170 100 + + + + Note that all of the chips except the 65550 rev A are 3.3v only. Which + is the reason for the drop in the dot clock. Now the maximum memory + clock is just the maximum supported by the video processor, not the + maximum supported by the video memory. So the value actually used for + the memory clock might be significantly less than this maximum value. + But assuming your memory clock is programmed to these maximum values + the various maximum dot clocks for the chips are + + + ------CRT/TFT------- --------DSTN-------- + 8bpp 16bpp 24bpp 8bpp 16bpp 24bpp + 65550 rev A 3.3v 80 53.2 35.47 53.2 35.47 26.6 + 65550 rev A 5v 106.2 53.2 35.47 53.2 35.47 26.6 + 65550 rev B 95 70 46.67 70 46.67 35.0 + 65554 94.5 77 51.33 77 51.33 38.5 + 65555 110 77 51.33 77 51.33 38.5 + 68554 110 77 51.33 77 51.33 38.5 + 69000 135 135 135 135 135 116.2 + 69030 170 170 170 170 170 140 + + + + If you exceed the maximum set by the memory clock, you'll get + corruption on the screen during graphics operations, as you will be + starving the HW BitBlt engine of clock cycles. If you are driving the + video memory too fast (too high a MemClk) you'll get pixel corruption + as the data actually written to the video memory is corrupted by + driving the memory too fast. You can probably get away with exceeding + the Max DClk at 8bpp on TFT's or CRT's by up to 10% or so without + problems, it will just generate more heat, since the 8bpp clocks + aren't limited by the available memory bandwidth. + + If you find you truly can't achieve the mode you are after with the + default clock limitations, look at the options "DacSpeed" and + "SetMClk". Using these should give you all the capabilities you'll + need in the server to get a particular mode to work. However use + caution with these options, because there is no guarantee that driving + the video processor beyond it capabilities won't cause damage. + + + 7. Troubleshooting + + + + The cursor appears as a white box, after switching modes + There is a known bug in the H/W cursor, that sometimes causes + the cursor to be redrawn as a white box, when the mode is + changed. This can be fixed by moving the cursor to a different + region, switching to the console and back again, or if it is too + annoying the H/W cursor can be disabled by removing the + "HWcursor" option. + + The cursor hot-spot isn't at the same point as the cursor + With modes on the 6555x machines that are stretched to fill the + flat panel, the H/W cursor is not correspondingly stretched. + This is a small and long-standing bug in the current server. You + can avoid this by either using the "NoStretch" option or + removing the HWcursor" option. + + The lower part of the screen is corrupted + Many DSTN screens use the top of video ram to implement a frame + accelerator. This reduces the amount of video ram available to + the modes. The server doesn't prevent the user from specifying a + mode that will use this memory, it prints a warning on the + console. The effect of this problem will be that the lower part + of the screen will reside in the same memory as the frame + accelerator and will therefore be corrupt. Try reducing the + amount of memory consumed by the mode. + + There is a video signal, but the screen doesn't sync. + You are using a mode that your screen cannot handle. If it is a + non-standard mode, maybe you need to tweak the timings a bit. If + it is a standard mode and frequency that your screen should be + able to handle, try to find different timings for a similar mode + and frequency combination. For LCD modes, it is possible that + your LCD panel requires different panel timings at the text + console than with a graphics mode. In this case you will need + the "UseModeline" and perhaps also the "FixPanelSize" options to + reprogram the LCD panel timings to sensible values. + + `Wavy' screen. + Horizontal waving or jittering of the whole screen, continuously + (independent from drawing operations). You are probably using a + dot clock that is too high (or too low); it is also possible + that there is interference with a close MCLK. Try a lower dot + clock. For CRT's you can also try to tweak the mode timings; + try increasing the second horizontal value somewhat. + + Crash or hang after start-up (probably with a black screen). + Try the "NoAccel" or one of the XAA acceleration options + discussed above. Check that the BIOS settings are OK; in + particular, disable caching of 0xa0000-0xaffff. Disabling hidden + DRAM refresh may also help. + + Hang as the first text is appearing on the screen on SVR4 + machines. + This problem has been reported under UnixWare 1.x, but not + tracked down. It doesn't occur under UnixWare 2.x and only + occurs on the HiQV series of chips. It might affect some other + SVR4 operating systems as well. The workaround is to turn off + the use of CPU to screen acceleration with the + "XaaNoCPUToScreenColorExapndFill" option. + + Crash, hang, or trash on the screen after a graphics operation. + This may be related to a bug in one of the accelerated + functions, or a problem with the BitBLT engine. Try the + "NoAccel" or one of the XAA acceleration options discussed + above. Also check the BIOS settings. It is also possible that + with a high dot clock and depth on a large screen there is very + little bandwidth left for using the BitBLT engine. Try reducing + the clock. + + Chipset is not detected. + Try forcing the chipset to a type that is most similar to what + you have. + + The screen is blank when starting X + One possible cause of this problem with older linux kernels is + that the "APM_DISPLAY_BLANK" option didn't work correct. Either + upgrade your kernel or rebuild it with the "APM_DISPLAY_BLANK" + option disabled. If the problem remains, or you aren't using + linux, a CRT/LCD or switch to and from the virtual console will + often fix it. + + Textmode is not properly restored + This has been reported on some configurations. Many laptops use + the programmable clock of the 6554x chips at the console. It is + not always possible to find out the setting that is used for + this clock if BIOS has written the MClk after the VClk. Hence + the server assumes a 25.175MHz clock at the console. This is + correct for most modes, but can cause some problems. Usually + this is fixed by switching between the LCD and CRT. + Alternatively the user can use the "TextClockFreq" option + described above to select a different clock for the text + console. Another possible cause of this problem is if linux + kernels are compiled with the "APM_DISPLAY_BLANK" option. As + mentioned before, try disabling this option. + + I can't display 640x480 on my 800x600 LCD + The problem here is that the flat panel needs timings that are + related to the panel size, and not the mode size. There is no + facility in the current Xservers to specify these values, and so + the server attempts to read the panel size from the chip. If the + user has used the "UseModeline" or "FixPanelSize" options the + panel timings are derived from the mode, which can be different + than the panel size. Try deleting these options from xorg.conf + or using an LCD/CRT switch. + + I can't get a 320x240 mode to occupy the whole 640x480 LCD + There is a bug in the 6554x's H/W cursor for modes that are + doubled vertically. The lower half of the screen is not + accessible. The servers solution to this problem is not to do + doubling vertically. Which results in the 320x240 mode only + expanded to 640x360. If this is a problem, a work around is to + remove the "HWcursor" option. The server will then allow the + mode to occupy the whole 640x480 LCD. + + After a suspend/resume my screen is messed up + During a suspend/resume, the BIOS controls what is read and + written back to the registers. If the screen is using a mode + that BIOS doesn't know about, then there is no guarantee that it + will be resumed correctly. For this reason a mode that is as + close to VESA like as possible should be selected. It is also + possible that the VGA palette can be affected by a + suspend/resume. Using an 8bpp, the colour will then be + displayed incorrectly. This shouldn't affect higher depths, and + is fixable with a switch to the virtual console and back. + + The right hand edge of the mode isn't visible on the LCD + This is usually due to a problem with the "LcdCenter" option. If + this option is removed form xorg.conf, then the problem might go + away. Alternatively the manufacturer could have incorrectly + programmed the panel size in the EGA console mode. The + "FixPanelSize" can be used to force the modeline values into the + panel size registers. Two machines that are known to have this + problem are the "HP OmniBook 5000" and the "NEC Versa 4080". + + My TFT screen has a reddish tint in 24bpp mode + For 6554x chipsets the server assumes that the TFT bus width is + 24bits. If this is not true then the screen will appear to have + a reddish tint. This can be fixed by using the "18BitBus" + option. Note that the reverse is also true. If the "18BitBus" is + used and the TFT bus width is 24bpp, then the screen will appear + reddish. Note that this option only has an effect on TFT + screens. + + SuperProbe won't work with my chipset + At least one non-PCI bus system with a HiQV chipset has been + found to require the "-no_bios" option for SuperProbe to + correctly detect the chipset with the factory default BIOS + settings. The server itself can correctly detect the chip in the + same situation. + + My 690xx machine lockups when using the + The 690xx MMIO mode has been implemented entirely from the + manual as I don't have the hardware to test it on. At this point + no testing has been done and it is entirely possible that the + "MMIO option will lockup your machine. You have been warned! + However if you do try this option and are willing to debug it, + I'd like to hear from you. + + My TrueColor windows are corrupted when using the + Chips and Technologies specify that the memory clock used with + the multimedia engine running should be lower than that used + without. As use of the HiQV chipsets multimedia engine was + supposed to be for things like zoomed video overlays, its use + was supposed to be occasional and so most machines have their + memory clock set to a value that is too high for use with the + "Overlay" option. So with the "Overlay" option, using the + "SetMClk" option to reduce the speed of the memory clock is + recommended. + + The mpeg video playing with the XVideo extension has corrupted + colours + The XVideo extension has only recently been added to the chips + driver. Some YUV to RGB colour have been noted at 15 and 16 bit + colour depths. However, 8 and 24 bit colour depths seem to work + fine. + + My ct69030 machine locks up when starting X + The ct69030 chipset introduced a new dual channel architecture. + In its current form, X can not take advantage of this second + display channel. In fact if the video BIOS on the machine sets + the ct69030 to a dual channel mode by default, X will lockup + hard at this point. The solution is to use the BIOS setup to + change to a single display channel mode, ensuring that both the + IOSS and MSS registers are set to a single channel mode. Work is + underway to fix this. + + I can't start X-windows with 16, 24 or 32bpp + Firstly, is your machine capable of 16/24/32bpp with the mode + specified. Many LCD displays are incapable of using a 24bpp + mode. Also you need at least a 65540 to use 16/24bpp and at + least a 65550 for 32bpp. The amount of memory used by the mode + will be doubled/tripled/quadrupled. The correct options to start + the server with these modes are + + + startx -- -depth 16 5-6-5 RGB ('64K color', XGA) + startx -- -depth 15 5-5-5 RGB ('Hicolor') + startx -- -depth 24 8-8-8 RGB truecolor + + + or with the HiQV series of chips you might try + + startx -- -depth 24 -fbbpp 32 8-8-8 RGB truecolor + + + however as X11R7.5 allows 32bpp pixmaps to be used with frame- + buffers operating in 24bpp, this mode of operating will cost per- + formance for no gain in functionality. + + Note that the "-bpp" option has been removed and replaced with a + "-depth" and "-fbbpp" option because of the confusion between the + depth and number of bits per pixel used to represent to framebuffer + and the pixmaps in the screens memory. + + A general problem with the server that can manifested in many way such + as drawing errors, wavy screens, etc is related to the programmable + clock. Many potential programmable clock register setting are + unstable. However luckily there are many different clock register + setting that can give the same or very similar clocks. The clock code + can be fooled into giving a different and perhaps more stable clock by + simply changing the clock value slightly. For example 65.00MHz might + be unstable while 65.10MHz is not. So for unexplained problems not + addressed above, please try to alter the clock you are using slightly, + say in steps of 0.05MHz and see if the problem goes away. + Alternatively, using the "CRTClkIndx" or "FPClkIndx" option with HiQV + chips might also help. + + + For other screen drawing related problems, try the "NoAccel" or one of + the XAA acceleration options discussed above. A useful trick for all + laptop computers is to switch between LCD/CRT (usually with something + like Fn-F5), if the screen is having problems. + + If you are having driver-related problems that are not addressed by + this document, or if you have found bugs in accelerated functions, you + can try contacting the Xorg team (the current driver maintainer can be + reached at ). + + + 8. Disclaimer + + + The Xorg X server, allows the user to do damage to their hardware with + software with old monitors which may not tolerate bad display + settings. Although the authors of this software have tried to prevent + this, they disclaim all responsibility for any damage caused by the + software. Use caution, if you think the X server is frying your + screen, TURN THE COMPUTER OFF!! + + + 9. Acknowledgement + + + The authors of this software wish to acknowledge the support supplied + by Chips and Technologies during the development of this software. + + + 10. Authors + + + Major Contributors (In no particular order) + + o Nozomi Ytow + + o Egbert Eich + + o David Bateman + + o Xavier Ducoin + + Contributors (In no particular order) + + o Ken Raeburn + + + o Shigehiro Nomura + + o Marc de Courville + + o Adam Sulmicki + + o Jens Maurer + + We also thank the many people on the net who have contributed by + reporting bugs and extensively testing this server. + + + diff --git a/hw/xfree86/drivers/video/chips/man/chips.man b/hw/xfree86/drivers/video/chips/man/chips.man new file mode 100644 index 0000000000..9821bc9cce --- /dev/null +++ b/hw/xfree86/drivers/video/chips/man/chips.man @@ -0,0 +1,250 @@ +.\" shorthand for double quote that works everywhere. +.ds q \N'34' +.TH CHIPS __drivermansuffix__ 2011-03-29 __vendorversion__ +.SH NAME +chips \- Chips and Technologies video driver for Xorg +.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 Xorg 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. +.SS Basic Architecture +The supported chipsets are +.BR ct65520 ", " ct65525 ", " ct65530 ", " +.BR ct65535 ", " ct65540 ", " ct65545 ", " +.B ct65546 +and +.BR ct65548 . +.PP +Color depths 1, 4, and 8 are supported on all chipsets, +while depths 15, 16, and 24 are supported only on the +.BR 65540 ", " 65545 ", " 65546 +and +.B 65548 +chipsets. +The driver is accelerated when used with the +.BR 65545 ", " 65546 +or +.B 65548 +chipsets, however the DirectColor visual is not available. +.SS Wingine Architecture +The supported chipsets are +.B ct64200 +and +.BR 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. +.SS HiQV Architecture +The supported chipsets are +.BR ct65550 ", " ct65554 ", " ct65555 ", " ct68554 ", " ct69000 +and +.BR 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 +.BR xorg.conf (__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 it may be 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 SW 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 \*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. +.TP +.BI "Option \*qFpMode\*q \*q" boolean \*q +The driver probes the chip to find out if a flat panel (LCD) is connected +and active. +If this is true it limits the possible screen size to the maximum +resolution of the panel. +The chips is initialized by the BIOS which may +set the chip to 'dual' mode even if no panel is connected. +In this case the available resolution on the CRT is limited to the panel size +the BIOS has set. +To tell the driver that no panel is connected despite +of what the BIOS is saying set this option to off. +Don't set it to off if a panel is connected. +Default: value probed by BIOS. +.SH "SEE ALSO" +.BR Xorg (__appmansuffix__), +.BR xorg.conf (__filemansuffix__), +.BR Xserver (__appmansuffix__), +.BR X (__miscmansuffix__) +.PP +You are also recommended to read the README file that comes with the driver +source, 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/hw/xfree86/drivers/video/chips/src/compat-api.h b/hw/xfree86/drivers/video/chips/src/compat-api.h new file mode 100644 index 0000000000..89976e41c4 --- /dev/null +++ b/hw/xfree86/drivers/video/chips/src/compat-api.h @@ -0,0 +1,104 @@ +/* + * Copyright 2012 Red Hat, Inc. + * + * 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 (including the next + * paragraph) 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 + * THE AUTHORS OR COPYRIGHT HOLDERS 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. + * + * Author: Dave Airlie + */ + +/* this file provides API compat between server post 1.13 and pre it, + it should be reused inside as many drivers as possible */ +#ifndef COMPAT_API_H +#define COMPAT_API_H + +#ifndef GLYPH_HAS_GLYPH_PICTURE_ACCESSOR +#define GetGlyphPicture(g, s) GlyphPicture((g))[(s)->myNum] +#define SetGlyphPicture(g, s, p) GlyphPicture((g))[(s)->myNum] = p +#endif + +#ifndef XF86_HAS_SCRN_CONV +#define xf86ScreenToScrn(s) xf86Screens[(s)->myNum] +#define xf86ScrnToScreen(s) screenInfo.screens[(s)->scrnIndex] +#endif + +#ifndef XF86_SCRN_INTERFACE + +#define SCRN_ARG_TYPE int +#define SCRN_INFO_PTR(arg1) ScrnInfoPtr pScrn = xf86Screens[(arg1)] + +#define SCREEN_ARG_TYPE int +#define SCREEN_PTR(arg1) ScreenPtr pScreen = screenInfo.screens[(arg1)] + +#define SCREEN_INIT_ARGS_DECL int i, ScreenPtr pScreen, int argc, char **argv + +#define BLOCKHANDLER_ARGS_DECL int arg, pointer blockData, pointer pTimeout, pointer pReadmask +#define BLOCKHANDLER_ARGS arg, blockData, pTimeout, pReadmask + +#define CLOSE_SCREEN_ARGS_DECL int scrnIndex, ScreenPtr pScreen +#define CLOSE_SCREEN_ARGS scrnIndex, pScreen + +#define ADJUST_FRAME_ARGS_DECL int arg, int x, int y, int flags +#define ADJUST_FRAME_ARGS(arg, x, y) (arg)->scrnIndex, x, y, 0 + +#define SWITCH_MODE_ARGS_DECL int arg, DisplayModePtr mode, int flags +#define SWITCH_MODE_ARGS(arg, m) (arg)->scrnIndex, m, 0 + +#define FREE_SCREEN_ARGS_DECL int arg, int flags + +#define VT_FUNC_ARGS_DECL int arg, int flags +#define VT_FUNC_ARGS pScrn->scrnIndex, 0 + +#define XF86_SCRN_ARG(x) ((x)->scrnIndex) +#else +#define SCRN_ARG_TYPE ScrnInfoPtr +#define SCRN_INFO_PTR(arg1) ScrnInfoPtr pScrn = (arg1) + +#define SCREEN_ARG_TYPE ScreenPtr +#define SCREEN_PTR(arg1) ScreenPtr pScreen = (arg1) + +#define SCREEN_INIT_ARGS_DECL ScreenPtr pScreen, int argc, char **argv + +#if ABI_VIDEODRV_VERSION >= SET_ABI_VERSION(23, 0) +#define BLOCKHANDLER_ARGS_DECL ScreenPtr arg, pointer pTimeout +#define BLOCKHANDLER_ARGS arg, pTimeout +#else +#define BLOCKHANDLER_ARGS_DECL ScreenPtr arg, pointer pTimeout, pointer pReadmask +#define BLOCKHANDLER_ARGS arg, pTimeout, pReadmask +#endif + +#define CLOSE_SCREEN_ARGS_DECL ScreenPtr pScreen +#define CLOSE_SCREEN_ARGS pScreen + +#define ADJUST_FRAME_ARGS_DECL ScrnInfoPtr arg, int x, int y +#define ADJUST_FRAME_ARGS(arg, x, y) arg, x, y + +#define SWITCH_MODE_ARGS_DECL ScrnInfoPtr arg, DisplayModePtr mode +#define SWITCH_MODE_ARGS(arg, m) arg, m + +#define FREE_SCREEN_ARGS_DECL ScrnInfoPtr arg + +#define VT_FUNC_ARGS_DECL ScrnInfoPtr arg +#define VT_FUNC_ARGS pScrn + +#define XF86_SCRN_ARG(x) (x) + +#endif + +#endif diff --git a/hw/xfree86/drivers/video/chips/src/ct_BlitMM.h b/hw/xfree86/drivers/video/chips/src/ct_BlitMM.h new file mode 100644 index 0000000000..eea77639d4 --- /dev/null +++ b/hw/xfree86/drivers/video/chips/src/ct_BlitMM.h @@ -0,0 +1,138 @@ + + + + + + +/* 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/hw/xfree86/drivers/video/chips/src/ct_Blitter.h b/hw/xfree86/drivers/video/chips/src/ct_Blitter.h new file mode 100644 index 0000000000..3de88eddd1 --- /dev/null +++ b/hw/xfree86/drivers/video/chips/src/ct_Blitter.h @@ -0,0 +1,166 @@ + + + + + + +/* 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 (aligned 8 pixel x 8 line) pointer */ +/* 31-21 reserved (0) */ +/* 8BD0: 15-0 background 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/hw/xfree86/drivers/video/chips/src/ct_BltHiQV.h b/hw/xfree86/drivers/video/chips/src/ct_BltHiQV.h new file mode 100644 index 0000000000..2180db3050 --- /dev/null +++ b/hw/xfree86/drivers/video/chips/src/ct_BltHiQV.h @@ -0,0 +1,185 @@ + + + + + + +/* 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 offset 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)); \ + usleep(10000); \ + cPtr->writeXR(cPtr, 0x20, (tmp & 0xFD)); \ + break; \ + } \ + } \ + } + +#if X_BYTE_ORDER == X_BIG_ENDIAN +# define TWEAK_24_BE(c) \ + c = ((c & 0xFF0000) >> 16) | (c & 0xFF00) | (( c & 0xFF) << 16) +#else +# define TWEAK_24_BE(c) +#endif + +#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) {\ + TWEAK_24_BE(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) {\ + TWEAK_24_BE(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/hw/xfree86/drivers/video/chips/src/ct_accel.c b/hw/xfree86/drivers/video/chips/src/ct_accel.c new file mode 100644 index 0000000000..19eaa08f2d --- /dev/null +++ b/hw/xfree86/drivers/video/chips/src/ct_accel.c @@ -0,0 +1,80 @@ +/* + * Copyright 1996, 1997, 1998 by David Bateman + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* + * 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 + * "officially" 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 "compiler.h" + +/* Drivers that need to access the PCI config space directly need this */ +#include "xf86Pci.h" + +/* Drivers that use XAA need this */ +#include "xf86fbman.h" + +/* Our driver specific include file */ +#include "ct_driver.h" + +#define CATNAME(prefix,subname) prefix##subname + +#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 + +Bool +CTNAME(AccelInit)(ScreenPtr pScreen) +{ + return FALSE; +} + +void +CTNAME(Sync)(ScrnInfoPtr pScrn) +{ +} + diff --git a/hw/xfree86/drivers/video/chips/src/ct_bank.c b/hw/xfree86/drivers/video/chips/src/ct_bank.c new file mode 100644 index 0000000000..0264616155 --- /dev/null +++ b/hw/xfree86/drivers/video/chips/src/ct_bank.c @@ -0,0 +1,629 @@ + +/* + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#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" + +/* Everything using inb/outb, etc needs "compiler.h" */ +#include "compiler.h" + +/* Drivers that need to access the PCI config space directly need this */ +#include "xf86Pci.h" + +/* Driver specific headers */ +#include "ct_driver.h" + +#if defined(__arm32__) && defined(__NetBSD__) +#include +#define arm32_drain_writebuf() sysarch(1, 0) +#elif defined(__arm32__) +#define arm32_drain_writebuf() +#endif + +#define ChipsBank(pScreen) CHIPSPTR(xf86ScreenToScrn(pScreen))->Bank + +#ifdef DIRECT_REGISTER_ACCESS +int +CHIPSSetRead(ScreenPtr pScreen, int bank) +{ + CHIPSPtr cPtr = CHIPSPTR(xf86ScreenToScrn(pScreen)); + + 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(xf86ScreenToScrn(pScreen)); + + 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(xf86ScreenToScrn(pScreen)); + + 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(xf86ScreenToScrn(pScreen)); + + 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(xf86ScreenToScrn(pScreen)); + + 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(xf86ScreenToScrn(pScreen)); + + 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(xf86ScreenToScrn(pScreen)); + 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(xf86ScreenToScrn(pScreen)); + 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(xf86ScreenToScrn(pScreen)); + 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(xf86ScreenToScrn(pScreen)); + 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(xf86ScreenToScrn(pScreen)); + 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(xf86ScreenToScrn(pScreen)); + 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(xf86ScreenToScrn(pScreen)); + + 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(xf86ScreenToScrn(pScreen)); + + 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(xf86ScreenToScrn(pScreen)); + + 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(xf86ScreenToScrn(pScreen)); + + 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(xf86ScreenToScrn(pScreen)); + + 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(xf86ScreenToScrn(pScreen)); + + 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(xf86ScreenToScrn(pScreen)); + + 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(xf86ScreenToScrn(pScreen)); + + 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(xf86ScreenToScrn(pScreen)); + 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(xf86ScreenToScrn(pScreen)); + 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(xf86ScreenToScrn(pScreen)); + 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(xf86ScreenToScrn(pScreen)); + 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(xf86ScreenToScrn(pScreen)); + 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(xf86ScreenToScrn(pScreen)); + 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(xf86ScreenToScrn(pScreen)); + + 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(xf86ScreenToScrn(pScreen)); + + 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/hw/xfree86/drivers/video/chips/src/ct_cursor.c b/hw/xfree86/drivers/video/chips/src/ct_cursor.c new file mode 100644 index 0000000000..3598bd27c4 --- /dev/null +++ b/hw/xfree86/drivers/video/chips/src/ct_cursor.c @@ -0,0 +1,475 @@ + +/* + * 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 + * Modified for Chips and Technologies by David Bateman + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* All drivers should typically include these */ +#include "xf86.h" +#include "xf86_OSproc.h" + +/* Everything using inb/outb, etc needs "compiler.h" */ +#include "compiler.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) + +/* 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 (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(pScrn->bitsPerPixel >> 3) { + case 4: + case 3: +#if 1 + memcpy((unsigned char *)cPtr->FbBase + cAcl->CursorAddress, + src, cPtr->CursorInfoRec->MaxWidth * + cPtr->CursorInfoRec->MaxHeight / 4); +#else + 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++; + } +#endif + 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++; + } + 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 pScreen, CursorPtr pCurs) +{ + ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + CHIPSPtr cPtr = CHIPSPTR(pScrn); + + return (((cPtr->Flags & ChipsHWCursor) != 0) + && !(pScrn->currentMode->Flags & V_DBLSCAN)); +} + +Bool +CHIPSCursorInit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + 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/hw/xfree86/drivers/video/chips/src/ct_ddc.c b/hw/xfree86/drivers/video/chips/src/ct_ddc.c new file mode 100644 index 0000000000..677d840538 --- /dev/null +++ b/hw/xfree86/drivers/video/chips/src/ct_ddc.c @@ -0,0 +1,287 @@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* All drivers should typically include these */ +#include "xf86.h" +#include "xf86_OSproc.h" + +/* Everything using inb/outb, etc needs "compiler.h" */ +#include "compiler.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); +} + +static void +chips_ddc1SetSpeed(ScrnInfoPtr pScrn, xf86ddcSpeed speed) +{ + vgaHWddc1SetSpeed(pScrn, speed); +} + +void +chips_ddc1(ScrnInfoPtr pScrn) +{ + unsigned char FR0B, FR0C, XR62; + unsigned char mask_c = 0x00; + unsigned char val, tmp_val = 0; + 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(XF86_SCRN_ARG(pScrn), chips_ddc1SetSpeed, + 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 = malloc(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/hw/xfree86/drivers/video/chips/src/ct_dga.c b/hw/xfree86/drivers/video/chips/src/ct_dga.c new file mode 100644 index 0000000000..af0c1c27f4 --- /dev/null +++ b/hw/xfree86/drivers/video/chips/src/ct_dga.c @@ -0,0 +1,235 @@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86Pci.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 +DGAFunctionRec CHIPS_DGAFuncs = { + CHIPS_OpenFramebuffer, + NULL, + CHIPS_SetMode, + CHIPS_SetViewport, + CHIPS_GetViewport, + NULL, NULL, NULL, NULL +}; + +static +DGAFunctionRec CHIPS_MMIODGAFuncs = { + CHIPS_OpenFramebuffer, + NULL, + CHIPS_SetMode, + CHIPS_SetViewport, + CHIPS_GetViewport, + NULL, NULL, NULL, NULL +}; + +static +DGAFunctionRec CHIPS_HiQVDGAFuncs = { + CHIPS_OpenFramebuffer, + NULL, + CHIPS_SetMode, + CHIPS_SetViewport, + CHIPS_GetViewport, + NULL, NULL, NULL, NULL +}; + + +Bool +CHIPSDGAInit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + 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 = realloc(modes, (num + 2) * sizeof(DGAModeRec)); + oneMore = TRUE; + } else { + newmodes = realloc(modes, (num + 1) * sizeof(DGAModeRec)); + oneMore = FALSE; + } + + if(!newmodes) { + free(modes); + return FALSE; + } + modes = newmodes; + +SECOND_PASS: + + currentMode = modes + num; + num++; + + currentMode->mode = pMode; + currentMode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE; + 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(VT_FUNC_ARGS); + + cPtr->DGAactive = FALSE; + } + } else { + if(!cPtr->DGAactive) { /* save the old parameters */ + OldDisplayWidth[index] = pScrn->displayWidth; + pScrn->LeaveVT(VT_FUNC_ARGS); + cPtr->DGAactive = TRUE; + } + + pScrn->displayWidth = pMode->bytesPerScanline / + (pMode->bitsPerPixel >> 3); + + CHIPSSwitchMode(SWITCH_MODE_ARGS(pScrn, pMode->mode)); + } + + 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(ADJUST_FRAME_ARGS(pScrn, x, y)); + cPtr->DGAViewportStatus = 0; /* CHIPSAdjustFrame loops until finished */ +} + +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/hw/xfree86/drivers/video/chips/src/ct_driver.c b/hw/xfree86/drivers/video/chips/src/ct_driver.c new file mode 100644 index 0000000000..48cfdbbbcf --- /dev/null +++ b/hw/xfree86/drivers/video/chips/src/ct_driver.c @@ -0,0 +1,7315 @@ +/* + * Copyright 1993 by Jon Block + * Modified by Mike Hollick + * Modified 1994 by Régis Cridlig + * + * Major Contributors to XFree86 3.2 + * Modified 1995/6 by Nozomi Ytow + * Modified 1996 by Egbert Eich + * Modified 1996 by David Bateman + * Modified 1996 by Xavier Ducoin + * + * Contributors to XFree86 3.2 + * Modified 1995/6 by Ken Raeburn + * Modified 1996 by Shigehiro Nomura + * Modified 1996 by Marc de Courville + * Modified 1996 by Adam Sulmicki + * Modified 1996 by Jens Maurer + * + * Large parts rewritten for XFree86 4.0 + * Modified 1998 by David Bateman + * Modified 1998 by Egbert Eich + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* All drivers should typically include these */ +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86Priv.h" + +/* Everything using inb/outb, etc needs "compiler.h" */ +#include "compiler.h" + +/* Drivers that need to access the PCI config space directly need this */ +#include "xf86Pci.h" + +#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6 +/* Standard resources are defined here */ +#include "xf86Resources.h" + +/* Needed by Resources Access Control (RAC) */ +#include "xf86RAC.h" +#endif + +/* All drivers using the vgahw module need this */ +#include "vgaHW.h" + +/* All drivers initialising the SW cursor need this */ +#include "mipointer.h" + +#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6 +#define USE_MIBANK 1 +#endif + +/* All drivers using the mi banking wrapper need this */ +#ifdef USE_MIBANK +#include "mibank.h" +#endif + +/* All drivers using the mi colormap manipulation need this */ +#include "micmap.h" + +#include "fb.h" +#include "fboverlay.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" + +#include "xf86fbman.h" +/* Driver specific headers */ +#include "ct_driver.h" + +/* traditionally these had been defined in xf86_OSlib.h */ +#ifndef XMODE_RGB +#define XMODE_RGB 0 +#define XMODE_NTSC 1 +#define XMODE_PAL 2 +#define XMODE_SECAM 3 +#endif + +#if defined(__arm__) && defined(__NetBSD__) +#define AVOID_VGAHW 1 +#endif + +/* Mandatory functions */ +static const OptionInfoRec * CHIPSAvailableOptions(int chipid, int busid); +static void CHIPSIdentify(int flags); +#ifdef XSERVER_LIBPCIACCESS +static Bool CHIPSPciProbe(DriverPtr drv, int entity_num, + struct pci_device *dev, intptr_t match_data); +#else +static Bool CHIPSProbe(DriverPtr drv, int flags); +#endif +static Bool CHIPSPreInit(ScrnInfoPtr pScrn, int flags); +static Bool CHIPSScreenInit(SCREEN_INIT_ARGS_DECL); +static Bool CHIPSEnterVT(VT_FUNC_ARGS_DECL); +static void CHIPSLeaveVT(VT_FUNC_ARGS_DECL); +static Bool CHIPSCloseScreen(CLOSE_SCREEN_ARGS_DECL); +static void CHIPSFreeScreen(FREE_SCREEN_ARGS_DECL); +static ModeStatus CHIPSValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, + Bool verbose, int flags); +static Bool CHIPSSaveScreen(ScreenPtr pScreen, int mode); + +/* Internally used functions */ +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, DisplayModePtr mode, + 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(BLOCKHANDLER_ARGS_DECL); + +/* + * 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(__arm__) && 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 CHIPS_VERSION 4000 +#define CHIPS_NAME "CHIPS" +#define CHIPS_DRIVER_NAME "chips" +#define CHIPS_MAJOR_VERSION PACKAGE_VERSION_MAJOR +#define CHIPS_MINOR_VERSION PACKAGE_VERSION_MINOR +#define CHIPS_PATCHLEVEL PACKAGE_VERSION_PATCHLEVEL + + +#ifdef XSERVER_LIBPCIACCESS + +#ifndef _XF86_PCIINFO_H +#define PCI_VENDOR_CHIPSTECH 0x102C +/* Chips & Tech */ +#define PCI_CHIP_65545 0x00D8 +#define PCI_CHIP_65548 0x00DC +#define PCI_CHIP_65550 0x00E0 +#define PCI_CHIP_65554 0x00E4 +#define PCI_CHIP_65555 0x00E5 +#define PCI_CHIP_68554 0x00F4 +#define PCI_CHIP_69000 0x00C0 +#define PCI_CHIP_69030 0x0C30 +#endif + +#define CHIPS_DEVICE_MATCH(d, i) \ + { PCI_VENDOR_CHIPSTECH, (d), PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, (i) } + +static const struct pci_id_match chips_device_match[] = { + CHIPS_DEVICE_MATCH(PCI_CHIP_65545, CHIPS_CT65545), + CHIPS_DEVICE_MATCH(PCI_CHIP_65548, CHIPS_CT65548), + CHIPS_DEVICE_MATCH(PCI_CHIP_65550, CHIPS_CT65550), + CHIPS_DEVICE_MATCH(PCI_CHIP_65554, CHIPS_CT65554), + CHIPS_DEVICE_MATCH(PCI_CHIP_65555, CHIPS_CT65555), + CHIPS_DEVICE_MATCH(PCI_CHIP_68554, CHIPS_CT68554), + CHIPS_DEVICE_MATCH(PCI_CHIP_69000, CHIPS_CT69000), + CHIPS_DEVICE_MATCH(PCI_CHIP_69030, CHIPS_CT69030), + { 0, 0, 0 }, +}; +#endif + +/* + * 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. + */ + +_X_EXPORT DriverRec CHIPS = { + CHIPS_VERSION, + CHIPS_DRIVER_NAME, + CHIPSIdentify, +#ifdef XSERVER_LIBPCIACCESS + NULL, +#else + CHIPSProbe, +#endif + CHIPSAvailableOptions, + NULL, + 0, + NULL, + +#ifdef XSERVER_LIBPCIACCESS + chips_device_match, + CHIPSPciProbe, +#endif +}; + +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} +}; + + +/* 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, "Stretch", 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, "Stretch", 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 } +}; + +#ifdef XFree86LOADER + +static MODULESETUPPROTO(chipsSetup); + +static XF86ModuleVersionInfo chipsVersRec = +{ + "chips", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XORG_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 + */ +_X_EXPORT 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, HaveDriverFuncs); + + /* + * Modules that this driver always requires can be loaded here + * by calling LoadSubModule(). + */ + + /* + * 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 = XNFcallocarray(sizeof(CHIPSRec), 1); + + if (pScrn->driverPrivate == NULL) + return FALSE; + + return TRUE; +} + +static void +CHIPSFreeRec(ScrnInfoPtr pScrn) +{ + if (pScrn->driverPrivate == NULL) + return; + free(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_PCI) { + if ((chip >= CHIPS_CT65550) && (chip <= CHIPS_CT69030)) + return ChipsHiQVOptions; + } + return Chips655xxOptions; +} + +/* Mandatory */ +#ifdef XSERVER_LIBPCIACCESS +Bool +CHIPSPciProbe(DriverPtr drv, int entity_num, struct pci_device * dev, + intptr_t match_data) +{ + ScrnInfoPtr pScrn = NULL; + CHIPSPtr cPtr; + + /* Allocate a ScrnInfoRec and claim the slot */ + pScrn = xf86ConfigPciEntity(pScrn, 0, entity_num, CHIPSPCIchipsets, NULL, + NULL, NULL, NULL, NULL); + if (pScrn != NULL) { + /* Fill in what we can of the ScrnInfoRec */ + pScrn->driverVersion = CHIPS_VERSION; + pScrn->driverName = CHIPS_DRIVER_NAME; + pScrn->name = CHIPS_NAME; + pScrn->Probe = NULL; + pScrn->PreInit = CHIPSPreInit; + pScrn->ScreenInit = CHIPSScreenInit; + pScrn->SwitchMode = CHIPSSwitchMode; + pScrn->AdjustFrame = CHIPSAdjustFrame; + pScrn->EnterVT = CHIPSEnterVT; + pScrn->LeaveVT = CHIPSLeaveVT; + pScrn->FreeScreen = CHIPSFreeScreen; + pScrn->ValidMode = CHIPSValidMode; + + if (!CHIPSGetRec(pScrn)) { + return FALSE; + } + cPtr = CHIPSPTR(pScrn); + cPtr->Chipset = match_data; + /* + * For cards that can do dual head per entity, mark the entity + * as shareable. + */ + if (match_data == CHIPS_CT69030) { + CHIPSEntPtr cPtrEnt = NULL; + DevUnion *pPriv; + + xf86SetEntitySharable(entity_num); + /* Allocate an entity private if necessary */ + if (CHIPSEntityIndex < 0) + CHIPSEntityIndex = xf86AllocateEntityPrivateIndex(); + pPriv = xf86GetEntityPrivate(pScrn->entityList[0], CHIPSEntityIndex); + if (!pPriv->ptr) { + pPriv->ptr = XNFcallocarray(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); + } + } + + return (pScrn != NULL); +} +#else +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 = CHIPS_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 shareable. + */ + 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 = XNFcallocarray(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); + } + + } + free(usedChips); + } + } + + + free(devSections); + return foundScreen; +} +#endif + + +/* 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; + + /* 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; inumEntities; i++) { + cPtr->pEnt = xf86GetEntityInfo(pScrn->entityList[i]); +#ifndef XSERVER_LIBPCIACCESS + if (cPtr->pEnt->resources) return FALSE; +#endif + /* If we are using libpciaccess this is already set in CHIPSPciProbe. + * If we are using something else we need to set it here. + */ + if (!cPtr->Chipset) + 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; +#ifndef XSERVER_LIBPCIACCESS + cPtr->PciTag = pciTag(cPtr->PciInfo->bus, + cPtr->PciInfo->device, + cPtr->PciInfo->func); +#endif + } + } + /* INT10 */ +#if 0 + if (xf86LoadSubModule(pScrn, "int10")) { + xf86Int10InfoPtr pInt; +#if 1 + xf86DrvMsg(pScrn->scrnIndex,X_INFO,"initializing int10\n"); + pInt = xf86InitInt10(cPtr->pEnt->index); + xf86FreeInt10(pInt); +#endif + } +#endif + + if (xf86LoadSubModule(pScrn, "vbe")) { + 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 = XNFcallocarray(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) { + default: + if (xf86LoadSubModule(pScrn, "fb") == NULL) { + vbeFree(cPtr->pVbe); + cPtr->pVbe = NULL; + CHIPSFreeRec(pScrn); + return FALSE; + } + break; + } + + if (!xf86LoadSubModule(pScrn, "exa")) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Falling back to shadowfb\n"); + cPtr->Flags &= ~(ChipsAccelSupport); + cPtr->Flags |= ChipsShadowFB; + } + + if (cPtr->Flags & ChipsShadowFB) { + if (!xf86LoadSubModule(pScrn, "shadowfb")) { + vbeFree(cPtr->pVbe); + cPtr->pVbe = NULL; + CHIPSFreeRec(pScrn); + return FALSE; + } + } + + if (cPtr->Accel.UseHWCursor) { + if (!xf86LoadSubModule(pScrn, "ramdac")) { + vbeFree(cPtr->pVbe); + cPtr->pVbe = NULL; + CHIPSFreeRec(pScrn); + return FALSE; + } + } + +#ifndef XSERVER_LIBPCIACCESS + if (cPtr->Flags & ChipsLinearSupport) + xf86SetOperatingState(resVgaMem, cPtr->pEnt->index, ResDisableOpr); + + if (cPtr->MMIOBaseVGA) + xf86SetOperatingState(resVgaIo, cPtr->pEnt->index, ResDisableOpr); +#endif + + 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); +#ifndef XSERVER_LIBPCIACCESS + resRange linearRes[] = { {ResExcMemBlock|ResBios|ResBus,0,0},_END }; +#endif + + /* Set pScrn->monitor */ + pScrn->monitor = pScrn->confScreen->monitor; + + /* All HiQV chips support 16/24/32 bpp, default to 16bpp for speed & vram */ + if (!xf86SetDepthBpp(pScrn, 16, 0, 0, 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); +#if defined(__arm__) + vgaHWSetMmioFuncs(hwp, (CARD8 *)IOPortBase, 0); +#elif defined(__powerpc__) + vgaHWSetMmioFuncs(hwp, ioBase, 0); +#else + vgaHWSetStdFuncs(hwp); +#endif + vgaHWGetIOBase(hwp); +#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12 + cPtr->PIOBase = hwp->PIOOffset; +#else + cPtr->PIOBase = 0; +#endif + + /* + * 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 = malloc(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; + } + + if (!(cPtr->Flags & ChipsLinearSupport)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Linear framebuffer required\n"); + return FALSE; + } + + /* 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 + if (BE_SWAP_APRETURE(pScrn,cPtr)) + cPtr->FbAddress = (PCI_REGION_BASE(cPtr->PciInfo, 0, REGION_MEM) & 0xff800000) + 0x800000L; + else +#endif + cPtr->FbAddress = PCI_REGION_BASE(cPtr->PciInfo, 0, REGION_MEM) & 0xff800000; + + from = X_PROBED; +#ifndef XSERVER_LIBPCIACCESS + if (xf86RegisterResources(cPtr->pEnt->index,NULL,ResNone)) + cPtr->Flags &= ~ChipsLinearSupport; +#endif + } 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; + } +#ifndef XSERVER_LIBPCIACCESS + linearRes[0].rBegin = cPtr->FbAddress; + linearRes[0].rEnd = cPtr->FbAddress + 0x800000; + if (xf86RegisterResources(cPtr->pEnt->index,linearRes,ResNone)) { + cPtr->Flags &= ~ChipsLinearSupport; + from = X_PROBED; + } +#endif + } + } + if (cPtr->Flags & ChipsLinearSupport) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Enabling linear addressing\n"); + xf86DrvMsg(pScrn->scrnIndex, from, + "base address is set at 0x%lX.\n", cPtr->FbAddress); +#if X_BYTE_ORDER == X_BIG_ENDIAN + if (BE_SWAP_APRETURE(pScrn,cPtr)) + cPtr->IOAddress = cPtr->FbAddress - 0x400000L; + else +#endif + cPtr->IOAddress = cPtr->FbAddress + 0x400000L; + xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, + "IOAddress is set at 0x%lX.\n",(unsigned long)cPtr->IOAddress); + + } 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(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; + cPtr->Flags |= Chips64BitMemory; + break; + case CHIPS_CT69000: + /* The ct69000 has 2Mb of SGRAM integrated */ + pScrn->videoRam = 2048; + cPtr->Flags |= Chips64BitMemory; + 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; + } + /* XR43: DRAM interface */ + /* bit 4-5 mem interface width */ + /* 00: 32Bit */ + /* 01: 64Bit */ + tmp = cPtr->readXR(cPtr, 0x43); + if ((tmp & 0x10) == 0x10) + cPtr->Flags |= Chips64BitMemory; + break; + } + } + +#if X_BYTE_ORDER == X_BIG_ENDIAN + if (cPtr->pEnt->chipset == CHIPS_CT69030 && ((cPtr->readXR(cPtr, 0x71) & 0x2)) == 0) /* CFG9: Pipeline variable ByteSwap mapping */ + cPtr->dualEndianAp = TRUE; + else /* CFG9: Pipeline A/B mapping */ + cPtr->dualEndianAp = FALSE; +#endif + + if ((cPtr->Flags & ChipsDualChannelSupport) && + (xf86IsEntityShared(pScrn->entityList[0]))) { + /* + * This takes gives either half or the amount of memory specified + * with the Crt2Memory option + */ + pScrn->memPhysBase = cPtr->FbAddress; + + 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; + pScrn->fbOffset = 0; + } else { + cPtrEnt->slaveFbAddress = cPtr->FbAddress + + cPtrEnt->masterFbMapSize; + cPtr->FbMapSize = cPtrEnt->slaveFbMapSize; + pScrn->videoRam = cPtrEnt->slavevideoRam; + pScrn->fbOffset = cPtrEnt->masterFbMapSize; + } + + 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; + + if (cPtr->pVbe) { + if ((pMon + = xf86PrintEDID(vbeDoEDID(cPtr->pVbe, pVbeModule))) != NULL) { + ddc_done = TRUE; + xf86SetDDCproperties(pScrn,pMon); + } + } + + if (!ddc_done) + if (xf86LoadSubModule(pScrn, "i2c")) { + if (chips_i2cInit(pScrn)) { + if ((pMon = xf86PrintEDID(xf86DoEDID_DDC2(XF86_SCRN_ARG(pScrn), + 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; + + 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 opportunity 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/max pixel clock */ + switch (cPtr->Chipset) { + case CHIPS_CT69030: + cPtr->MinClock = 3000; + cPtr->MaxClock = 170000; + break; + case CHIPS_CT69000: + cPtr->MinClock = 3000; + cPtr->MaxClock = 135000; + break; + case CHIPS_CT68554: + case CHIPS_CT65555: + cPtr->MinClock = 1000; + cPtr->MaxClock = 110000; + break; + case CHIPS_CT65554: + cPtr->MinClock = 1000; + cPtr->MaxClock = 95000; + break; + case CHIPS_CT65550: + cPtr->MinClock = 1000; + 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; + } + xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock is %7.3f MHz\n", + (float)(cPtr->MinClock / 1000.)); + + /* 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 */ + /* If flag Chips64BitMemory is set assume a 64bitmemory interface, */ + /* and 32bits on the others. Thus multiply by a suitable factor */ + if (cPtr->Flags & Chips64BitMemory) { + if (cPtr->FrameBufferSize && (cPtr->PanelType & ChipsLCD)) + cPtr->MaxClock = min(cPtr->MaxClock, + MemClk->Clk * 8 * 0.7 / (bytesPerPixel + 1)); + else + cPtr->MaxClock = min(cPtr->MaxClock, + MemClk->Clk * 8 * 0.7 / bytesPerPixel); + } else { + if (cPtr->FrameBufferSize && (cPtr->PanelType & ChipsLCD)) + cPtr->MaxClock = min(cPtr->MaxClock, + MemClk->Clk * 4 * 0.7 / (bytesPerPixel + 1)); + 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(__arm__) && 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; + const char *s; +#ifndef XSERVER_LIBPCIACCESS + resRange linearRes[] = { {ResExcMemBlock|ResBios|ResBus,0,0},_END }; +#endif + + /* Set pScrn->monitor */ + pScrn->monitor = pScrn->confScreen->monitor; + + if (cPtr->Flags & ChipsHDepthSupport) + i = xf86SetDepthBpp(pScrn, 0, 0, 0, Support24bppFb | + SupportConvert32to24 | PreferConvert32to24); + else + i = xf86SetDepthBpp(pScrn, 8, 0, 0, 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); + vgaHWSetStdFuncs(hwp); + 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 = malloc(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; + } + + if (!(cPtr->Flags & ChipsLinearSupport)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Linear framebuffer required\n"); + return FALSE; + } + + /* 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; + } +#ifndef XSERVER_LIBPCIACCESS + linearRes[0].rBegin = cPtr->FbAddress; + linearRes[0].rEnd = cPtr->FbAddress + 0x800000; + if (xf86RegisterResources(cPtr->pEnt->index,linearRes,ResNone)) { + useLinear = FALSE; + from = X_PROBED; + } +#endif + } + + if (useLinear) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Enabling linear addressing\n"); + xf86DrvMsg(pScrn->scrnIndex, from, + "base address is set at 0x%lX.\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 + } +#ifndef XSERVER_LIBPCIACCESS + 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"); + } + } +#endif + } + + 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; + 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")) { + 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; + const char *s; +#ifndef XSERVER_LIBPCIACCESS + resRange linearRes[] = { {ResExcMemBlock|ResBios|ResBus,0,0},_END }; +#endif + + /* Set pScrn->monitor */ + pScrn->monitor = pScrn->confScreen->monitor; + + if (cPtr->Flags & ChipsHDepthSupport) + i = xf86SetDepthBpp(pScrn, 0, 0, 0, Support24bppFb | + SupportConvert32to24 | PreferConvert32to24); + else + i = xf86SetDepthBpp(pScrn, 8, 0, 0, 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); + vgaHWSetStdFuncs(hwp); + 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 = malloc(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; + } + + if (!(cPtr->Flags & ChipsLinearSupport)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Linear framebuffer required\n"); + return FALSE; + } + + /* 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 = PCI_REGION_BASE(cPtr->PciInfo, 0, REGION_MEM) & 0xff800000; +#ifndef XSERVER_LIBPCIACCESS + if (xf86RegisterResources(cPtr->pEnt->index,NULL,ResNone)) { + useLinear = FALSE; + from = X_PROBED; + } +#endif + } 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; + } +#ifndef XSERVER_LIBPCIACCESS + linearRes[0].rBegin = cPtr->FbAddress; + linearRes[0].rEnd = cPtr->FbAddress + 0x800000; + if (xf86RegisterResources(cPtr->pEnt->index,linearRes,ResNone)) { + useLinear = FALSE; + from = X_PROBED; + } +#endif + } + } + + if (useLinear) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Enabling linear addressing\n"); + xf86DrvMsg(pScrn->scrnIndex, from, + "base address is set at 0x%lX.\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 & 0x080u) ? (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 + } +#ifndef XSERVER_LIBPCIACCESS + 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"); + } + } +#endif + } + + /* 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; + 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")) { + if (cPtr->pVbe) + xf86SetDDCproperties(pScrn,xf86PrintEDID(vbeDoEDID(cPtr->pVbe, NULL))); + } + return TRUE; +} + + +/* Mandatory */ +static Bool +CHIPSEnterVT(VT_FUNC_ARGS_DECL) +{ + SCRN_INFO_PTR(arg); + 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 & ChipsVideoSupport) + && (cPtr->Flags & ChipsLinearSupport)) + CHIPSResetVideo(pScrn); + + /*usleep(50000);*/ + chipsHWCursorOn(cPtr, pScrn); + /* cursor settle delay */ + usleep(50000); + CHIPSAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); + usleep(50000); + return TRUE; +} + +/* Mandatory */ +static void +CHIPSLeaveVT(VT_FUNC_ARGS_DECL) +{ + SCRN_INFO_PTR(arg); + 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, +#ifdef AVOID_VGAHW + FALSE); +#else + TRUE); +#endif + 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) ? 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(SCREEN_INIT_ARGS_DECL) +{ + ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + vgaHWPtr hwp; + CHIPSPtr cPtr; + CHIPSACLPtr cAcl; + int ret; + int init_picture = 0; + VisualPtr visual; + int allocatebase, freespace, currentaddr; +#ifndef XSERVER_LIBPCIACCESS + unsigned int racflag = 0; +#endif + 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 */ + +#ifndef AVOID_VGAHW + /* Map the VGA memory */ + if (!vgaHWMapMem(pScrn)) + return FALSE; +#endif + + /* Map the Chips memory and possible MMIO areas */ + if (!chipsMapMem(pScrn)) + return FALSE; + + /* 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(__arm__) && 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(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); + + /* + * 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 (!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 = malloc(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 16: + default: + ret = fbScreenInit(pScreen, FBStart, + width,height, + pScrn->xDpi, pScrn->yDpi, + displayWidth,pScrn->bitsPerPixel); + init_picture = 1; + break; + } + + if (!ret) + return FALSE; + +#if X_BYTE_ORDER == X_BIG_ENDIAN + /* TODO : find a better way to do this */ + if (pScrn->depth == 24) { + int dummy ; + /* Fixup RGB ordering in 24 BPP */ + dummy = pScrn->offset.red ; + pScrn->offset.red = pScrn->offset.blue; + pScrn->offset.blue = dummy ; + + dummy = pScrn->mask.red ; + pScrn->mask.red = pScrn->mask.blue; + pScrn->mask.blue = dummy ; + } +#endif + + 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; + +#ifdef USE_MIBANK + if (!(cPtr->Flags & ChipsLinearSupport)) { + miBankInfoPtr pBankInfo; + + /* Setup the vga banking variables */ + pBankInfo = (miBankInfoPtr)XNFcallocarray(sizeof(miBankInfoRec),1); + if (pBankInfo == NULL) + return FALSE; + +#if defined(__arm__) + 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)) { + free(pBankInfo); + pBankInfo = NULL; + return FALSE; + } + xf86SetBackingStore(pScreen); + + /* Initialise cursor functions */ + miDCInitialize (pScreen, xf86GetPointerScreenFuncs()); + + } else +#endif /* USE_MIBANK */ + { + /* !!! 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 + 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(pScrn->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(pScrn->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(pScrn->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)); + + xf86InitFBManager(pScreen, &AvailFBArea); + } + + if (cPtr->Flags & ChipsAccelSupport) { + if (IS_HiQV(cPtr)) { + CHIPSInitEXA(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(pScrn->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(!xf86HandleColormaps(pScreen, 256, pScrn->rgbBits, + (pScrn->depth == 16 ? chipsLoadPalette16 : chipsLoadPalette), + NULL, CMAP_RELOAD_ON_MODE_SWITCH | CMAP_PALETTED_TRUECOLOR)) + return FALSE; + +#ifndef XSERVER_LIBPCIACCESS + 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; +#endif +#ifdef ENABLE_SILKEN_MOUSE + xf86SetSilkenMouse(pScreen); +#endif + + if ((cPtr->Flags & ChipsVideoSupport) + && (cPtr->Flags & ChipsLinearSupport)) { + CHIPSInitVideo(pScreen); + } + + pScreen->SaveScreen = CHIPSSaveScreen; + + /* Setup DPMS mode */ + if (cPtr->Flags & ChipsDPMSSupport) + xf86DPMSInit(pScreen, (DPMSSetProcPtr)chipsDisplayPowerManagementSet, + 0); + + /* 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(SWITCH_MODE_ARGS_DECL) +{ + SCRN_INFO_PTR(arg); + 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(pScrn, mode); +} + +/* Mandatory */ +void +CHIPSAdjustFrame(ADJUST_FRAME_ARGS_DECL) +{ + SCRN_INFO_PTR(arg); + 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: + Base >>= 1; + 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); + } + +} + +/* Mandatory */ +static Bool +CHIPSCloseScreen(CLOSE_SCREEN_ARGS_DECL) +{ + ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + 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->CursorInfoRec) + xf86DestroyCursorInfoRec(cPtr->CursorInfoRec); + free(cPtr->ShadowPtr); + free(cPtr->DGAModes); + pScrn->vtSema = FALSE; + if(cPtr->BlockHandler) + pScreen->BlockHandler = cPtr->BlockHandler; + + pScreen->CloseScreen = cPtr->CloseScreen; /*§§§*/ + xf86ClearPrimInitDone(pScrn->entityList[0]); + return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS);/*§§§*/ +} + +/* Optional */ +static void +CHIPSFreeScreen(FREE_SCREEN_ARGS_DECL) +{ + SCRN_INFO_PTR(arg); + if (xf86LoaderCheckSymbol("vgaHWFreeHWRec")) + vgaHWFreeHWRec(pScrn); + CHIPSFreeRec(pScrn); +} + +/* Optional */ +static ModeStatus +CHIPSValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags) +{ + SCRN_INFO_PTR(arg); + CHIPSPtr cPtr = CHIPSPTR(pScrn); + + /* The tests here need to be expanded */ + if ((mode->Flags & V_INTERLACE) && (cPtr->PanelType & ChipsLCD)) + return MODE_NO_INTERLACE; + if ((cPtr->PanelType & ChipsLCD) + && !xf86ReturnOptValBool(cPtr->Options, OPTION_PANEL_SIZE, FALSE) + && ((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; + +#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 8 + xf86EnableAccess(pScrn); +#endif + 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 = xf86ScreenToScrn(pScreen); + + 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, NULL, 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, DisplayModePtr mode, + 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 = mode ? mode->Clock : 0; + if (xf86ReturnOptValBool(cPtr->Options, OPTION_USE_MODELINE, FALSE)) { + Clock->FPClock = mode ? mode->Clock : 0; + } 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 = mode ? mode->SynthClock : 0; + } + 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 = mode ? mode->SynthClock : 0; + } + 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 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 abest = 42; +#ifdef DEBUG + double bestFout = 0; +#endif + 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; + bestM = M; + bestN = N; + bestP = P; + bestPSN = PSN; +#ifdef DEBUG + bestFout = Fout; +#endif + } + } + } + } + } + /* @@@ >= 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 */ + +#ifdef AVOID_VGAHW + vgaHWSave(pScrn, VgaSave, VGA_SR_CMAP | VGA_SR_MODE); +#else + vgaHWSave(pScrn, VgaSave, VGA_SR_ALL); +#endif + + /* 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 performance 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 separate + * 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, 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 */ + } + 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) { + 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; + +#if X_BYTE_ORDER == X_BIG_ENDIAN + ChipsNew->XR[0x0A] &= 0xCF; + if (pScrn->bitsPerPixel == 16) { + if (!cPtr->dualEndianAp) + ChipsNew->XR[0x0A] |= 0x10; + } +#endif + 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; + ChipsNew->CR[0x3C] = vgaHWHBlankKGA(mode, ChipsStd, 8, 0) << 6; + } 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)) { + 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, TRUE)) { + 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((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) { + 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(__arm__) && 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 (!xf86ReturnOptValBool(cPtr->Options, OPTION_LCD_STRETCH, FALSE) + && xf86ReturnOptValBool(cPtr->Options, OPTION_LCD_CENTER, TRUE)) + { + 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 0 + if (mode->CrtcHDisplay == 1024) + cPtr->OverlaySkewY += 5; + else if (mode->CrtcHDisplay == 1280) +#endif + 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; + + 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 chosen 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, 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 chosen 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, 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 auto h-centering */ + else { + ChipsNew->XR[0x55] &= 0xFD; /* disable auto h-centering */ + 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 empirically 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] |= 0x04; + else + ChipsNew->XR[0x51] &= ~0x04; + + /* 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 -- re-enable */ + /* 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 -- re-enable */ + /* 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 synchronous 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 & 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)) { +#ifndef XSERVER_LIBPCIACCESS + if (cPtr->pEnt->location.type == BUS_PCI) + 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 + { + void** result = (void**)&cPtr->MMIOBase; + int err = pci_device_map_range(cPtr->PciInfo, + cPtr->IOAddress, + 0x20000L, + PCI_DEV_MAP_FLAG_WRITABLE, + result); + if (err) + return FALSE; + } +#endif + } else { +#ifndef XSERVER_LIBPCIACCESS + if (cPtr->pEnt->location.type == BUS_PCI) + 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); +#else + { + void** result = (void**)&cPtr->MMIOBase; + int err = pci_device_map_range(cPtr->PciInfo, + cPtr->IOAddress, + 0x10000L, + PCI_DEV_MAP_FLAG_WRITABLE, + result); + if (err) + return FALSE; + } +#endif + } + + 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; + } + } + +#ifndef XSERVER_LIBPCIACCESS + if (cPtr->pEnt->location.type == BUS_PCI) + cPtr->FbBase = xf86MapPciMem(pScrn->scrnIndex,VIDMEM_FRAMEBUFFER, + cPtr->PciTag, Addr, Map); + + else + cPtr->FbBase = xf86MapVidMem(pScrn->scrnIndex,VIDMEM_FRAMEBUFFER, + Addr, Map); +#else + { + void** result = (void**)&cPtr->FbBase; + int err = pci_device_map_range(cPtr->PciInfo, + Addr, + Map, + PCI_DEV_MAP_FLAG_WRITABLE | + PCI_DEV_MAP_FLAG_WRITE_COMBINE, + result); + if (err) + return FALSE; + } + +#endif + + if (cPtr->FbBase == NULL) + return FALSE; + } + if (cPtr->Flags & ChipsFullMMIOSupport) { +#ifndef XSERVER_LIBPCIACCESS + cPtr->MMIOBaseVGA = xf86MapPciMem(pScrn->scrnIndex, + VIDMEM_MMIO,cPtr->PciTag, + cPtr->IOAddress, 0x2000L); +#else + cPtr->MMIOBaseVGA = cPtr->MMIOBase; +#endif + /* 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) +#ifndef XSERVER_LIBPCIACCESS + cPtr->MMIOBasePipeB = xf86MapPciMem(pScrn->scrnIndex, + VIDMEM_MMIO,cPtr->PciTag, + cPtr->IOAddress + 0x800000, 0x2000L); +#else + { + void** result = (void**)&cPtr->MMIOBasePipeB; + int err = pci_device_map_range(cPtr->PciInfo, + cPtr->IOAddress + 0x800000, + 0x2000L, + PCI_DEV_MAP_FLAG_WRITABLE, + result); + if (err) + return FALSE; + } +#endif + + 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)) { +#ifndef XSERVER_LIBPCIACCESS + if (cPtr->MMIOBase) + xf86UnMapVidMem(pScrn->scrnIndex, (pointer)cPtr->MMIOBase, + 0x20000); + if (cPtr->MMIOBasePipeB) + xf86UnMapVidMem(pScrn->scrnIndex, (pointer)cPtr->MMIOBasePipeB, + 0x20000); +#else + if (cPtr->MMIOBase) + pci_device_unmap_range(cPtr->PciInfo, cPtr->MMIOBase, 0x20000); + + if (cPtr->MMIOBasePipeB) + pci_device_unmap_range(cPtr->PciInfo, cPtr->MMIOBasePipeB, 0x2000); + +#endif + cPtr->MMIOBasePipeB = NULL; + } else { +#ifndef XSERVER_LIBPCIACCESS + if (cPtr->MMIOBase) + xf86UnMapVidMem(pScrn->scrnIndex, (pointer)cPtr->MMIOBase, + 0x10000); +#else + if (cPtr->MMIOBase) + pci_device_unmap_range(cPtr->PciInfo, cPtr->MMIOBase, 0x10000); +#endif + } + cPtr->MMIOBase = NULL; +#ifndef XSERVER_LIBPCIACCESS + xf86UnMapVidMem(pScrn->scrnIndex, (pointer)cPtr->FbBase, + cPtr->FbMapSize); +#else + pci_device_unmap_range(cPtr->PciInfo, cPtr->FbBase, cPtr->FbMapSize); +#endif + } + 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 | ChipsLCDProbed; + } + 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 (BLOCKHANDLER_ARGS_DECL) +{ + SCREEN_PTR(arg); + ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + CHIPSPtr cPtr = CHIPSPTR(pScrn); + + pScreen->BlockHandler = cPtr->BlockHandler; + (*pScreen->BlockHandler) (BLOCKHANDLER_ARGS); + pScreen->BlockHandler = chipsBlockHandler; + + if(cPtr->VideoTimerCallback) { + UpdateCurrentTime(); + (*cPtr->VideoTimerCallback)(pScrn, currentTime.milliseconds); + } +} diff --git a/hw/xfree86/drivers/video/chips/src/ct_driver.h b/hw/xfree86/drivers/video/chips/src/ct_driver.h new file mode 100644 index 0000000000..980c6f749a --- /dev/null +++ b/hw/xfree86/drivers/video/chips/src/ct_driver.h @@ -0,0 +1,565 @@ +/* + * Modified 1996 by Egbert Eich + * Modified 1996 by David Bateman + * + * 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. + */ + + + +#ifndef _CT_DRIVER_H_ +#define _CT_DRIVER_H_ + +#include "config.h" +#include "ct_pcirename.h" +#include "exa.h" +#include "vbe.h" +#include "xf86Cursor.h" +#include "xf86i2c.h" +#include "xf86DDC.h" +#include "xf86xv.h" +#include "vgaHW.h" +#include +#include + +#include "compat-api.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 +#define Chips64BitMemory 0x00000800 + +/* Options flags for the C&T chipsets */ +#define ChipsHWCursor 0x00001000 +#define ChipsShadowFB 0x00002000 +#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; + int srcpitch, srcoffset, xdir, ydir; + /* 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; +#ifndef XSERVER_LIBPCIACCESS + PCITAG PciTag; +#endif + int Chipset; + EntityInfoPtr pEnt; + unsigned long PIOBase; + unsigned long 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)(SCRN_ARG_TYPE arg, 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; + ExaDriverPtr pExa; + 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 __arm__ +#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; + Bool dualEndianAp; +} 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(ADJUST_FRAME_ARGS_DECL); +Bool CHIPSSwitchMode(SWITCH_MODE_ARGS_DECL); + +/* 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); +Bool CHIPSInitEXA(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(SCRN_ARG_TYPE arg, int x, int y); + +#if X_BYTE_ORDER == X_BIG_ENDIAN +# define BE_SWAP_APRETURE(pScrn,cPtr) \ + ((pScrn->bitsPerPixel == 16) && cPtr->dualEndianAp) +#endif + +/* + * 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/hw/xfree86/drivers/video/chips/src/ct_exa.c b/hw/xfree86/drivers/video/chips/src/ct_exa.c new file mode 100644 index 0000000000..8fe2cf6925 --- /dev/null +++ b/hw/xfree86/drivers/video/chips/src/ct_exa.c @@ -0,0 +1,329 @@ +/* + * EXA acceleration for now ct65550 only, for lack of other hardware + * + * Copyright (C) 2016 Michael Lorenz + * + * 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 + * MICHAEL LORENZ 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. + */ + +/* $NetBSD: ct_exa.c,v 1.3 2017/02/16 15:05:57 macallan Exp $ */ + +#include + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* All drivers should typically include these */ +#include "xf86.h" +#include "xf86_OSproc.h" + +/* Everything using inb/outb, etc needs "compiler.h" */ +#include "compiler.h" + +#include "ct_driver.h" +#include "ct_BltHiQV.h" + + +#ifdef DEBUG +#define ENTER xf86Msg(X_ERROR, "%s\n", __func__) +#define LEAVE xf86Msg(X_ERROR, "%s done\n", __func__) +int last_op = 0, lx, ly, lw, lh, dx, dy, xdir, ydir, lsp, ldp; +#else +#define ENTER +#define LEAVE +#endif + +static void +ctWaitMarker(ScreenPtr pScreen, int Marker) +{ + ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + CHIPSPtr cPtr = CHIPSPTR(pScrn); + ENTER; + ctBLTWAIT; +} + +static int +ctMarkSync(ScreenPtr pScreenInfo) +{ + ENTER; + return 0; +} + +static Bool +ctPrepareCopy +( + PixmapPtr pSrcPixmap, + PixmapPtr pDstPixmap, + int xdir, + int ydir, + int alu, + Pixel planemask +) +{ + ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSACLPtr cAcl = CHIPSACLPTR(pScrn); + + ENTER; + ctBLTWAIT; + cAcl->srcpitch = exaGetPixmapPitch(pSrcPixmap); + cAcl->srcoffset = exaGetPixmapOffset(pSrcPixmap); + cAcl->xdir = xdir; + cAcl->ydir = ydir; + ctSETROP(ChipsAluConv[alu & 0xF] | ((xdir < 0) ? ctRIGHT2LEFT : 0) | + ((ydir < 0) ? ctBOTTOM2TOP : 0) | + ctPATSOLID/* | ctPATMONO*/); + ctSETMONOCTL(ctDWORDALIGN); + ctSETPITCH(cAcl->srcpitch, exaGetPixmapPitch(pDstPixmap)); + LEAVE; + return TRUE; +} + +static void +ctCopy +( + PixmapPtr pDstPixmap, + int srcX, + int srcY, + int dstX, + int dstY, + int w, + int h +) +{ + ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSACLPtr cAcl = CHIPSACLPTR(pScrn); + int src = cAcl->srcoffset; + int dst = exaGetPixmapOffset(pDstPixmap); + int dstpitch = exaGetPixmapPitch(pDstPixmap); + + if (cAcl->ydir < 0) { + srcY += (h - 1); + dstY += (h - 1); + } + + if (cAcl->xdir < 0) { + srcX += (w - 1); + dstX += (w - 1); + } + + src += srcX * cAcl->BytesPerPixel + srcY * cAcl->srcpitch; + dst += dstX * cAcl->BytesPerPixel + dstY * dstpitch; + ctBLTWAIT; + ctSETSRCADDR(src); + ctSETDSTADDR(dst); + ctSETHEIGHTWIDTHGO(h, w * cAcl->BytesPerPixel); + LEAVE; +#ifdef DEBUG + last_op = 1; + lx = srcX; + ly = srcY; + lw = w; + lh = h; + dx = dstX; + dy = dstY; + xdir = cAcl->xdir; + ydir = cAcl->ydir; + lsp = cAcl->srcpitch; + ldp = dstpitch; +#endif +} + +static void +ctDoneCopy(PixmapPtr pDstPixmap) +{ + ENTER; + ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSACLPtr cAcl = CHIPSACLPTR(pScrn); + ctBLTWAIT; + LEAVE; +} + +static Bool +ctPrepareSolid( + PixmapPtr pPixmap, + int alu, + Pixel planemask, + Pixel fg) +{ + ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSACLPtr cAcl = CHIPSACLPTR(pScrn); + int pitch = exaGetPixmapPitch(pPixmap); + + ENTER; + ctBLTWAIT; + ctSETPITCH(pitch, pitch); + ctSETROP(ChipsAluConv2[alu & 0xF] | ctPATSOLID | ctPATMONO); + ctSETMONOCTL(ctDWORDALIGN); + ctSETBGCOLOR24(fg); + LEAVE; + return TRUE; +} + +static void +ctSolid( + PixmapPtr pPixmap, + int x1, + int y1, + int x2, + int y2) +{ + ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSACLPtr cAcl = CHIPSACLPTR(pScrn); + int dst = exaGetPixmapOffset(pPixmap); + + ENTER; + ctBLTWAIT; + dst += x1 * cAcl->BytesPerPixel + y1 * exaGetPixmapPitch(pPixmap); + ctSETDSTADDR(dst); + ctSETSRCADDR(dst); + ctSETHEIGHTWIDTHGO(y2 - y1, (x2 - x1) * cAcl->BytesPerPixel); + LEAVE; +#ifdef DEBUG + last_op = 2; +#endif +} + +/* + * Memcpy-based UTS. + */ +static Bool +ctUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, + char *src, int src_pitch) +{ + ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; + CHIPSPtr cPtr = CHIPSPTR(pScrn); + unsigned char *dst = cPtr->FbBase + exaGetPixmapOffset(pDst); + int dst_pitch = exaGetPixmapPitch(pDst); + + int bpp = pDst->drawable.bitsPerPixel; + int cpp = (bpp + 7) / 8; + int wBytes = w * cpp; + + ENTER; + ctBLTWAIT; + dst += (x * cpp) + (y * dst_pitch); + + while (h--) { + memcpy(dst, src, wBytes); + src += src_pitch; + dst += dst_pitch; + } + LEAVE; + return TRUE; +} + +/* + * Memcpy-based DFS. + */ +static Bool +ctDownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, + char *dst, int dst_pitch) +{ + ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum]; + CHIPSPtr cPtr = CHIPSPTR(pScrn); + unsigned char *src = cPtr->FbBase + exaGetPixmapOffset(pSrc); + int src_pitch = exaGetPixmapPitch(pSrc); + + int bpp = pSrc->drawable.bitsPerPixel; + int cpp = (bpp + 7) / 8; + int wBytes = w * cpp; + + ENTER; + ctBLTWAIT; + src += (x * cpp) + (y * src_pitch); + + while (h--) { + memcpy(dst, src, wBytes); + src += src_pitch; + dst += dst_pitch; + } + LEAVE; + return TRUE; +} + +Bool +CHIPSInitEXA(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + CHIPSPtr cPtr = CHIPSPTR(pScrn); + CHIPSACLPtr cAcl = CHIPSACLPTR(pScrn); + ExaDriverPtr pExa; + + pExa = exaDriverAlloc(); + if (!pExa) + return FALSE; + + cPtr->pExa = pExa; + +#if 0 + cPtr->writeXR(cPtr, 0x20, 0); /* XXX blitter in 8bit mode */ +#endif + + cAcl->BytesPerPixel = pScrn->bitsPerPixel >> 3; + cAcl->BitsPerPixel = pScrn->bitsPerPixel; + cAcl->planemask = -1; + cAcl->bgColor = -1; + cAcl->fgColor = -1; + cAcl->FbOffset = 0; + + pExa->exa_major = EXA_VERSION_MAJOR; + pExa->exa_minor = EXA_VERSION_MINOR; + + pExa->memoryBase = cPtr->FbBase; + pExa->offScreenBase = cAcl->CacheStart; + pExa->memorySize = cAcl->CacheEnd; + + /* + * Contrary to the manual, the blitter needs 8 byte pitch alignment or it + * will lock up. Probably shouldn't be surprised, there are hidden 64bit + * alignment requirements all over the place. + */ + pExa->pixmapOffsetAlign = 8; + pExa->pixmapPitchAlign = 8; + + pExa->flags = EXA_OFFSCREEN_PIXMAPS; + + /* entirely bogus since the chip doesn't use coordinates */ + pExa->maxX = 2048; + pExa->maxY = 2048; + + pExa->MarkSync = ctMarkSync; + pExa->WaitMarker = ctWaitMarker; + + pExa->PrepareSolid = ctPrepareSolid; + pExa->Solid = ctSolid; + pExa->DoneSolid = ctDoneCopy; + + pExa->PrepareCopy = ctPrepareCopy; + pExa->Copy = ctCopy; + pExa->DoneCopy = ctDoneCopy; + + /* EXA hits more optimized paths when it does not have to fallback because + * of missing UTS/DFS, hook memcpy-based UTS/DFS. + */ + pExa->UploadToScreen = ctUploadToScreen; + pExa->DownloadFromScreen = ctDownloadFromScreen; + + return exaDriverInit(pScreen, pExa); +} diff --git a/hw/xfree86/drivers/video/chips/src/ct_pcirename.h b/hw/xfree86/drivers/video/chips/src/ct_pcirename.h new file mode 100644 index 0000000000..f0f5cf8fb6 --- /dev/null +++ b/hw/xfree86/drivers/video/chips/src/ct_pcirename.h @@ -0,0 +1,122 @@ +/* + * Copyright 2007 George Sapountzis + * + * 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 (including the next + * paragraph) 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 + * THE AUTHORS OR COPYRIGHT HOLDERS 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. + */ + +/** + * Macros for porting drivers from legacy xfree86 PCI code to the pciaccess + * library. The main purpose being to facilitate source code compatibility. + */ + +#ifndef CIRPCIRENAME_H +#define CIRPCIRENAME_H + +enum region_type { + REGION_MEM, + REGION_IO +}; + +#ifndef XSERVER_LIBPCIACCESS + +/* pciVideoPtr */ +#define PCI_DEV_VENDOR_ID(_pcidev) ((_pcidev)->vendor) +#define PCI_DEV_DEVICE_ID(_pcidev) ((_pcidev)->chipType) +#define PCI_DEV_REVISION(_pcidev) ((_pcidev)->chipRev) + +#define PCI_SUB_VENDOR_ID(_pcidev) ((_pcidev)->subsysVendor) +#define PCI_SUB_DEVICE_ID(_pcidev) ((_pcidev)->subsysCard) + +#define PCI_DEV_TAG(_pcidev) pciTag((_pcidev)->bus, \ + (_pcidev)->device, \ + (_pcidev)->func) +#define PCI_DEV_BUS(_pcidev) ((_pcidev)->bus) +#define PCI_DEV_DEV(_pcidev) ((_pcidev)->device) +#define PCI_DEV_FUNC(_pcidev) ((_pcidev)->func) + +/* pciConfigPtr */ +#define PCI_CFG_TAG(_pcidev) (((pciConfigPtr)(_pcidev)->thisCard)->tag) +#define PCI_CFG_BUS(_pcidev) (((pciConfigPtr)(_pcidev)->thisCard)->busnum) +#define PCI_CFG_DEV(_pcidev) (((pciConfigPtr)(_pcidev)->thisCard)->devnum) +#define PCI_CFG_FUNC(_pcidev) (((pciConfigPtr)(_pcidev)->thisCard)->funcnum) + +/* region addr: xfree86 uses different fields for memory regions and I/O ports */ +#define PCI_REGION_BASE(_pcidev, _b, _type) \ + (((_type) == REGION_MEM) ? (_pcidev)->memBase[(_b)] \ + : (_pcidev)->ioBase[(_b)]) + +/* region size: xfree86 uses the log2 of the region size, + * but with zero meaning no region, not size of one XXX */ +#define PCI_REGION_SIZE(_pcidev, _b) \ + (((_pcidev)->size[(_b)] > 0) ? (1 << (_pcidev)->size[(_b)]) : 0) + +/* read/write PCI configuration space */ +#define PCI_READ_BYTE(_pcidev, _value_ptr, _offset) \ + *(_value_ptr) = pciReadByte(PCI_CFG_TAG(_pcidev), (_offset)) + +#define PCI_READ_LONG(_pcidev, _value_ptr, _offset) \ + *(_value_ptr) = pciReadLong(PCI_CFG_TAG(_pcidev), (_offset)) + +#define PCI_WRITE_LONG(_pcidev, _value, _offset) \ + pciWriteLong(PCI_CFG_TAG(_pcidev), (_offset), (_value)) + +#else /* XSERVER_LIBPCIACCESS */ + +typedef struct pci_device *pciVideoPtr; + +#define PCI_DEV_VENDOR_ID(_pcidev) ((_pcidev)->vendor_id) +#define PCI_DEV_DEVICE_ID(_pcidev) ((_pcidev)->device_id) +#define PCI_DEV_REVISION(_pcidev) ((_pcidev)->revision) + +#define PCI_SUB_VENDOR_ID(_pcidev) ((_pcidev)->subvendor_id) +#define PCI_SUB_DEVICE_ID(_pcidev) ((_pcidev)->subdevice_id) + +/* pci-rework functions take a 'pci_device' parameter instead of a tag */ +#define PCI_DEV_TAG(_pcidev) (_pcidev) + +/* PCI_DEV macros, typically used in printf's, add domain ? XXX */ +#define PCI_DEV_BUS(_pcidev) ((_pcidev)->bus) +#define PCI_DEV_DEV(_pcidev) ((_pcidev)->dev) +#define PCI_DEV_FUNC(_pcidev) ((_pcidev)->func) + +/* pci-rework functions take a 'pci_device' parameter instead of a tag */ +#define PCI_CFG_TAG(_pcidev) (_pcidev) + +/* PCI_CFG macros, typically used in DRI init, contain the domain */ +#define PCI_CFG_BUS(_pcidev) (((_pcidev)->domain << 8) | \ + (_pcidev)->bus) +#define PCI_CFG_DEV(_pcidev) ((_pcidev)->dev) +#define PCI_CFG_FUNC(_pcidev) ((_pcidev)->func) + +#define PCI_REGION_BASE(_pcidev, _b, _type) ((_pcidev)->regions[(_b)].base_addr) +#define PCI_REGION_SIZE(_pcidev, _b) ((_pcidev)->regions[(_b)].size) + +#define PCI_READ_BYTE(_pcidev, _value_ptr, _offset) \ + pci_device_cfg_read_u8((_pcidev), (_value_ptr), (_offset)) + +#define PCI_READ_LONG(_pcidev, _value_ptr, _offset) \ + pci_device_cfg_read_u32((_pcidev), (_value_ptr), (_offset)) + +#define PCI_WRITE_LONG(_pcidev, _value, _offset) \ + pci_device_cfg_write_u32((_pcidev), (_value), (_offset)) + +#endif /* XSERVER_LIBPCIACCESS */ + +#endif /* CIRPCIRENAME_H */ diff --git a/hw/xfree86/drivers/video/chips/src/ct_regs.c b/hw/xfree86/drivers/video/chips/src/ct_regs.c new file mode 100644 index 0000000000..5ae521f8d7 --- /dev/null +++ b/hw/xfree86/drivers/video/chips/src/ct_regs.c @@ -0,0 +1,523 @@ +/* + * Created 1998 by David Bateman + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* + * 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" + +/* Everything using inb/outb, etc needs "compiler.h" */ +#include "compiler.h" + +/* Drivers that need to access the PCI config space directly need this */ +#include "xf86Pci.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 + */ +static 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. + * + * 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) +{ + if (hwp->paletteEnabled) + index &= ~0x20; + else + index |= 0x20; + + if (hwp->IOBase == VGA_IOBASE_MONO) + (void) minb(CHIPS_MMIO_MONO_STAT_1); + else + (void) 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) +{ + if (hwp->paletteEnabled) + index &= ~0x20; + else + index |= 0x20; + + if (hwp->IOBase == VGA_IOBASE_MONO) + (void) minb(CHIPS_MMIO_MONO_STAT_1); + else + (void) 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) +{ + if (hwp->IOBase == VGA_IOBASE_MONO) + (void) minb(CHIPS_MMIO_MONO_STAT_1); + else + (void) minb(CHIPS_MMIO_COLOR_STAT_1); + moutb(CHIPS_MMIO_ATTR_INDEX, 0x00); + hwp->paletteEnabled = TRUE; +} + +static void +chipsMmioDisablePalette(vgaHWPtr hwp) +{ + if (hwp->IOBase == VGA_IOBASE_MONO) + (void) minb(CHIPS_MMIO_MONO_STAT_1); + else + (void) 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/hw/xfree86/drivers/video/chips/src/ct_shadow.c b/hw/xfree86/drivers/video/chips/src/ct_shadow.c new file mode 100644 index 0000000000..66b0ba7ccb --- /dev/null +++ b/hw/xfree86/drivers/video/chips/src/ct_shadow.c @@ -0,0 +1,243 @@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xf86.h" +#include "xf86_OSproc.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(SCRN_ARG_TYPE arg, int x, int y) +{ + SCRN_INFO_PTR(arg); + 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)(arg, 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/hw/xfree86/drivers/video/chips/src/ct_video.c b/hw/xfree86/drivers/video/chips/src/ct_video.c new file mode 100644 index 0000000000..22c20fb584 --- /dev/null +++ b/hw/xfree86/drivers/video/chips/src/ct_video.c @@ -0,0 +1,1033 @@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "compiler.h" +#include "xf86Pci.h" +#include "xf86fbman.h" +#include "regionstr.h" + +#include "ct_driver.h" +#include +#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) + +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, + DrawablePtr); +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 = xf86ScreenToScrn(pScreen); + XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL; + XF86VideoAdaptorPtr newAdaptor = NULL; + CHIPSPtr cPtr = CHIPSPTR(pScrn); + int num_adaptors; + + if ((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 */ + malloc((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); + + free(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; + + + 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 = xf86ScreenToScrn(pScreen); + CHIPSPtr cPtr = CHIPSPTR(pScrn); + XF86VideoAdaptorPtr adapt; + CHIPSPortPrivPtr pPriv; + + if(!(adapt = calloc(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->manualDoubleBuffer = FALSE; + pPriv->currentBuffer = 0; + + /* gotta uninit this someplace */ + REGION_NULL(pScreen, &pPriv->clip); + + cPtr->adaptor = adapt; + + xvColorKey = MAKE_ATOM("XV_COLORKEY"); + + CHIPSResetVideo(pScrn); + + return adapt; +} + + +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(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(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 = xf86ScrnToScreen(pScrn); + + new_linear = xf86AllocateOffscreenLinear(pScreen, size, 8, + NULL, NULL, NULL); + + if(!new_linear) { + int max_size; + + xf86QueryLargestOffscreenLinear(pScreen, &max_size, 8, + PRIORITY_EXTREME); + + if(max_size < size) + return NULL; + + xf86PurgeUnlockedOffscreenAreas(pScreen); + new_linear = xf86AllocateOffscreenLinear(pScreen, size, 8, + 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; + Bool dblscan = (pScrn->currentMode->Flags & V_DBLSCAN) == V_DBLSCAN; + int val; + + + 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 */ + val = cPtr->OverlaySkewY + (dstBox->y1 << (dblscan ? 1 : 0)); + cPtr->writeMR(cPtr, 0x2E, ((val) & 0xFF)); + tmp = cPtr->readMR(cPtr, 0x2F); + tmp = (tmp & 0xF8) + (((val) >> 8) & 0x07); + cPtr->writeMR(cPtr, 0x2F, tmp); + /* Bottom Edge of Overlay*/ + val = cPtr->OverlaySkewY + (dstBox->y2 << (dblscan ? 1 : 0)); + cPtr->writeMR(cPtr, 0x30, ((val - 1) & 0xFF)); + tmp = cPtr->readMR(cPtr, 0x31); + tmp = (tmp & 0xF8) + (((val - 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 || dblscan) { + m1f = m1f | 0x80; /* set V-interpolation */ + m1e = m1e | 0x08; + if (dblscan) + tmp = cPtr->VideoZoomMax >> 1; + if (drw_h > src_h) + tmp = 256 * src_h / drw_h; + cPtr->writeMR(cPtr, 0x33, tmp & 0xFC); + } + cPtr->writeMR(cPtr, 0x1F, m1f); + cPtr->writeMR(cPtr, 0x1E, m1e); + + tmp = cPtr->readMR(cPtr, 0x3C); + cPtr->writeMR(cPtr, 0x3C, (tmp | 0x7)); +} + +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, + DrawablePtr pDraw +){ + CHIPSPortPrivPtr pPriv = (CHIPSPortPrivPtr)data; + CHIPSPtr cPtr = CHIPSPTR(pScrn); + INT32 x1, x2, y1, y2; + unsigned char *dst_start; + int 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 (!xf86XVClipVideoHelper(&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; + + dstPitch = ((width << 1) + 15) & ~15; + new_size = ((dstPitch * height) + bpp - 1) / bpp; + + pPriv->doubleBuffer = (pScrn->currentMode->Flags & V_DBLSCAN) != V_DBLSCAN; + + 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(!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) { + REGION_COPY(pScrn->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) { + 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, size, bpp; + OffscreenPrivPtr pPriv; + + if((w > 1024) || (h > 1024)) + return BadAlloc; + + w = (w + 1) & ~1; + pitch = ((w << 1) + 15) & ~15; + bpp = pScrn->bitsPerPixel >> 3; + size = ((pitch * h) + bpp - 1) / bpp; + + if(!(linear = CHIPSAllocateMemory(pScrn, NULL, size))) + return BadAlloc; + + surface->width = w; + surface->height = h; + + if(!(surface->pitches = malloc(sizeof(int)))) { + xf86FreeOffscreenLinear(linear); + return BadAlloc; + } + if(!(surface->offsets = malloc(sizeof(int)))) { + free(surface->pitches); + xf86FreeOffscreenLinear(linear); + return BadAlloc; + } + if(!(pPriv = malloc(sizeof(OffscreenPrivRec)))) { + free(surface->pitches); + free(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); + free(surface->pitches); + free(surface->offsets); + free(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(!xf86XVClipVideoHelper(&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 = malloc(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); +} diff --git a/hw/xfree86/drivers/video/chips/util/AsmMacros.h b/hw/xfree86/drivers/video/chips/util/AsmMacros.h new file mode 100644 index 0000000000..aede90b6e9 --- /dev/null +++ b/hw/xfree86/drivers/video/chips/util/AsmMacros.h @@ -0,0 +1,338 @@ +/* + * (c) Copyright 1993,1994 by David Wexelblat + * + * 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. + * + */ + + +#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(unsigned long port, char val) +{ + __asm__ __volatile__("stba %0, [%1] %2" : : "r" (val), "r" (port), "i" (ASI_PL)); +} + +static __inline__ void +outw(unsigned long port, char val) +{ + __asm__ __volatile__("stha %0, [%1] %2" : : "r" (val), "r" (port), "i" (ASI_PL)); +} + +static __inline__ void +outl(unsigned long port, char val) +{ + __asm__ __volatile__("sta %0, [%1] %2" : : "r" (val), "r" (port), "i" (ASI_PL)); +} + +static __inline__ unsigned int +inb(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(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(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(short port, char val) +{ + if ((unsigned short)port >= 0x400) return; + + *(volatile unsigned char*)(((unsigned short)(port))+IOPortBase) = val; +} + +static __inline__ void +outw(short port, short val) +{ + if ((unsigned short)port >= 0x400) return; + + *(volatile unsigned short*)(((unsigned short)(port))+IOPortBase) = val; +} + +static __inline__ void +outl(short port, int val) +{ + if ((unsigned short)port >= 0x400) return; + + *(volatile unsigned long*)(((unsigned short)(port))+IOPortBase) = val; +} + +static __inline__ unsigned int +inb(short port) +{ + if ((unsigned short)port >= 0x400) return((unsigned int)-1); + + return(*(volatile unsigned char*)(((unsigned short)(port))+IOPortBase)); +} + +static __inline__ unsigned int +inw(short port) +{ + if ((unsigned short)port >= 0x400) return((unsigned int)-1); + + return(*(volatile unsigned short*)(((unsigned short)(port))+IOPortBase)); +} + +static __inline__ unsigned int +inl(short port) +{ + if ((unsigned short)port >= 0x400) return((unsigned int)-1); + + return(*(volatile unsigned long*)(((unsigned short)(port))+IOPortBase)); +} +#else /* __arm32__ */ +#if defined(__FreeBSD__) && defined(__alpha__) + +#include + +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(short port, char val) +{ + __asm__ __volatile__("outb %0,%1" : :"a" (val), "d" (port)); +} + +static __inline__ void +outw(short portm, short val) +{ + __asm__ __volatile__("outw %0,%1" : :"a" (val), "d" (port)); +} + +static __inline__ void +outl(short port, unsigned int val) +{ + __asm__ __volatile__("outl %0,%1" : :"a" (val), "d" (port)); +} + +static __inline__ unsigned int +inb(short port) +{ + unsigned char ret; + __asm__ __volatile__("inb %1,%0" : + "=a" (ret) : + "d" (port)); + return ret; +} + +static __inline__ unsigned int +inw(short port) +{ + unsigned short ret; + __asm__ __volatile__("inw %1,%0" : + "=a" (ret) : + "d" (port)); + return ret; +} + +static __inline__ unsigned int +inl(short port) +{ + unsigned int ret; + __asm__ __volatile__("inl %1,%0" : + "=a" (ret) : + "d" (port)); + return ret; +} + +#else /* GCCUSESGAS */ + +static __inline__ void +outb(short port, char val) +{ + __asm__ __volatile__("out%B0 (%1)" : :"a" (val), "d" (port)); +} + +static __inline__ void +outw(short port, short val) +{ + __asm__ __volatile__("out%W0 (%1)" : :"a" (val), "d" (port)); +} + +static __inline__ void +outl(short port, unsigned int val) +{ + __asm__ __volatile__("out%L0 (%1)" : :"a" (val), "d" (port)); +} + +static __inline__ unsigned int +inb(short port) +{ + unsigned int ret; + __asm__ __volatile__("in%B0 (%1)" : + "=a" (ret) : + "d" (port)); + return ret; +} + +static __inline__ unsigned int +inw(short port) +{ + unsigned int ret; + __asm__ __volatile__("in%W0 (%1)" : + "=a" (ret) : + "d" (port)); + return ret; +} + +static __inline__ unsigned int +inl(short port) +{ + unsigned int ret; + __asm__ __volatile__("in%L0 (%1)" : + "=a" (ret) : + "d" (port)); + return ret; +} + +#endif /* GCCUSESGAS */ +#endif /* arm32 */ +#endif /* linux && __sparc__ */ +#endif /* linux && __alpha__ */ +#endif /* __FreeBSD__ && __alpha__ */ + +#if defined(linux) || defined(__arm32__) + +#define intr_disable() +#define intr_enable() + +#else + +static __inline__ void +intr_disable(void) +{ + __asm__ __volatile__("cli"); +} + +static __inline__ void +intr_enable(void) +{ + __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) +# define asm __asm +# endif +# ifdef SVR4 +# include +# endif +# include +# define intr_disable() asm("cli") +# define intr_enable() asm("sti") + +#endif /* _MINIX and _ACK */ +#endif /* __GNUC__ */ diff --git a/hw/xfree86/drivers/video/chips/util/dRegs.c b/hw/xfree86/drivers/video/chips/util/dRegs.c new file mode 100644 index 0000000000..0d2f0cb4d1 --- /dev/null +++ b/hw/xfree86/drivers/video/chips/util/dRegs.c @@ -0,0 +1,248 @@ +#include +#include +#include + +#include "iopl.h" + +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/hw/xfree86/drivers/video/chips/util/iopl.h b/hw/xfree86/drivers/video/chips/util/iopl.h new file mode 100644 index 0000000000..a0440dedd6 --- /dev/null +++ b/hw/xfree86/drivers/video/chips/util/iopl.h @@ -0,0 +1,46 @@ +#ifdef __NetBSD__ +# include +# include +# include +#else +# if defined(__linux__) +/* Can't because provides conflicting inb, outb, etc + * # include + */ +int iopl(int level); +# endif +# if defined(SVR4) && defined(i386) && defined(sun) +# include +# include +# include +# include +# endif +# include "AsmMacros.h" +#endif /* NetBSD */ + +#include +#include +#include + +#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 diff --git a/hw/xfree86/drivers/video/chips/util/mRegs.c b/hw/xfree86/drivers/video/chips/util/mRegs.c new file mode 100644 index 0000000000..843d01db4e --- /dev/null +++ b/hw/xfree86/drivers/video/chips/util/mRegs.c @@ -0,0 +1,129 @@ +#include +#include +#include + +#include "iopl.h" + +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/hw/xfree86/drivers/video/chips/util/modClock.c b/hw/xfree86/drivers/video/chips/util/modClock.c new file mode 100644 index 0000000000..d77ada05ad --- /dev/null +++ b/hw/xfree86/drivers/video/chips/util/modClock.c @@ -0,0 +1,356 @@ +#include +#include +#include + +#include + +#include "iopl.h" + +#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 + +static 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 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 + + 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; +} + +static 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; +} + +static 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; + if (! fnmatch("*memClock",argv[0],FNM_PATHNAME)) { + 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; + } + } +}